//===-- LICM.cpp - Loop Invariant Code Motion Pass ------------------------===//
//
// 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 pass performs loop invariant code motion, attempting to remove as much
// code from the body of a loop as possible.  It does this by either hoisting
// code into the preheader block, or by sinking code to the exit blocks if it is
// safe.  This pass also promotes must-aliased memory locations in the loop to
// live in registers, thus hoisting and sinking "invariant" loads and stores.
//
// Hoisting operations out of loops is a canonicalization transform.  It
// enables and simplifies subsequent optimizations in the middle-end.
// Rematerialization of hoisted instructions to reduce register pressure is the
// responsibility of the back-end, which has more accurate information about
// register pressure and also handles other optimizations than LICM that
// increase live-ranges.
//
// This pass uses alias analysis for two purposes:
//
//  1. Moving loop invariant loads and calls out of loops.  If we can determine
//     that a load or call inside of a loop never aliases anything stored to,
//     we can hoist it or sink it like any other instruction.
//  2. Scalar Promotion of Memory - If there is a store instruction inside of
//     the loop, we try to move the store to happen AFTER the loop instead of
//     inside of the loop.  This can only happen if a few conditions are true:
//       A. The pointer stored through is loop invariant
//       B. There are no stores or loads in the loop which _may_ alias the
//          pointer.  There are no calls in the loop which mod/ref the pointer.
//     If these conditions are true, we can promote the loads and stores in the
//     loop of the pointer to use a temporary alloca'd variable.  We then use
//     the SSAUpdater to construct the appropriate SSA form for the value.
//
//===----------------------------------------------------------------------===//

#include "llvm/Transforms/Scalar/LICM.h"
#include "llvm/ADT/PriorityWorklist.h"
#include "llvm/ADT/SetOperations.h"
#include "llvm/ADT/Statistic.h"
#include "llvm/Analysis/AliasAnalysis.h"
#include "llvm/Analysis/AliasSetTracker.h"
#include "llvm/Analysis/AssumptionCache.h"
#include "llvm/Analysis/CaptureTracking.h"
#include "llvm/Analysis/DomTreeUpdater.h"
#include "llvm/Analysis/GuardUtils.h"
#include "llvm/Analysis/LazyBlockFrequencyInfo.h"
#include "llvm/Analysis/Loads.h"
#include "llvm/Analysis/LoopInfo.h"
#include "llvm/Analysis/LoopIterator.h"
#include "llvm/Analysis/LoopNestAnalysis.h"
#include "llvm/Analysis/LoopPass.h"
#include "llvm/Analysis/MemorySSA.h"
#include "llvm/Analysis/MemorySSAUpdater.h"
#include "llvm/Analysis/MustExecute.h"
#include "llvm/Analysis/OptimizationRemarkEmitter.h"
#include "llvm/Analysis/ScalarEvolution.h"
#include "llvm/Analysis/TargetLibraryInfo.h"
#include "llvm/Analysis/TargetTransformInfo.h"
#include "llvm/Analysis/ValueTracking.h"
#include "llvm/IR/CFG.h"
#include "llvm/IR/Constants.h"
#include "llvm/IR/DataLayout.h"
#include "llvm/IR/DebugInfoMetadata.h"
#include "llvm/IR/DerivedTypes.h"
#include "llvm/IR/Dominators.h"
#include "llvm/IR/IRBuilder.h"
#include "llvm/IR/Instructions.h"
#include "llvm/IR/IntrinsicInst.h"
#include "llvm/IR/LLVMContext.h"
#include "llvm/IR/Metadata.h"
#include "llvm/IR/PatternMatch.h"
#include "llvm/IR/PredIteratorCache.h"
#include "llvm/InitializePasses.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/Transforms/Scalar.h"
#include "llvm/Transforms/Utils/AssumeBundleBuilder.h"
#include "llvm/Transforms/Utils/BasicBlockUtils.h"
#include "llvm/Transforms/Utils/Local.h"
#include "llvm/Transforms/Utils/LoopUtils.h"
#include "llvm/Transforms/Utils/SSAUpdater.h"
#include <algorithm>
#include <utility>
using namespace llvm;

namespace llvm {
class LPMUpdater;
} // namespace llvm

#define DEBUG_TYPE "licm"

STATISTIC(NumCreatedBlocks, "Number of blocks created");
STATISTIC(NumClonedBranches, "Number of branches cloned");
STATISTIC(NumSunk, "Number of instructions sunk out of loop");
STATISTIC(NumHoisted, "Number of instructions hoisted out of loop");
STATISTIC(NumMovedLoads, "Number of load insts hoisted or sunk");
STATISTIC(NumMovedCalls, "Number of call insts hoisted or sunk");
STATISTIC(NumPromotionCandidates, "Number of promotion candidates");
STATISTIC(NumLoadPromoted, "Number of load-only promotions");
STATISTIC(NumLoadStorePromoted, "Number of load and store promotions");
STATISTIC(NumMinMaxHoisted,
          "Number of min/max expressions hoisted out of the loop");
STATISTIC(NumGEPsHoisted,
          "Number of geps reassociated and hoisted out of the loop");
STATISTIC(NumAddSubHoisted, "Number of add/subtract expressions reassociated "
                            "and hoisted out of the loop");
STATISTIC(NumFPAssociationsHoisted, "Number of invariant FP expressions "
                                    "reassociated and hoisted out of the loop");
STATISTIC(NumIntAssociationsHoisted,
          "Number of invariant int expressions "
          "reassociated and hoisted out of the loop");
STATISTIC(NumBOAssociationsHoisted, "Number of invariant BinaryOp expressions "
                                    "reassociated and hoisted out of the loop");

/// Memory promotion is enabled by default.
static cl::opt<bool>
    DisablePromotion("disable-licm-promotion", cl::Hidden, cl::init(false),
                     cl::desc("Disable memory promotion in LICM pass"));

static cl::opt<bool> ControlFlowHoisting(
    "licm-control-flow-hoisting", cl::Hidden, cl::init(false),
    cl::desc("Enable control flow (and PHI) hoisting in LICM"));

static cl::opt<bool>
    SingleThread("licm-force-thread-model-single", cl::Hidden, cl::init(false),
                 cl::desc("Force thread model single in LICM pass"));

static cl::opt<uint32_t> MaxNumUsesTraversed(
    "licm-max-num-uses-traversed", cl::Hidden, cl::init(8),
    cl::desc("Max num uses visited for identifying load "
             "invariance in loop using invariant start (default = 8)"));

static cl::opt<unsigned> FPAssociationUpperLimit(
    "licm-max-num-fp-reassociations", cl::init(5U), cl::Hidden,
    cl::desc(
        "Set upper limit for the number of transformations performed "
        "during a single round of hoisting the reassociated expressions."));

static cl::opt<unsigned> IntAssociationUpperLimit(
    "licm-max-num-int-reassociations", cl::init(5U), cl::Hidden,
    cl::desc(
        "Set upper limit for the number of transformations performed "
        "during a single round of hoisting the reassociated expressions."));

// Experimental option to allow imprecision in LICM in pathological cases, in
// exchange for faster compile. This is to be removed if MemorySSA starts to
// address the same issue. LICM calls MemorySSAWalker's
// getClobberingMemoryAccess, up to the value of the Cap, getting perfect
// accuracy. Afterwards, LICM will call into MemorySSA's getDefiningAccess,
// which may not be precise, since optimizeUses is capped. The result is
// correct, but we may not get as "far up" as possible to get which access is
// clobbering the one queried.
cl::opt<unsigned> llvm::SetLicmMssaOptCap(
    "licm-mssa-optimization-cap", cl::init(100), cl::Hidden,
    cl::desc("Enable imprecision in LICM in pathological cases, in exchange "
             "for faster compile. Caps the MemorySSA clobbering calls."));

// Experimentally, memory promotion carries less importance than sinking and
// hoisting. Limit when we do promotion when using MemorySSA, in order to save
// compile time.
cl::opt<unsigned> llvm::SetLicmMssaNoAccForPromotionCap(
    "licm-mssa-max-acc-promotion", cl::init(250), cl::Hidden,
    cl::desc("[LICM & MemorySSA] When MSSA in LICM is disabled, this has no "
             "effect. When MSSA in LICM is enabled, then this is the maximum "
             "number of accesses allowed to be present in a loop in order to "
             "enable memory promotion."));

static bool inSubLoop(BasicBlock *BB, Loop *CurLoop, LoopInfo *LI);
static bool isNotUsedOrFoldableInLoop(const Instruction &I, const Loop *CurLoop,
                                      const LoopSafetyInfo *SafetyInfo,
                                      TargetTransformInfo *TTI,
                                      bool &FoldableInLoop, bool LoopNestMode);
static void hoist(Instruction &I, const DominatorTree *DT, const Loop *CurLoop,
                  BasicBlock *Dest, ICFLoopSafetyInfo *SafetyInfo,
                  MemorySSAUpdater &MSSAU, ScalarEvolution *SE,
                  OptimizationRemarkEmitter *ORE);
static bool sink(Instruction &I, LoopInfo *LI, DominatorTree *DT,
                 const Loop *CurLoop, ICFLoopSafetyInfo *SafetyInfo,
                 MemorySSAUpdater &MSSAU, OptimizationRemarkEmitter *ORE);
static bool isSafeToExecuteUnconditionally(
    Instruction &Inst, const DominatorTree *DT, const TargetLibraryInfo *TLI,
    const Loop *CurLoop, const LoopSafetyInfo *SafetyInfo,
    OptimizationRemarkEmitter *ORE, const Instruction *CtxI,
    AssumptionCache *AC, bool AllowSpeculation);
static bool noConflictingReadWrites(Instruction *I, MemorySSA *MSSA,
                                    AAResults *AA, Loop *CurLoop,
                                    SinkAndHoistLICMFlags &Flags);
static bool pointerInvalidatedByLoop(MemorySSA *MSSA, MemoryUse *MU,
                                     Loop *CurLoop, Instruction &I,
                                     SinkAndHoistLICMFlags &Flags,
                                     bool InvariantGroup);
static bool pointerInvalidatedByBlock(BasicBlock &BB, MemorySSA &MSSA,
                                      MemoryUse &MU);
/// Aggregates various functions for hoisting computations out of loop.
static bool hoistArithmetics(Instruction &I, Loop &L,
                             ICFLoopSafetyInfo &SafetyInfo,
                             MemorySSAUpdater &MSSAU, AssumptionCache *AC,
                             DominatorTree *DT);
static Instruction *cloneInstructionInExitBlock(
    Instruction &I, BasicBlock &ExitBlock, PHINode &PN, const LoopInfo *LI,
    const LoopSafetyInfo *SafetyInfo, MemorySSAUpdater &MSSAU);

static void eraseInstruction(Instruction &I, ICFLoopSafetyInfo &SafetyInfo,
                             MemorySSAUpdater &MSSAU);

static void moveInstructionBefore(Instruction &I, BasicBlock::iterator Dest,
                                  ICFLoopSafetyInfo &SafetyInfo,
                                  MemorySSAUpdater &MSSAU, ScalarEvolution *SE);

static void foreachMemoryAccess(MemorySSA *MSSA, Loop *L,
                                function_ref<void(Instruction *)> Fn);
using PointersAndHasReadsOutsideSet =
    std::pair<SmallSetVector<Value *, 8>, bool>;
static SmallVector<PointersAndHasReadsOutsideSet, 0>
collectPromotionCandidates(MemorySSA *MSSA, AliasAnalysis *AA, Loop *L);

namespace {
struct LoopInvariantCodeMotion {
  bool runOnLoop(Loop *L, AAResults *AA, LoopInfo *LI, DominatorTree *DT,
                 AssumptionCache *AC, TargetLibraryInfo *TLI,
                 TargetTransformInfo *TTI, ScalarEvolution *SE, MemorySSA *MSSA,
                 OptimizationRemarkEmitter *ORE, bool LoopNestMode = false);

  LoopInvariantCodeMotion(unsigned LicmMssaOptCap,
                          unsigned LicmMssaNoAccForPromotionCap,
                          bool LicmAllowSpeculation)
      : LicmMssaOptCap(LicmMssaOptCap),
        LicmMssaNoAccForPromotionCap(LicmMssaNoAccForPromotionCap),
        LicmAllowSpeculation(LicmAllowSpeculation) {}

private:
  unsigned LicmMssaOptCap;
  unsigned LicmMssaNoAccForPromotionCap;
  bool LicmAllowSpeculation;
};

struct LegacyLICMPass : public LoopPass {
  static char ID; // Pass identification, replacement for typeid
  LegacyLICMPass(
      unsigned LicmMssaOptCap = SetLicmMssaOptCap,
      unsigned LicmMssaNoAccForPromotionCap = SetLicmMssaNoAccForPromotionCap,
      bool LicmAllowSpeculation = true)
      : LoopPass(ID), LICM(LicmMssaOptCap, LicmMssaNoAccForPromotionCap,
                           LicmAllowSpeculation) {
    initializeLegacyLICMPassPass(*PassRegistry::getPassRegistry());
  }

  bool runOnLoop(Loop *L, LPPassManager &LPM) override {
    if (skipLoop(L))
      return false;

    LLVM_DEBUG(dbgs() << "Perform LICM on Loop with header at block "
                      << L->getHeader()->getNameOrAsOperand() << "\n");

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

    auto *SE = getAnalysisIfAvailable<ScalarEvolutionWrapperPass>();
    MemorySSA *MSSA = &getAnalysis<MemorySSAWrapperPass>().getMSSA();
    // For the old PM, we can't use OptimizationRemarkEmitter as an analysis
    // pass. Function analyses need to be preserved across loop transformations
    // but ORE cannot be preserved (see comment before the pass definition).
    OptimizationRemarkEmitter ORE(L->getHeader()->getParent());
    return LICM.runOnLoop(
        L, &getAnalysis<AAResultsWrapperPass>().getAAResults(),
        &getAnalysis<LoopInfoWrapperPass>().getLoopInfo(),
        &getAnalysis<DominatorTreeWrapperPass>().getDomTree(),
        &getAnalysis<AssumptionCacheTracker>().getAssumptionCache(*F),
        &getAnalysis<TargetLibraryInfoWrapperPass>().getTLI(*F),
        &getAnalysis<TargetTransformInfoWrapperPass>().getTTI(*F),
        SE ? &SE->getSE() : nullptr, MSSA, &ORE);
  }

  /// This transformation requires natural loop information & requires that
  /// loop preheaders be inserted into the CFG...
  ///
  void getAnalysisUsage(AnalysisUsage &AU) const override {
    AU.addPreserved<DominatorTreeWrapperPass>();
    AU.addPreserved<LoopInfoWrapperPass>();
    AU.addRequired<TargetLibraryInfoWrapperPass>();
    AU.addRequired<MemorySSAWrapperPass>();
    AU.addPreserved<MemorySSAWrapperPass>();
    AU.addRequired<TargetTransformInfoWrapperPass>();
    AU.addRequired<AssumptionCacheTracker>();
    getLoopAnalysisUsage(AU);
    LazyBlockFrequencyInfoPass::getLazyBFIAnalysisUsage(AU);
    AU.addPreserved<LazyBlockFrequencyInfoPass>();
    AU.addPreserved<LazyBranchProbabilityInfoPass>();
  }

private:
  LoopInvariantCodeMotion LICM;
};
} // namespace

PreservedAnalyses LICMPass::run(Loop &L, LoopAnalysisManager &AM,
                                LoopStandardAnalysisResults &AR, LPMUpdater &) {
  if (!AR.MSSA)
    reportFatalUsageError("LICM requires MemorySSA (loop-mssa)");

  // For the new PM, we also can't use OptimizationRemarkEmitter as an analysis
  // pass.  Function analyses need to be preserved across loop transformations
  // but ORE cannot be preserved (see comment before the pass definition).
  OptimizationRemarkEmitter ORE(L.getHeader()->getParent());

  LoopInvariantCodeMotion LICM(Opts.MssaOptCap, Opts.MssaNoAccForPromotionCap,
                               Opts.AllowSpeculation);
  if (!LICM.runOnLoop(&L, &AR.AA, &AR.LI, &AR.DT, &AR.AC, &AR.TLI, &AR.TTI,
                      &AR.SE, AR.MSSA, &ORE))
    return PreservedAnalyses::all();

  auto PA = getLoopPassPreservedAnalyses();
  PA.preserve<MemorySSAAnalysis>();

  return PA;
}

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

  OS << '<';
  OS << (Opts.AllowSpeculation ? "" : "no-") << "allowspeculation";
  OS << '>';
}

PreservedAnalyses LNICMPass::run(LoopNest &LN, LoopAnalysisManager &AM,
                                 LoopStandardAnalysisResults &AR,
                                 LPMUpdater &) {
  if (!AR.MSSA)
    reportFatalUsageError("LNICM requires MemorySSA (loop-mssa)");

  // For the new PM, we also can't use OptimizationRemarkEmitter as an analysis
  // pass.  Function analyses need to be preserved across loop transformations
  // but ORE cannot be preserved (see comment before the pass definition).
  OptimizationRemarkEmitter ORE(LN.getParent());

  LoopInvariantCodeMotion LICM(Opts.MssaOptCap, Opts.MssaNoAccForPromotionCap,
                               Opts.AllowSpeculation);

  Loop &OutermostLoop = LN.getOutermostLoop();
  bool Changed = LICM.runOnLoop(&OutermostLoop, &AR.AA, &AR.LI, &AR.DT, &AR.AC,
                                &AR.TLI, &AR.TTI, &AR.SE, AR.MSSA, &ORE, true);

  if (!Changed)
    return PreservedAnalyses::all();

  auto PA = getLoopPassPreservedAnalyses();

  PA.preserve<DominatorTreeAnalysis>();
  PA.preserve<LoopAnalysis>();
  PA.preserve<MemorySSAAnalysis>();

  return PA;
}

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

  OS << '<';
  OS << (Opts.AllowSpeculation ? "" : "no-") << "allowspeculation";
  OS << '>';
}

char LegacyLICMPass::ID = 0;
INITIALIZE_PASS_BEGIN(LegacyLICMPass, "licm", "Loop Invariant Code Motion",
                      false, false)
INITIALIZE_PASS_DEPENDENCY(LoopPass)
INITIALIZE_PASS_DEPENDENCY(TargetLibraryInfoWrapperPass)
INITIALIZE_PASS_DEPENDENCY(TargetTransformInfoWrapperPass)
INITIALIZE_PASS_DEPENDENCY(MemorySSAWrapperPass)
INITIALIZE_PASS_DEPENDENCY(LazyBFIPass)
INITIALIZE_PASS_END(LegacyLICMPass, "licm", "Loop Invariant Code Motion", false,
                    false)

Pass *llvm::createLICMPass() { return new LegacyLICMPass(); }

llvm::SinkAndHoistLICMFlags::SinkAndHoistLICMFlags(bool IsSink, Loop &L,
                                                   MemorySSA &MSSA)
    : SinkAndHoistLICMFlags(SetLicmMssaOptCap, SetLicmMssaNoAccForPromotionCap,
                            IsSink, L, MSSA) {}

llvm::SinkAndHoistLICMFlags::SinkAndHoistLICMFlags(
    unsigned LicmMssaOptCap, unsigned LicmMssaNoAccForPromotionCap, bool IsSink,
    Loop &L, MemorySSA &MSSA)
    : LicmMssaOptCap(LicmMssaOptCap),
      LicmMssaNoAccForPromotionCap(LicmMssaNoAccForPromotionCap),
      IsSink(IsSink) {
  unsigned AccessCapCount = 0;
  for (auto *BB : L.getBlocks())
    if (const auto *Accesses = MSSA.getBlockAccesses(BB))
      for (const auto &MA : *Accesses) {
        (void)MA;
        ++AccessCapCount;
        if (AccessCapCount > LicmMssaNoAccForPromotionCap) {
          NoOfMemAccTooLarge = true;
          return;
        }
      }
}

/// Hoist expressions out of the specified loop. Note, alias info for inner
/// loop is not preserved so it is not a good idea to run LICM multiple
/// times on one loop.
bool LoopInvariantCodeMotion::runOnLoop(Loop *L, AAResults *AA, LoopInfo *LI,
                                        DominatorTree *DT, AssumptionCache *AC,
                                        TargetLibraryInfo *TLI,
                                        TargetTransformInfo *TTI,
                                        ScalarEvolution *SE, MemorySSA *MSSA,
                                        OptimizationRemarkEmitter *ORE,
                                        bool LoopNestMode) {
  bool Changed = false;

  assert(L->isLCSSAForm(*DT) && "Loop is not in LCSSA form.");

  // If this loop has metadata indicating that LICM is not to be performed then
  // just exit.
  if (hasDisableLICMTransformsHint(L)) {
    return false;
  }

  // Don't sink stores from loops with coroutine suspend instructions.
  // LICM would sink instructions into the default destination of
  // the coroutine switch. The default destination of the switch is to
  // handle the case where the coroutine is suspended, by which point the
  // coroutine frame may have been destroyed. No instruction can be sunk there.
  // FIXME: This would unfortunately hurt the performance of coroutines, however
  // there is currently no general solution for this. Similar issues could also
  // potentially happen in other passes where instructions are being moved
  // across that edge.
  bool HasCoroSuspendInst = llvm::any_of(L->getBlocks(), [](BasicBlock *BB) {
    return llvm::any_of(*BB, [](Instruction &I) {
      IntrinsicInst *II = dyn_cast<IntrinsicInst>(&I);
      return II && II->getIntrinsicID() == Intrinsic::coro_suspend;
    });
  });

  MemorySSAUpdater MSSAU(MSSA);
  SinkAndHoistLICMFlags Flags(LicmMssaOptCap, LicmMssaNoAccForPromotionCap,
                              /*IsSink=*/true, *L, *MSSA);

  // Get the preheader block to move instructions into...
  BasicBlock *Preheader = L->getLoopPreheader();

  // Compute loop safety information.
  ICFLoopSafetyInfo SafetyInfo;
  SafetyInfo.computeLoopSafetyInfo(L);

  // We want to visit all of the instructions in this loop... that are not parts
  // of our subloops (they have already had their invariants hoisted out of
  // their loop, into this loop, so there is no need to process the BODIES of
  // the subloops).
  //
  // Traverse the body of the loop in depth first order on the dominator tree so
  // that we are guaranteed to see definitions before we see uses.  This allows
  // us to sink instructions in one pass, without iteration.  After sinking
  // instructions, we perform another pass to hoist them out of the loop.
  if (L->hasDedicatedExits())
    Changed |=
        LoopNestMode
            ? sinkRegionForLoopNest(DT->getNode(L->getHeader()), AA, LI, DT,
                                    TLI, TTI, L, MSSAU, &SafetyInfo, Flags, ORE)
            : sinkRegion(DT->getNode(L->getHeader()), AA, LI, DT, TLI, TTI, L,
                         MSSAU, &SafetyInfo, Flags, ORE);
  Flags.setIsSink(false);
  if (Preheader)
    Changed |= hoistRegion(DT->getNode(L->getHeader()), AA, LI, DT, AC, TLI, L,
                           MSSAU, SE, &SafetyInfo, Flags, ORE, LoopNestMode,
                           LicmAllowSpeculation);

  // Now that all loop invariants have been removed from the loop, promote any
  // memory references to scalars that we can.
  // Don't sink stores from loops without dedicated block exits. Exits
  // containing indirect branches are not transformed by loop simplify,
  // make sure we catch that. An additional load may be generated in the
  // preheader for SSA updater, so also avoid sinking when no preheader
  // is available.
  if (!DisablePromotion && Preheader && L->hasDedicatedExits() &&
      !Flags.tooManyMemoryAccesses() && !HasCoroSuspendInst) {
    // Figure out the loop exits and their insertion points
    SmallVector<BasicBlock *, 8> ExitBlocks;
    L->getUniqueExitBlocks(ExitBlocks);

    // We can't insert into a catchswitch.
    bool HasCatchSwitch = llvm::any_of(ExitBlocks, [](BasicBlock *Exit) {
      return isa<CatchSwitchInst>(Exit->getTerminator());
    });

    if (!HasCatchSwitch) {
      SmallVector<BasicBlock::iterator, 8> InsertPts;
      SmallVector<MemoryAccess *, 8> MSSAInsertPts;
      InsertPts.reserve(ExitBlocks.size());
      MSSAInsertPts.reserve(ExitBlocks.size());
      for (BasicBlock *ExitBlock : ExitBlocks) {
        InsertPts.push_back(ExitBlock->getFirstInsertionPt());
        MSSAInsertPts.push_back(nullptr);
      }

      PredIteratorCache PIC;

      // Promoting one set of accesses may make the pointers for another set
      // loop invariant, so run this in a loop.
      bool Promoted = false;
      bool LocalPromoted;
      do {
        LocalPromoted = false;
        for (auto [PointerMustAliases, HasReadsOutsideSet] :
             collectPromotionCandidates(MSSA, AA, L)) {
          LocalPromoted |= promoteLoopAccessesToScalars(
              PointerMustAliases, ExitBlocks, InsertPts, MSSAInsertPts, PIC, LI,
              DT, AC, TLI, TTI, L, MSSAU, &SafetyInfo, ORE,
              LicmAllowSpeculation, HasReadsOutsideSet);
        }
        Promoted |= LocalPromoted;
      } while (LocalPromoted);

      // Once we have promoted values across the loop body we have to
      // recursively reform LCSSA as any nested loop may now have values defined
      // within the loop used in the outer loop.
      // FIXME: This is really heavy handed. It would be a bit better to use an
      // SSAUpdater strategy during promotion that was LCSSA aware and reformed
      // it as it went.
      if (Promoted)
        formLCSSARecursively(*L, *DT, LI, SE);

      Changed |= Promoted;
    }
  }

  // Check that neither this loop nor its parent have had LCSSA broken. LICM is
  // specifically moving instructions across the loop boundary and so it is
  // especially in need of basic functional correctness checking here.
  assert(L->isLCSSAForm(*DT) && "Loop not left in LCSSA form after LICM!");
  assert((L->isOutermost() || L->getParentLoop()->isLCSSAForm(*DT)) &&
         "Parent loop not left in LCSSA form after LICM!");

  if (VerifyMemorySSA)
    MSSA->verifyMemorySSA();

  if (Changed && SE)
    SE->forgetLoopDispositions();
  return Changed;
}

/// Walk the specified region of the CFG (defined by all blocks dominated by
/// the specified block, and that are in the current loop) in reverse depth
/// first order w.r.t the DominatorTree.  This allows us to visit uses before
/// definitions, allowing us to sink a loop body in one pass without iteration.
///
bool llvm::sinkRegion(DomTreeNode *N, AAResults *AA, LoopInfo *LI,
                      DominatorTree *DT, TargetLibraryInfo *TLI,
                      TargetTransformInfo *TTI, Loop *CurLoop,
                      MemorySSAUpdater &MSSAU, ICFLoopSafetyInfo *SafetyInfo,
                      SinkAndHoistLICMFlags &Flags,
                      OptimizationRemarkEmitter *ORE, Loop *OutermostLoop) {

  // Verify inputs.
  assert(N != nullptr && AA != nullptr && LI != nullptr && DT != nullptr &&
         CurLoop != nullptr && SafetyInfo != nullptr &&
         "Unexpected input to sinkRegion.");

  // We want to visit children before parents. We will enqueue all the parents
  // before their children in the worklist and process the worklist in reverse
  // order.
  SmallVector<BasicBlock *, 16> Worklist =
      collectChildrenInLoop(DT, N, CurLoop);

  bool Changed = false;
  for (BasicBlock *BB : reverse(Worklist)) {
    // subloop (which would already have been processed).
    if (inSubLoop(BB, CurLoop, LI))
      continue;

    for (BasicBlock::iterator II = BB->end(); II != BB->begin();) {
      Instruction &I = *--II;

      // The instruction is not used in the loop if it is dead.  In this case,
      // we just delete it instead of sinking it.
      if (isInstructionTriviallyDead(&I, TLI)) {
        LLVM_DEBUG(dbgs() << "LICM deleting dead inst: " << I << '\n');
        salvageKnowledge(&I);
        salvageDebugInfo(I);
        ++II;
        eraseInstruction(I, *SafetyInfo, MSSAU);
        Changed = true;
        continue;
      }

      // Check to see if we can sink this instruction to the exit blocks
      // of the loop.  We can do this if the all users of the instruction are
      // outside of the loop.  In this case, it doesn't even matter if the
      // operands of the instruction are loop invariant.
      //
      bool FoldableInLoop = false;
      bool LoopNestMode = OutermostLoop != nullptr;
      if (!I.mayHaveSideEffects() &&
          isNotUsedOrFoldableInLoop(I, LoopNestMode ? OutermostLoop : CurLoop,
                                    SafetyInfo, TTI, FoldableInLoop,
                                    LoopNestMode) &&
          canSinkOrHoistInst(I, AA, DT, CurLoop, MSSAU, true, Flags, ORE)) {
        if (sink(I, LI, DT, CurLoop, SafetyInfo, MSSAU, ORE)) {
          if (!FoldableInLoop) {
            ++II;
            salvageDebugInfo(I);
            eraseInstruction(I, *SafetyInfo, MSSAU);
          }
          Changed = true;
        }
      }
    }
  }
  if (VerifyMemorySSA)
    MSSAU.getMemorySSA()->verifyMemorySSA();
  return Changed;
}

bool llvm::sinkRegionForLoopNest(DomTreeNode *N, AAResults *AA, LoopInfo *LI,
                                 DominatorTree *DT, TargetLibraryInfo *TLI,
                                 TargetTransformInfo *TTI, Loop *CurLoop,
                                 MemorySSAUpdater &MSSAU,
                                 ICFLoopSafetyInfo *SafetyInfo,
                                 SinkAndHoistLICMFlags &Flags,
                                 OptimizationRemarkEmitter *ORE) {

  bool Changed = false;
  SmallPriorityWorklist<Loop *, 4> Worklist;
  Worklist.insert(CurLoop);
  appendLoopsToWorklist(*CurLoop, Worklist);
  while (!Worklist.empty()) {
    Loop *L = Worklist.pop_back_val();
    Changed |= sinkRegion(DT->getNode(L->getHeader()), AA, LI, DT, TLI, TTI, L,
                          MSSAU, SafetyInfo, Flags, ORE, CurLoop);
  }
  return Changed;
}

namespace {
// This is a helper class for hoistRegion to make it able to hoist control flow
// in order to be able to hoist phis. The way this works is that we initially
// start hoisting to the loop preheader, and when we see a loop invariant branch
// we make note of this. When we then come to hoist an instruction that's
// conditional on such a branch we duplicate the branch and the relevant control
// flow, then hoist the instruction into the block corresponding to its original
// block in the duplicated control flow.
class ControlFlowHoister {
private:
  // Information about the loop we are hoisting from
  LoopInfo *LI;
  DominatorTree *DT;
  Loop *CurLoop;
  MemorySSAUpdater &MSSAU;

  // A map of blocks in the loop to the block their instructions will be hoisted
  // to.
  DenseMap<BasicBlock *, BasicBlock *> HoistDestinationMap;

  // The branches that we can hoist, mapped to the block that marks a
  // convergence point of their control flow.
  DenseMap<BranchInst *, BasicBlock *> HoistableBranches;

public:
  ControlFlowHoister(LoopInfo *LI, DominatorTree *DT, Loop *CurLoop,
                     MemorySSAUpdater &MSSAU)
      : LI(LI), DT(DT), CurLoop(CurLoop), MSSAU(MSSAU) {}

  void registerPossiblyHoistableBranch(BranchInst *BI) {
    // We can only hoist conditional branches with loop invariant operands.
    if (!ControlFlowHoisting || !BI->isConditional() ||
        !CurLoop->hasLoopInvariantOperands(BI))
      return;

    // The branch destinations need to be in the loop, and we don't gain
    // anything by duplicating conditional branches with duplicate successors,
    // as it's essentially the same as an unconditional branch.
    BasicBlock *TrueDest = BI->getSuccessor(0);
    BasicBlock *FalseDest = BI->getSuccessor(1);
    if (!CurLoop->contains(TrueDest) || !CurLoop->contains(FalseDest) ||
        TrueDest == FalseDest)
      return;

    // We can hoist BI if one branch destination is the successor of the other,
    // or both have common successor which we check by seeing if the
    // intersection of their successors is non-empty.
    // TODO: This could be expanded to allowing branches where both ends
    // eventually converge to a single block.
    SmallPtrSet<BasicBlock *, 4> TrueDestSucc(llvm::from_range,
                                              successors(TrueDest));
    SmallPtrSet<BasicBlock *, 4> FalseDestSucc(llvm::from_range,
                                               successors(FalseDest));
    BasicBlock *CommonSucc = nullptr;
    if (TrueDestSucc.count(FalseDest)) {
      CommonSucc = FalseDest;
    } else if (FalseDestSucc.count(TrueDest)) {
      CommonSucc = TrueDest;
    } else {
      set_intersect(TrueDestSucc, FalseDestSucc);
      // If there's one common successor use that.
      if (TrueDestSucc.size() == 1)
        CommonSucc = *TrueDestSucc.begin();
      // If there's more than one pick whichever appears first in the block list
      // (we can't use the value returned by TrueDestSucc.begin() as it's
      // unpredicatable which element gets returned).
      else if (!TrueDestSucc.empty()) {
        Function *F = TrueDest->getParent();
        auto IsSucc = [&](BasicBlock &BB) { return TrueDestSucc.count(&BB); };
        auto It = llvm::find_if(*F, IsSucc);
        assert(It != F->end() && "Could not find successor in function");
        CommonSucc = &*It;
      }
    }
    // The common successor has to be dominated by the branch, as otherwise
    // there will be some other path to the successor that will not be
    // controlled by this branch so any phi we hoist would be controlled by the
    // wrong condition. This also takes care of avoiding hoisting of loop back
    // edges.
    // TODO: In some cases this could be relaxed if the successor is dominated
    // by another block that's been hoisted and we can guarantee that the
    // control flow has been replicated exactly.
    if (CommonSucc && DT->dominates(BI, CommonSucc))
      HoistableBranches[BI] = CommonSucc;
  }

  bool canHoistPHI(PHINode *PN) {
    // The phi must have loop invariant operands.
    if (!ControlFlowHoisting || !CurLoop->hasLoopInvariantOperands(PN))
      return false;
    // We can hoist phis if the block they are in is the target of hoistable
    // branches which cover all of the predecessors of the block.
    BasicBlock *BB = PN->getParent();
    SmallPtrSet<BasicBlock *, 8> PredecessorBlocks(llvm::from_range,
                                                   predecessors(BB));
    // If we have less predecessor blocks than predecessors then the phi will
    // have more than one incoming value for the same block which we can't
    // handle.
    // TODO: This could be handled be erasing some of the duplicate incoming
    // values.
    if (PredecessorBlocks.size() != pred_size(BB))
      return false;
    for (auto &Pair : HoistableBranches) {
      if (Pair.second == BB) {
        // Which blocks are predecessors via this branch depends on if the
        // branch is triangle-like or diamond-like.
        if (Pair.first->getSuccessor(0) == BB) {
          PredecessorBlocks.erase(Pair.first->getParent());
          PredecessorBlocks.erase(Pair.first->getSuccessor(1));
        } else if (Pair.first->getSuccessor(1) == BB) {
          PredecessorBlocks.erase(Pair.first->getParent());
          PredecessorBlocks.erase(Pair.first->getSuccessor(0));
        } else {
          PredecessorBlocks.erase(Pair.first->getSuccessor(0));
          PredecessorBlocks.erase(Pair.first->getSuccessor(1));
        }
      }
    }
    // PredecessorBlocks will now be empty if for every predecessor of BB we
    // found a hoistable branch source.
    return PredecessorBlocks.empty();
  }

  BasicBlock *getOrCreateHoistedBlock(BasicBlock *BB) {
    if (!ControlFlowHoisting)
      return CurLoop->getLoopPreheader();
    // If BB has already been hoisted, return that
    if (auto It = HoistDestinationMap.find(BB); It != HoistDestinationMap.end())
      return It->second;

    // Check if this block is conditional based on a pending branch
    auto HasBBAsSuccessor =
        [&](DenseMap<BranchInst *, BasicBlock *>::value_type &Pair) {
          return BB != Pair.second && (Pair.first->getSuccessor(0) == BB ||
                                       Pair.first->getSuccessor(1) == BB);
        };
    auto It = llvm::find_if(HoistableBranches, HasBBAsSuccessor);

    // If not involved in a pending branch, hoist to preheader
    BasicBlock *InitialPreheader = CurLoop->getLoopPreheader();
    if (It == HoistableBranches.end()) {
      LLVM_DEBUG(dbgs() << "LICM using "
                        << InitialPreheader->getNameOrAsOperand()
                        << " as hoist destination for "
                        << BB->getNameOrAsOperand() << "\n");
      HoistDestinationMap[BB] = InitialPreheader;
      return InitialPreheader;
    }
    BranchInst *BI = It->first;
    assert(std::none_of(std::next(It), HoistableBranches.end(),
                        HasBBAsSuccessor) &&
           "BB is expected to be the target of at most one branch");

    LLVMContext &C = BB->getContext();
    BasicBlock *TrueDest = BI->getSuccessor(0);
    BasicBlock *FalseDest = BI->getSuccessor(1);
    BasicBlock *CommonSucc = HoistableBranches[BI];
    BasicBlock *HoistTarget = getOrCreateHoistedBlock(BI->getParent());

    // Create hoisted versions of blocks that currently don't have them
    auto CreateHoistedBlock = [&](BasicBlock *Orig) {
      auto [It, Inserted] = HoistDestinationMap.try_emplace(Orig);
      if (!Inserted)
        return It->second;
      BasicBlock *New =
          BasicBlock::Create(C, Orig->getName() + ".licm", Orig->getParent());
      It->second = New;
      DT->addNewBlock(New, HoistTarget);
      if (CurLoop->getParentLoop())
        CurLoop->getParentLoop()->addBasicBlockToLoop(New, *LI);
      ++NumCreatedBlocks;
      LLVM_DEBUG(dbgs() << "LICM created " << New->getName()
                        << " as hoist destination for " << Orig->getName()
                        << "\n");
      return New;
    };
    BasicBlock *HoistTrueDest = CreateHoistedBlock(TrueDest);
    BasicBlock *HoistFalseDest = CreateHoistedBlock(FalseDest);
    BasicBlock *HoistCommonSucc = CreateHoistedBlock(CommonSucc);

    // Link up these blocks with branches.
    if (!HoistCommonSucc->getTerminator()) {
      // The new common successor we've generated will branch to whatever that
      // hoist target branched to.
      BasicBlock *TargetSucc = HoistTarget->getSingleSuccessor();
      assert(TargetSucc && "Expected hoist target to have a single successor");
      HoistCommonSucc->moveBefore(TargetSucc);
      BranchInst::Create(TargetSucc, HoistCommonSucc);
    }
    if (!HoistTrueDest->getTerminator()) {
      HoistTrueDest->moveBefore(HoistCommonSucc);
      BranchInst::Create(HoistCommonSucc, HoistTrueDest);
    }
    if (!HoistFalseDest->getTerminator()) {
      HoistFalseDest->moveBefore(HoistCommonSucc);
      BranchInst::Create(HoistCommonSucc, HoistFalseDest);
    }

    // If BI is being cloned to what was originally the preheader then
    // HoistCommonSucc will now be the new preheader.
    if (HoistTarget == InitialPreheader) {
      // Phis in the loop header now need to use the new preheader.
      InitialPreheader->replaceSuccessorsPhiUsesWith(HoistCommonSucc);
      MSSAU.wireOldPredecessorsToNewImmediatePredecessor(
          HoistTarget->getSingleSuccessor(), HoistCommonSucc, {HoistTarget});
      // The new preheader dominates the loop header.
      DomTreeNode *PreheaderNode = DT->getNode(HoistCommonSucc);
      DomTreeNode *HeaderNode = DT->getNode(CurLoop->getHeader());
      DT->changeImmediateDominator(HeaderNode, PreheaderNode);
      // The preheader hoist destination is now the new preheader, with the
      // exception of the hoist destination of this branch.
      for (auto &Pair : HoistDestinationMap)
        if (Pair.second == InitialPreheader && Pair.first != BI->getParent())
          Pair.second = HoistCommonSucc;
    }

    // Now finally clone BI.
    ReplaceInstWithInst(
        HoistTarget->getTerminator(),
        BranchInst::Create(HoistTrueDest, HoistFalseDest, BI->getCondition()));
    ++NumClonedBranches;

    assert(CurLoop->getLoopPreheader() &&
           "Hoisting blocks should not have destroyed preheader");
    return HoistDestinationMap[BB];
  }
};
} // namespace

/// Walk the specified region of the CFG (defined by all blocks dominated by
/// the specified block, and that are in the current loop) in depth first
/// order w.r.t the DominatorTree.  This allows us to visit definitions before
/// uses, allowing us to hoist a loop body in one pass without iteration.
///
bool llvm::hoistRegion(DomTreeNode *N, AAResults *AA, LoopInfo *LI,
                       DominatorTree *DT, AssumptionCache *AC,
                       TargetLibraryInfo *TLI, Loop *CurLoop,
                       MemorySSAUpdater &MSSAU, ScalarEvolution *SE,
                       ICFLoopSafetyInfo *SafetyInfo,
                       SinkAndHoistLICMFlags &Flags,
                       OptimizationRemarkEmitter *ORE, bool LoopNestMode,
                       bool AllowSpeculation) {
  // Verify inputs.
  assert(N != nullptr && AA != nullptr && LI != nullptr && DT != nullptr &&
         CurLoop != nullptr && SafetyInfo != nullptr &&
         "Unexpected input to hoistRegion.");

  ControlFlowHoister CFH(LI, DT, CurLoop, MSSAU);

  // Keep track of instructions that have been hoisted, as they may need to be
  // re-hoisted if they end up not dominating all of their uses.
  SmallVector<Instruction *, 16> HoistedInstructions;

  // For PHI hoisting to work we need to hoist blocks before their successors.
  // We can do this by iterating through the blocks in the loop in reverse
  // post-order.
  LoopBlocksRPO Worklist(CurLoop);
  Worklist.perform(LI);
  bool Changed = false;
  BasicBlock *Preheader = CurLoop->getLoopPreheader();
  for (BasicBlock *BB : Worklist) {
    // Only need to process the contents of this block if it is not part of a
    // subloop (which would already have been processed).
    if (!LoopNestMode && inSubLoop(BB, CurLoop, LI))
      continue;

    for (Instruction &I : llvm::make_early_inc_range(*BB)) {
      // Try hoisting the instruction out to the preheader.  We can only do
      // this if all of the operands of the instruction are loop invariant and
      // if it is safe to hoist the instruction. We also check block frequency
      // to make sure instruction only gets hoisted into colder blocks.
      // TODO: It may be safe to hoist if we are hoisting to a conditional block
      // and we have accurately duplicated the control flow from the loop header
      // to that block.
      if (CurLoop->hasLoopInvariantOperands(&I) &&
          canSinkOrHoistInst(I, AA, DT, CurLoop, MSSAU, true, Flags, ORE) &&
          isSafeToExecuteUnconditionally(
              I, DT, TLI, CurLoop, SafetyInfo, ORE,
              Preheader->getTerminator(), AC, AllowSpeculation)) {
        hoist(I, DT, CurLoop, CFH.getOrCreateHoistedBlock(BB), SafetyInfo,
              MSSAU, SE, ORE);
        HoistedInstructions.push_back(&I);
        Changed = true;
        continue;
      }

      // Attempt to remove floating point division out of the loop by
      // converting it to a reciprocal multiplication.
      if (I.getOpcode() == Instruction::FDiv && I.hasAllowReciprocal() &&
          CurLoop->isLoopInvariant(I.getOperand(1))) {
        auto Divisor = I.getOperand(1);
        auto One = llvm::ConstantFP::get(Divisor->getType(), 1.0);
        auto ReciprocalDivisor = BinaryOperator::CreateFDiv(One, Divisor);
        ReciprocalDivisor->setFastMathFlags(I.getFastMathFlags());
        SafetyInfo->insertInstructionTo(ReciprocalDivisor, I.getParent());
        ReciprocalDivisor->insertBefore(I.getIterator());
        ReciprocalDivisor->setDebugLoc(I.getDebugLoc());

        auto Product =
            BinaryOperator::CreateFMul(I.getOperand(0), ReciprocalDivisor);
        Product->setFastMathFlags(I.getFastMathFlags());
        SafetyInfo->insertInstructionTo(Product, I.getParent());
        Product->insertAfter(I.getIterator());
        Product->setDebugLoc(I.getDebugLoc());
        I.replaceAllUsesWith(Product);
        eraseInstruction(I, *SafetyInfo, MSSAU);

        hoist(*ReciprocalDivisor, DT, CurLoop, CFH.getOrCreateHoistedBlock(BB),
              SafetyInfo, MSSAU, SE, ORE);
        HoistedInstructions.push_back(ReciprocalDivisor);
        Changed = true;
        continue;
      }

      auto IsInvariantStart = [&](Instruction &I) {
        using namespace PatternMatch;
        return I.use_empty() &&
               match(&I, m_Intrinsic<Intrinsic::invariant_start>());
      };
      auto MustExecuteWithoutWritesBefore = [&](Instruction &I) {
        return SafetyInfo->isGuaranteedToExecute(I, DT, CurLoop) &&
               SafetyInfo->doesNotWriteMemoryBefore(I, CurLoop);
      };
      if ((IsInvariantStart(I) || isGuard(&I)) &&
          CurLoop->hasLoopInvariantOperands(&I) &&
          MustExecuteWithoutWritesBefore(I)) {
        hoist(I, DT, CurLoop, CFH.getOrCreateHoistedBlock(BB), SafetyInfo,
              MSSAU, SE, ORE);
        HoistedInstructions.push_back(&I);
        Changed = true;
        continue;
      }

      if (PHINode *PN = dyn_cast<PHINode>(&I)) {
        if (CFH.canHoistPHI(PN)) {
          // Redirect incoming blocks first to ensure that we create hoisted
          // versions of those blocks before we hoist the phi.
          for (unsigned int i = 0; i < PN->getNumIncomingValues(); ++i)
            PN->setIncomingBlock(
                i, CFH.getOrCreateHoistedBlock(PN->getIncomingBlock(i)));
          hoist(*PN, DT, CurLoop, CFH.getOrCreateHoistedBlock(BB), SafetyInfo,
                MSSAU, SE, ORE);
          assert(DT->dominates(PN, BB) && "Conditional PHIs not expected");
          Changed = true;
          continue;
        }
      }

      // Try to reassociate instructions so that part of computations can be
      // done out of loop.
      if (hoistArithmetics(I, *CurLoop, *SafetyInfo, MSSAU, AC, DT)) {
        Changed = true;
        continue;
      }

      // Remember possibly hoistable branches so we can actually hoist them
      // later if needed.
      if (BranchInst *BI = dyn_cast<BranchInst>(&I))
        CFH.registerPossiblyHoistableBranch(BI);
    }
  }

  // If we hoisted instructions to a conditional block they may not dominate
  // their uses that weren't hoisted (such as phis where some operands are not
  // loop invariant). If so make them unconditional by moving them to their
  // immediate dominator. We iterate through the instructions in reverse order
  // which ensures that when we rehoist an instruction we rehoist its operands,
  // and also keep track of where in the block we are rehoisting to make sure
  // that we rehoist instructions before the instructions that use them.
  Instruction *HoistPoint = nullptr;
  if (ControlFlowHoisting) {
    for (Instruction *I : reverse(HoistedInstructions)) {
      if (!llvm::all_of(I->uses(),
                        [&](Use &U) { return DT->dominates(I, U); })) {
        BasicBlock *Dominator =
            DT->getNode(I->getParent())->getIDom()->getBlock();
        if (!HoistPoint || !DT->dominates(HoistPoint->getParent(), Dominator)) {
          if (HoistPoint)
            assert(DT->dominates(Dominator, HoistPoint->getParent()) &&
                   "New hoist point expected to dominate old hoist point");
          HoistPoint = Dominator->getTerminator();
        }
        LLVM_DEBUG(dbgs() << "LICM rehoisting to "
                          << HoistPoint->getParent()->getNameOrAsOperand()
                          << ": " << *I << "\n");
        moveInstructionBefore(*I, HoistPoint->getIterator(), *SafetyInfo, MSSAU,
                              SE);
        HoistPoint = I;
        Changed = true;
      }
    }
  }
  if (VerifyMemorySSA)
    MSSAU.getMemorySSA()->verifyMemorySSA();

    // Now that we've finished hoisting make sure that LI and DT are still
    // valid.
#ifdef EXPENSIVE_CHECKS
  if (Changed) {
    assert(DT->verify(DominatorTree::VerificationLevel::Fast) &&
           "Dominator tree verification failed");
    LI->verify(*DT);
  }
#endif

  return Changed;
}

// Return true if LI is invariant within scope of the loop. LI is invariant if
// CurLoop is dominated by an invariant.start representing the same memory
// location and size as the memory location LI loads from, and also the
// invariant.start has no uses.
static bool isLoadInvariantInLoop(LoadInst *LI, DominatorTree *DT,
                                  Loop *CurLoop) {
  Value *Addr = LI->getPointerOperand();
  const DataLayout &DL = LI->getDataLayout();
  const TypeSize LocSizeInBits = DL.getTypeSizeInBits(LI->getType());

  // It is not currently possible for clang to generate an invariant.start
  // intrinsic with scalable vector types because we don't support thread local
  // sizeless types and we don't permit sizeless types in structs or classes.
  // Furthermore, even if support is added for this in future the intrinsic
  // itself is defined to have a size of -1 for variable sized objects. This
  // makes it impossible to verify if the intrinsic envelops our region of
  // interest. For example, both <vscale x 32 x i8> and <vscale x 16 x i8>
  // types would have a -1 parameter, but the former is clearly double the size
  // of the latter.
  if (LocSizeInBits.isScalable())
    return false;

  // If we've ended up at a global/constant, bail. We shouldn't be looking at
  // uselists for non-local Values in a loop pass.
  if (isa<Constant>(Addr))
    return false;

  unsigned UsesVisited = 0;
  // Traverse all uses of the load operand value, to see if invariant.start is
  // one of the uses, and whether it dominates the load instruction.
  for (auto *U : Addr->users()) {
    // Avoid traversing for Load operand with high number of users.
    if (++UsesVisited > MaxNumUsesTraversed)
      return false;
    IntrinsicInst *II = dyn_cast<IntrinsicInst>(U);
    // If there are escaping uses of invariant.start instruction, the load maybe
    // non-invariant.
    if (!II || II->getIntrinsicID() != Intrinsic::invariant_start ||
        !II->use_empty())
      continue;
    ConstantInt *InvariantSize = cast<ConstantInt>(II->getArgOperand(0));
    // The intrinsic supports having a -1 argument for variable sized objects
    // so we should check for that here.
    if (InvariantSize->isNegative())
      continue;
    uint64_t InvariantSizeInBits = InvariantSize->getSExtValue() * 8;
    // Confirm the invariant.start location size contains the load operand size
    // in bits. Also, the invariant.start should dominate the load, and we
    // should not hoist the load out of a loop that contains this dominating
    // invariant.start.
    if (LocSizeInBits.getFixedValue() <= InvariantSizeInBits &&
        DT->properlyDominates(II->getParent(), CurLoop->getHeader()))
      return true;
  }

  return false;
}

namespace {
/// Return true if-and-only-if we know how to (mechanically) both hoist and
/// sink a given instruction out of a loop.  Does not address legality
/// concerns such as aliasing or speculation safety.
bool isHoistableAndSinkableInst(Instruction &I) {
  // Only these instructions are hoistable/sinkable.
  return (isa<LoadInst>(I) || isa<StoreInst>(I) || isa<CallInst>(I) ||
          isa<FenceInst>(I) || isa<CastInst>(I) || isa<UnaryOperator>(I) ||
          isa<BinaryOperator>(I) || isa<SelectInst>(I) ||
          isa<GetElementPtrInst>(I) || isa<CmpInst>(I) ||
          isa<InsertElementInst>(I) || isa<ExtractElementInst>(I) ||
          isa<ShuffleVectorInst>(I) || isa<ExtractValueInst>(I) ||
          isa<InsertValueInst>(I) || isa<FreezeInst>(I));
}

/// Return true if I is the only Instruction with a MemoryAccess in L.
bool isOnlyMemoryAccess(const Instruction *I, const Loop *L,
                        const MemorySSAUpdater &MSSAU) {
  for (auto *BB : L->getBlocks())
    if (auto *Accs = MSSAU.getMemorySSA()->getBlockAccesses(BB)) {
      int NotAPhi = 0;
      for (const auto &Acc : *Accs) {
        if (isa<MemoryPhi>(&Acc))
          continue;
        const auto *MUD = cast<MemoryUseOrDef>(&Acc);
        if (MUD->getMemoryInst() != I || NotAPhi++ == 1)
          return false;
      }
    }
  return true;
}
}

static MemoryAccess *getClobberingMemoryAccess(MemorySSA &MSSA,
                                               BatchAAResults &BAA,
                                               SinkAndHoistLICMFlags &Flags,
                                               MemoryUseOrDef *MA) {
  // See declaration of SetLicmMssaOptCap for usage details.
  if (Flags.tooManyClobberingCalls())
    return MA->getDefiningAccess();

  MemoryAccess *Source =
      MSSA.getSkipSelfWalker()->getClobberingMemoryAccess(MA, BAA);
  Flags.incrementClobberingCalls();
  return Source;
}

bool llvm::canSinkOrHoistInst(Instruction &I, AAResults *AA, DominatorTree *DT,
                              Loop *CurLoop, MemorySSAUpdater &MSSAU,
                              bool TargetExecutesOncePerLoop,
                              SinkAndHoistLICMFlags &Flags,
                              OptimizationRemarkEmitter *ORE) {
  // If we don't understand the instruction, bail early.
  if (!isHoistableAndSinkableInst(I))
    return false;

  MemorySSA *MSSA = MSSAU.getMemorySSA();
  // Loads have extra constraints we have to verify before we can hoist them.
  if (LoadInst *LI = dyn_cast<LoadInst>(&I)) {
    if (!LI->isUnordered())
      return false; // Don't sink/hoist volatile or ordered atomic loads!

    // Loads from constant memory are always safe to move, even if they end up
    // in the same alias set as something that ends up being modified.
    if (!isModSet(AA->getModRefInfoMask(LI->getOperand(0))))
      return true;
    if (LI->hasMetadata(LLVMContext::MD_invariant_load))
      return true;

    if (LI->isAtomic() && !TargetExecutesOncePerLoop)
      return false; // Don't risk duplicating unordered loads

    // This checks for an invariant.start dominating the load.
    if (isLoadInvariantInLoop(LI, DT, CurLoop))
      return true;

    auto MU = cast<MemoryUse>(MSSA->getMemoryAccess(LI));

    bool InvariantGroup = LI->hasMetadata(LLVMContext::MD_invariant_group);

    bool Invalidated = pointerInvalidatedByLoop(
        MSSA, MU, CurLoop, I, Flags, InvariantGroup);
    // Check loop-invariant address because this may also be a sinkable load
    // whose address is not necessarily loop-invariant.
    if (ORE && Invalidated && CurLoop->isLoopInvariant(LI->getPointerOperand()))
      ORE->emit([&]() {
        return OptimizationRemarkMissed(
                   DEBUG_TYPE, "LoadWithLoopInvariantAddressInvalidated", LI)
               << "failed to move load with loop-invariant address "
                  "because the loop may invalidate its value";
      });

    return !Invalidated;
  } else if (CallInst *CI = dyn_cast<CallInst>(&I)) {
    // Don't sink calls which can throw.
    if (CI->mayThrow())
      return false;

    // Convergent attribute has been used on operations that involve
    // inter-thread communication which results are implicitly affected by the
    // enclosing control flows. It is not safe to hoist or sink such operations
    // across control flow.
    if (CI->isConvergent())
      return false;

    // FIXME: Current LLVM IR semantics don't work well with coroutines and
    // thread local globals. We currently treat getting the address of a thread
    // local global as not accessing memory, even though it may not be a
    // constant throughout a function with coroutines. Remove this check after
    // we better model semantics of thread local globals.
    if (CI->getFunction()->isPresplitCoroutine())
      return false;

    using namespace PatternMatch;
    if (match(CI, m_Intrinsic<Intrinsic::assume>()))
      // Assumes don't actually alias anything or throw
      return true;

    // Handle simple cases by querying alias analysis.
    MemoryEffects Behavior = AA->getMemoryEffects(CI);

    if (Behavior.doesNotAccessMemory())
      return true;
    if (Behavior.onlyReadsMemory()) {
      // If we can prove there are no writes to the memory read by the call, we
      // can hoist or sink.
      return !pointerInvalidatedByLoop(
          MSSA, cast<MemoryUse>(MSSA->getMemoryAccess(CI)), CurLoop, I, Flags,
          /*InvariantGroup=*/false);
    }

    if (Behavior.onlyWritesMemory()) {
      // can hoist or sink if there are no conflicting read/writes to the
      // memory location written to by the call.
      return noConflictingReadWrites(CI, MSSA, AA, CurLoop, Flags);
    }

    return false;
  } else if (auto *FI = dyn_cast<FenceInst>(&I)) {
    // Fences alias (most) everything to provide ordering.  For the moment,
    // just give up if there are any other memory operations in the loop.
    return isOnlyMemoryAccess(FI, CurLoop, MSSAU);
  } else if (auto *SI = dyn_cast<StoreInst>(&I)) {
    if (!SI->isUnordered())
      return false; // Don't sink/hoist volatile or ordered atomic store!

    // We can only hoist a store that we can prove writes a value which is not
    // read or overwritten within the loop.  For those cases, we fallback to
    // load store promotion instead.  TODO: We can extend this to cases where
    // there is exactly one write to the location and that write dominates an
    // arbitrary number of reads in the loop.
    if (isOnlyMemoryAccess(SI, CurLoop, MSSAU))
      return true;
    return noConflictingReadWrites(SI, MSSA, AA, CurLoop, Flags);
  }

  assert(!I.mayReadOrWriteMemory() && "unhandled aliasing");

  // We've established mechanical ability and aliasing, it's up to the caller
  // to check fault safety
  return true;
}

/// Returns true if a PHINode is a trivially replaceable with an
/// Instruction.
/// This is true when all incoming values are that instruction.
/// This pattern occurs most often with LCSSA PHI nodes.
///
static bool isTriviallyReplaceablePHI(const PHINode &PN, const Instruction &I) {
  for (const Value *IncValue : PN.incoming_values())
    if (IncValue != &I)
      return false;

  return true;
}

/// Return true if the instruction is foldable in the loop.
static bool isFoldableInLoop(const Instruction &I, const Loop *CurLoop,
                         const TargetTransformInfo *TTI) {
  if (auto *GEP = dyn_cast<GetElementPtrInst>(&I)) {
    InstructionCost CostI =
        TTI->getInstructionCost(&I, TargetTransformInfo::TCK_SizeAndLatency);
    if (CostI != TargetTransformInfo::TCC_Free)
      return false;
    // For a GEP, we cannot simply use getInstructionCost because currently
    // it optimistically assumes that a GEP will fold into addressing mode
    // regardless of its users.
    const BasicBlock *BB = GEP->getParent();
    for (const User *U : GEP->users()) {
      const Instruction *UI = cast<Instruction>(U);
      if (CurLoop->contains(UI) &&
          (BB != UI->getParent() ||
           (!isa<StoreInst>(UI) && !isa<LoadInst>(UI))))
        return false;
    }
    return true;
  }

  return false;
}

/// Return true if the only users of this instruction are outside of
/// the loop. If this is true, we can sink the instruction to the exit
/// blocks of the loop.
///
/// We also return true if the instruction could be folded away in lowering.
/// (e.g.,  a GEP can be folded into a load as an addressing mode in the loop).
static bool isNotUsedOrFoldableInLoop(const Instruction &I, const Loop *CurLoop,
                                      const LoopSafetyInfo *SafetyInfo,
                                      TargetTransformInfo *TTI,
                                      bool &FoldableInLoop, bool LoopNestMode) {
  const auto &BlockColors = SafetyInfo->getBlockColors();
  bool IsFoldable = isFoldableInLoop(I, CurLoop, TTI);
  for (const User *U : I.users()) {
    const Instruction *UI = cast<Instruction>(U);
    if (const PHINode *PN = dyn_cast<PHINode>(UI)) {
      const BasicBlock *BB = PN->getParent();
      // We cannot sink uses in catchswitches.
      if (isa<CatchSwitchInst>(BB->getTerminator()))
        return false;

      // We need to sink a callsite to a unique funclet.  Avoid sinking if the
      // phi use is too muddled.
      if (isa<CallInst>(I))
        if (!BlockColors.empty() &&
            BlockColors.find(const_cast<BasicBlock *>(BB))->second.size() != 1)
          return false;

      if (LoopNestMode) {
        while (isa<PHINode>(UI) && UI->hasOneUser() &&
               UI->getNumOperands() == 1) {
          if (!CurLoop->contains(UI))
            break;
          UI = cast<Instruction>(UI->user_back());
        }
      }
    }

    if (CurLoop->contains(UI)) {
      if (IsFoldable) {
        FoldableInLoop = true;
        continue;
      }
      return false;
    }
  }
  return true;
}

static Instruction *cloneInstructionInExitBlock(
    Instruction &I, BasicBlock &ExitBlock, PHINode &PN, const LoopInfo *LI,
    const LoopSafetyInfo *SafetyInfo, MemorySSAUpdater &MSSAU) {
  Instruction *New;
  if (auto *CI = dyn_cast<CallInst>(&I)) {
    const auto &BlockColors = SafetyInfo->getBlockColors();

    // Sinking call-sites need to be handled differently from other
    // instructions.  The cloned call-site needs a funclet bundle operand
    // appropriate for its location in the CFG.
    SmallVector<OperandBundleDef, 1> OpBundles;
    for (unsigned BundleIdx = 0, BundleEnd = CI->getNumOperandBundles();
         BundleIdx != BundleEnd; ++BundleIdx) {
      OperandBundleUse Bundle = CI->getOperandBundleAt(BundleIdx);
      if (Bundle.getTagID() == LLVMContext::OB_funclet)
        continue;

      OpBundles.emplace_back(Bundle);
    }

    if (!BlockColors.empty()) {
      const ColorVector &CV = BlockColors.find(&ExitBlock)->second;
      assert(CV.size() == 1 && "non-unique color for exit block!");
      BasicBlock *BBColor = CV.front();
      BasicBlock::iterator EHPad = BBColor->getFirstNonPHIIt();
      if (EHPad->isEHPad())
        OpBundles.emplace_back("funclet", &*EHPad);
    }

    New = CallInst::Create(CI, OpBundles);
    New->copyMetadata(*CI);
  } else {
    New = I.clone();
  }

  New->insertInto(&ExitBlock, ExitBlock.getFirstInsertionPt());
  if (!I.getName().empty())
    New->setName(I.getName() + ".le");

  if (MSSAU.getMemorySSA()->getMemoryAccess(&I)) {
    // Create a new MemoryAccess and let MemorySSA set its defining access.
    // After running some passes, MemorySSA might be outdated, and the
    // instruction `I` may have become a non-memory touching instruction.
    MemoryAccess *NewMemAcc = MSSAU.createMemoryAccessInBB(
        New, nullptr, New->getParent(), MemorySSA::Beginning,
        /*CreationMustSucceed=*/false);
    if (NewMemAcc) {
      if (auto *MemDef = dyn_cast<MemoryDef>(NewMemAcc))
        MSSAU.insertDef(MemDef, /*RenameUses=*/true);
      else {
        auto *MemUse = cast<MemoryUse>(NewMemAcc);
        MSSAU.insertUse(MemUse, /*RenameUses=*/true);
      }
    }
  }

  // Build LCSSA PHI nodes for any in-loop operands (if legal).  Note that
  // this is particularly cheap because we can rip off the PHI node that we're
  // replacing for the number and blocks of the predecessors.
  // OPT: If this shows up in a profile, we can instead finish sinking all
  // invariant instructions, and then walk their operands to re-establish
  // LCSSA. That will eliminate creating PHI nodes just to nuke them when
  // sinking bottom-up.
  for (Use &Op : New->operands())
    if (LI->wouldBeOutOfLoopUseRequiringLCSSA(Op.get(), PN.getParent())) {
      auto *OInst = cast<Instruction>(Op.get());
      PHINode *OpPN =
          PHINode::Create(OInst->getType(), PN.getNumIncomingValues(),
                          OInst->getName() + ".lcssa");
      OpPN->insertBefore(ExitBlock.begin());
      for (unsigned i = 0, e = PN.getNumIncomingValues(); i != e; ++i)
        OpPN->addIncoming(OInst, PN.getIncomingBlock(i));
      Op = OpPN;
    }
  return New;
}

static void eraseInstruction(Instruction &I, ICFLoopSafetyInfo &SafetyInfo,
                             MemorySSAUpdater &MSSAU) {
  MSSAU.removeMemoryAccess(&I);
  SafetyInfo.removeInstruction(&I);
  I.eraseFromParent();
}

static void moveInstructionBefore(Instruction &I, BasicBlock::iterator Dest,
                                  ICFLoopSafetyInfo &SafetyInfo,
                                  MemorySSAUpdater &MSSAU,
                                  ScalarEvolution *SE) {
  SafetyInfo.removeInstruction(&I);
  SafetyInfo.insertInstructionTo(&I, Dest->getParent());
  I.moveBefore(*Dest->getParent(), Dest);
  if (MemoryUseOrDef *OldMemAcc = cast_or_null<MemoryUseOrDef>(
          MSSAU.getMemorySSA()->getMemoryAccess(&I)))
    MSSAU.moveToPlace(OldMemAcc, Dest->getParent(),
                      MemorySSA::BeforeTerminator);
  if (SE)
    SE->forgetBlockAndLoopDispositions(&I);
}

static Instruction *sinkThroughTriviallyReplaceablePHI(
    PHINode *TPN, Instruction *I, LoopInfo *LI,
    SmallDenseMap<BasicBlock *, Instruction *, 32> &SunkCopies,
    const LoopSafetyInfo *SafetyInfo, const Loop *CurLoop,
    MemorySSAUpdater &MSSAU) {
  assert(isTriviallyReplaceablePHI(*TPN, *I) &&
         "Expect only trivially replaceable PHI");
  BasicBlock *ExitBlock = TPN->getParent();
  auto [It, Inserted] = SunkCopies.try_emplace(ExitBlock);
  if (Inserted)
    It->second = cloneInstructionInExitBlock(*I, *ExitBlock, *TPN, LI,
                                             SafetyInfo, MSSAU);
  return It->second;
}

static bool canSplitPredecessors(PHINode *PN, LoopSafetyInfo *SafetyInfo) {
  BasicBlock *BB = PN->getParent();
  if (!BB->canSplitPredecessors())
    return false;
  // It's not impossible to split EHPad blocks, but if BlockColors already exist
  // it require updating BlockColors for all offspring blocks accordingly. By
  // skipping such corner case, we can make updating BlockColors after splitting
  // predecessor fairly simple.
  if (!SafetyInfo->getBlockColors().empty() &&
      BB->getFirstNonPHIIt()->isEHPad())
    return false;
  for (BasicBlock *BBPred : predecessors(BB)) {
    if (isa<IndirectBrInst>(BBPred->getTerminator()))
      return false;
  }
  return true;
}

static void splitPredecessorsOfLoopExit(PHINode *PN, DominatorTree *DT,
                                        LoopInfo *LI, const Loop *CurLoop,
                                        LoopSafetyInfo *SafetyInfo,
                                        MemorySSAUpdater *MSSAU) {
#ifndef NDEBUG
  SmallVector<BasicBlock *, 32> ExitBlocks;
  CurLoop->getUniqueExitBlocks(ExitBlocks);
  SmallPtrSet<BasicBlock *, 32> ExitBlockSet(llvm::from_range, ExitBlocks);
#endif
  BasicBlock *ExitBB = PN->getParent();
  assert(ExitBlockSet.count(ExitBB) && "Expect the PHI is in an exit block.");

  // Split predecessors of the loop exit to make instructions in the loop are
  // exposed to exit blocks through trivially replaceable PHIs while keeping the
  // loop in the canonical form where each predecessor of each exit block should
  // be contained within the loop. For example, this will convert the loop below
  // from
  //
  // LB1:
  //   %v1 =
  //   br %LE, %LB2
  // LB2:
  //   %v2 =
  //   br %LE, %LB1
  // LE:
  //   %p = phi [%v1, %LB1], [%v2, %LB2] <-- non-trivially replaceable
  //
  // to
  //
  // LB1:
  //   %v1 =
  //   br %LE.split, %LB2
  // LB2:
  //   %v2 =
  //   br %LE.split2, %LB1
  // LE.split:
  //   %p1 = phi [%v1, %LB1]  <-- trivially replaceable
  //   br %LE
  // LE.split2:
  //   %p2 = phi [%v2, %LB2]  <-- trivially replaceable
  //   br %LE
  // LE:
  //   %p = phi [%p1, %LE.split], [%p2, %LE.split2]
  //
  const auto &BlockColors = SafetyInfo->getBlockColors();
  SmallSetVector<BasicBlock *, 8> PredBBs(pred_begin(ExitBB), pred_end(ExitBB));
  DomTreeUpdater DTU(DT, DomTreeUpdater::UpdateStrategy::Lazy);
  while (!PredBBs.empty()) {
    BasicBlock *PredBB = *PredBBs.begin();
    assert(CurLoop->contains(PredBB) &&
           "Expect all predecessors are in the loop");
    if (PN->getBasicBlockIndex(PredBB) >= 0) {
      BasicBlock *NewPred = SplitBlockPredecessors(
          ExitBB, PredBB, ".split.loop.exit", &DTU, LI, MSSAU, true);
      // Since we do not allow splitting EH-block with BlockColors in
      // canSplitPredecessors(), we can simply assign predecessor's color to
      // the new block.
      if (!BlockColors.empty())
        // Grab a reference to the ColorVector to be inserted before getting the
        // reference to the vector we are copying because inserting the new
        // element in BlockColors might cause the map to be reallocated.
        SafetyInfo->copyColors(NewPred, PredBB);
    }
    PredBBs.remove(PredBB);
  }
}

/// When an instruction is found to only be used outside of the loop, this
/// function moves it to the exit blocks and patches up SSA form as needed.
/// This method is guaranteed to remove the original instruction from its
/// position, and may either delete it or move it to outside of the loop.
///
static bool sink(Instruction &I, LoopInfo *LI, DominatorTree *DT,
                 const Loop *CurLoop, ICFLoopSafetyInfo *SafetyInfo,
                 MemorySSAUpdater &MSSAU, OptimizationRemarkEmitter *ORE) {
  bool Changed = false;
  LLVM_DEBUG(dbgs() << "LICM sinking instruction: " << I << "\n");

  // Iterate over users to be ready for actual sinking. Replace users via
  // unreachable blocks with undef and make all user PHIs trivially replaceable.
  SmallPtrSet<Instruction *, 8> VisitedUsers;
  for (Value::user_iterator UI = I.user_begin(), UE = I.user_end(); UI != UE;) {
    auto *User = cast<Instruction>(*UI);
    Use &U = UI.getUse();
    ++UI;

    if (VisitedUsers.count(User) || CurLoop->contains(User))
      continue;

    if (!DT->isReachableFromEntry(User->getParent())) {
      U = PoisonValue::get(I.getType());
      Changed = true;
      continue;
    }

    // The user must be a PHI node.
    PHINode *PN = cast<PHINode>(User);

    // Surprisingly, instructions can be used outside of loops without any
    // exits.  This can only happen in PHI nodes if the incoming block is
    // unreachable.
    BasicBlock *BB = PN->getIncomingBlock(U);
    if (!DT->isReachableFromEntry(BB)) {
      U = PoisonValue::get(I.getType());
      Changed = true;
      continue;
    }

    VisitedUsers.insert(PN);
    if (isTriviallyReplaceablePHI(*PN, I))
      continue;

    if (!canSplitPredecessors(PN, SafetyInfo))
      return Changed;

    // Split predecessors of the PHI so that we can make users trivially
    // replaceable.
    splitPredecessorsOfLoopExit(PN, DT, LI, CurLoop, SafetyInfo, &MSSAU);

    // Should rebuild the iterators, as they may be invalidated by
    // splitPredecessorsOfLoopExit().
    UI = I.user_begin();
    UE = I.user_end();
  }

  if (VisitedUsers.empty())
    return Changed;

  ORE->emit([&]() {
    return OptimizationRemark(DEBUG_TYPE, "InstSunk", &I)
           << "sinking " << ore::NV("Inst", &I);
  });
  if (isa<LoadInst>(I))
    ++NumMovedLoads;
  else if (isa<CallInst>(I))
    ++NumMovedCalls;
  ++NumSunk;

#ifndef NDEBUG
  SmallVector<BasicBlock *, 32> ExitBlocks;
  CurLoop->getUniqueExitBlocks(ExitBlocks);
  SmallPtrSet<BasicBlock *, 32> ExitBlockSet(llvm::from_range, ExitBlocks);
#endif

  // Clones of this instruction. Don't create more than one per exit block!
  SmallDenseMap<BasicBlock *, Instruction *, 32> SunkCopies;

  // If this instruction is only used outside of the loop, then all users are
  // PHI nodes in exit blocks due to LCSSA form. Just RAUW them with clones of
  // the instruction.
  // First check if I is worth sinking for all uses. Sink only when it is worth
  // across all uses.
  SmallSetVector<User*, 8> Users(I.user_begin(), I.user_end());
  for (auto *UI : Users) {
    auto *User = cast<Instruction>(UI);

    if (CurLoop->contains(User))
      continue;

    PHINode *PN = cast<PHINode>(User);
    assert(ExitBlockSet.count(PN->getParent()) &&
           "The LCSSA PHI is not in an exit block!");

    // The PHI must be trivially replaceable.
    Instruction *New = sinkThroughTriviallyReplaceablePHI(
        PN, &I, LI, SunkCopies, SafetyInfo, CurLoop, MSSAU);
    // As we sink the instruction out of the BB, drop its debug location.
    New->dropLocation();
    PN->replaceAllUsesWith(New);
    eraseInstruction(*PN, *SafetyInfo, MSSAU);
    Changed = true;
  }
  return Changed;
}

/// When an instruction is found to only use loop invariant operands that
/// is safe to hoist, this instruction is called to do the dirty work.
///
static void hoist(Instruction &I, const DominatorTree *DT, const Loop *CurLoop,
                  BasicBlock *Dest, ICFLoopSafetyInfo *SafetyInfo,
                  MemorySSAUpdater &MSSAU, ScalarEvolution *SE,
                  OptimizationRemarkEmitter *ORE) {
  LLVM_DEBUG(dbgs() << "LICM hoisting to " << Dest->getNameOrAsOperand() << ": "
                    << I << "\n");
  ORE->emit([&]() {
    return OptimizationRemark(DEBUG_TYPE, "Hoisted", &I) << "hoisting "
                                                         << ore::NV("Inst", &I);
  });

  // Metadata can be dependent on conditions we are hoisting above.
  // Conservatively strip all metadata on the instruction unless we were
  // guaranteed to execute I if we entered the loop, in which case the metadata
  // is valid in the loop preheader.
  // Similarly, If I is a call and it is not guaranteed to execute in the loop,
  // then moving to the preheader means we should strip attributes on the call
  // that can cause UB since we may be hoisting above conditions that allowed
  // inferring those attributes. They may not be valid at the preheader.
  if ((I.hasMetadataOtherThanDebugLoc() || isa<CallInst>(I)) &&
      // The check on hasMetadataOtherThanDebugLoc is to prevent us from burning
      // time in isGuaranteedToExecute if we don't actually have anything to
      // drop.  It is a compile time optimization, not required for correctness.
      !SafetyInfo->isGuaranteedToExecute(I, DT, CurLoop))
    I.dropUBImplyingAttrsAndMetadata();

  if (isa<PHINode>(I))
    // Move the new node to the end of the phi list in the destination block.
    moveInstructionBefore(I, Dest->getFirstNonPHIIt(), *SafetyInfo, MSSAU, SE);
  else
    // Move the new node to the destination block, before its terminator.
    moveInstructionBefore(I, Dest->getTerminator()->getIterator(), *SafetyInfo,
                          MSSAU, SE);

  I.updateLocationAfterHoist();

  if (isa<LoadInst>(I))
    ++NumMovedLoads;
  else if (isa<CallInst>(I))
    ++NumMovedCalls;
  ++NumHoisted;
}

/// Only sink or hoist an instruction if it is not a trapping instruction,
/// or if the instruction is known not to trap when moved to the preheader.
/// or if it is a trapping instruction and is guaranteed to execute.
static bool isSafeToExecuteUnconditionally(
    Instruction &Inst, const DominatorTree *DT, const TargetLibraryInfo *TLI,
    const Loop *CurLoop, const LoopSafetyInfo *SafetyInfo,
    OptimizationRemarkEmitter *ORE, const Instruction *CtxI,
    AssumptionCache *AC, bool AllowSpeculation) {
  if (AllowSpeculation &&
      isSafeToSpeculativelyExecute(&Inst, CtxI, AC, DT, TLI))
    return true;

  bool GuaranteedToExecute =
      SafetyInfo->isGuaranteedToExecute(Inst, DT, CurLoop);

  if (!GuaranteedToExecute) {
    auto *LI = dyn_cast<LoadInst>(&Inst);
    if (LI && CurLoop->isLoopInvariant(LI->getPointerOperand()))
      ORE->emit([&]() {
        return OptimizationRemarkMissed(
                   DEBUG_TYPE, "LoadWithLoopInvariantAddressCondExecuted", LI)
               << "failed to hoist load with loop-invariant address "
                  "because load is conditionally executed";
      });
  }

  return GuaranteedToExecute;
}

namespace {
class LoopPromoter : public LoadAndStorePromoter {
  Value *SomePtr; // Designated pointer to store to.
  SmallVectorImpl<BasicBlock *> &LoopExitBlocks;
  SmallVectorImpl<BasicBlock::iterator> &LoopInsertPts;
  SmallVectorImpl<MemoryAccess *> &MSSAInsertPts;
  PredIteratorCache &PredCache;
  MemorySSAUpdater &MSSAU;
  LoopInfo &LI;
  DebugLoc DL;
  Align Alignment;
  bool UnorderedAtomic;
  AAMDNodes AATags;
  ICFLoopSafetyInfo &SafetyInfo;
  bool CanInsertStoresInExitBlocks;
  ArrayRef<const Instruction *> Uses;

  // We're about to add a use of V in a loop exit block.  Insert an LCSSA phi
  // (if legal) if doing so would add an out-of-loop use to an instruction
  // defined in-loop.
  Value *maybeInsertLCSSAPHI(Value *V, BasicBlock *BB) const {
    if (!LI.wouldBeOutOfLoopUseRequiringLCSSA(V, BB))
      return V;

    Instruction *I = cast<Instruction>(V);
    // We need to create an LCSSA PHI node for the incoming value and
    // store that.
    PHINode *PN = PHINode::Create(I->getType(), PredCache.size(BB),
                                  I->getName() + ".lcssa");
    PN->insertBefore(BB->begin());
    for (BasicBlock *Pred : PredCache.get(BB))
      PN->addIncoming(I, Pred);
    return PN;
  }

public:
  LoopPromoter(Value *SP, ArrayRef<const Instruction *> Insts, SSAUpdater &S,
               SmallVectorImpl<BasicBlock *> &LEB,
               SmallVectorImpl<BasicBlock::iterator> &LIP,
               SmallVectorImpl<MemoryAccess *> &MSSAIP, PredIteratorCache &PIC,
               MemorySSAUpdater &MSSAU, LoopInfo &li, DebugLoc dl,
               Align Alignment, bool UnorderedAtomic, const AAMDNodes &AATags,
               ICFLoopSafetyInfo &SafetyInfo, bool CanInsertStoresInExitBlocks)
      : LoadAndStorePromoter(Insts, S), SomePtr(SP), LoopExitBlocks(LEB),
        LoopInsertPts(LIP), MSSAInsertPts(MSSAIP), PredCache(PIC), MSSAU(MSSAU),
        LI(li), DL(std::move(dl)), Alignment(Alignment),
        UnorderedAtomic(UnorderedAtomic), AATags(AATags),
        SafetyInfo(SafetyInfo),
        CanInsertStoresInExitBlocks(CanInsertStoresInExitBlocks), Uses(Insts) {}

  void insertStoresInLoopExitBlocks() {
    // Insert stores after in the loop exit blocks.  Each exit block gets a
    // store of the live-out values that feed them.  Since we've already told
    // the SSA updater about the defs in the loop and the preheader
    // definition, it is all set and we can start using it.
    DIAssignID *NewID = nullptr;
    for (unsigned i = 0, e = LoopExitBlocks.size(); i != e; ++i) {
      BasicBlock *ExitBlock = LoopExitBlocks[i];
      Value *LiveInValue = SSA.GetValueInMiddleOfBlock(ExitBlock);
      LiveInValue = maybeInsertLCSSAPHI(LiveInValue, ExitBlock);
      Value *Ptr = maybeInsertLCSSAPHI(SomePtr, ExitBlock);
      BasicBlock::iterator InsertPos = LoopInsertPts[i];
      StoreInst *NewSI = new StoreInst(LiveInValue, Ptr, InsertPos);
      if (UnorderedAtomic)
        NewSI->setOrdering(AtomicOrdering::Unordered);
      NewSI->setAlignment(Alignment);
      NewSI->setDebugLoc(DL);
      // Attach DIAssignID metadata to the new store, generating it on the
      // first loop iteration.
      if (i == 0) {
        // NewSI will have its DIAssignID set here if there are any stores in
        // Uses with a DIAssignID attachment. This merged ID will then be
        // attached to the other inserted stores (in the branch below).
        NewSI->mergeDIAssignID(Uses);
        NewID = cast_or_null<DIAssignID>(
            NewSI->getMetadata(LLVMContext::MD_DIAssignID));
      } else {
        // Attach the DIAssignID (or nullptr) merged from Uses in the branch
        // above.
        NewSI->setMetadata(LLVMContext::MD_DIAssignID, NewID);
      }

      if (AATags)
        NewSI->setAAMetadata(AATags);

      MemoryAccess *MSSAInsertPoint = MSSAInsertPts[i];
      MemoryAccess *NewMemAcc;
      if (!MSSAInsertPoint) {
        NewMemAcc = MSSAU.createMemoryAccessInBB(
            NewSI, nullptr, NewSI->getParent(), MemorySSA::Beginning);
      } else {
        NewMemAcc =
            MSSAU.createMemoryAccessAfter(NewSI, nullptr, MSSAInsertPoint);
      }
      MSSAInsertPts[i] = NewMemAcc;
      MSSAU.insertDef(cast<MemoryDef>(NewMemAcc), true);
      // FIXME: true for safety, false may still be correct.
    }
  }

  void doExtraRewritesBeforeFinalDeletion() override {
    if (CanInsertStoresInExitBlocks)
      insertStoresInLoopExitBlocks();
  }

  void instructionDeleted(Instruction *I) const override {
    SafetyInfo.removeInstruction(I);
    MSSAU.removeMemoryAccess(I);
  }

  bool shouldDelete(Instruction *I) const override {
    if (isa<StoreInst>(I))
      return CanInsertStoresInExitBlocks;
    return true;
  }
};

bool isNotCapturedBeforeOrInLoop(const Value *V, const Loop *L,
                                 DominatorTree *DT) {
  // We can perform the captured-before check against any instruction in the
  // loop header, as the loop header is reachable from any instruction inside
  // the loop.
  // TODO: ReturnCaptures=true shouldn't be necessary here.
  return capturesNothing(PointerMayBeCapturedBefore(
      V, /*ReturnCaptures=*/true, L->getHeader()->getTerminator(), DT,
      /*IncludeI=*/false, CaptureComponents::Provenance));
}

/// Return true if we can prove that a caller cannot inspect the object if an
/// unwind occurs inside the loop.
bool isNotVisibleOnUnwindInLoop(const Value *Object, const Loop *L,
                                DominatorTree *DT) {
  bool RequiresNoCaptureBeforeUnwind;
  if (!isNotVisibleOnUnwind(Object, RequiresNoCaptureBeforeUnwind))
    return false;

  return !RequiresNoCaptureBeforeUnwind ||
         isNotCapturedBeforeOrInLoop(Object, L, DT);
}

bool isThreadLocalObject(const Value *Object, const Loop *L, DominatorTree *DT,
                         TargetTransformInfo *TTI) {
  // The object must be function-local to start with, and then not captured
  // before/in the loop.
  return (isIdentifiedFunctionLocal(Object) &&
          isNotCapturedBeforeOrInLoop(Object, L, DT)) ||
         (TTI->isSingleThreaded() || SingleThread);
}

} // namespace

/// Try to promote memory values to scalars by sinking stores out of the
/// loop and moving loads to before the loop.  We do this by looping over
/// the stores in the loop, looking for stores to Must pointers which are
/// loop invariant.
///
bool llvm::promoteLoopAccessesToScalars(
    const SmallSetVector<Value *, 8> &PointerMustAliases,
    SmallVectorImpl<BasicBlock *> &ExitBlocks,
    SmallVectorImpl<BasicBlock::iterator> &InsertPts,
    SmallVectorImpl<MemoryAccess *> &MSSAInsertPts, PredIteratorCache &PIC,
    LoopInfo *LI, DominatorTree *DT, AssumptionCache *AC,
    const TargetLibraryInfo *TLI, TargetTransformInfo *TTI, Loop *CurLoop,
    MemorySSAUpdater &MSSAU, ICFLoopSafetyInfo *SafetyInfo,
    OptimizationRemarkEmitter *ORE, bool AllowSpeculation,
    bool HasReadsOutsideSet) {
  // Verify inputs.
  assert(LI != nullptr && DT != nullptr && CurLoop != nullptr &&
         SafetyInfo != nullptr &&
         "Unexpected Input to promoteLoopAccessesToScalars");

  LLVM_DEBUG({
    dbgs() << "Trying to promote set of must-aliased pointers:\n";
    for (Value *Ptr : PointerMustAliases)
      dbgs() << "  " << *Ptr << "\n";
  });
  ++NumPromotionCandidates;

  Value *SomePtr = *PointerMustAliases.begin();
  BasicBlock *Preheader = CurLoop->getLoopPreheader();

  // It is not safe to promote a load/store from the loop if the load/store is
  // conditional.  For example, turning:
  //
  //    for () { if (c) *P += 1; }
  //
  // into:
  //
  //    tmp = *P;  for () { if (c) tmp +=1; } *P = tmp;
  //
  // is not safe, because *P may only be valid to access if 'c' is true.
  //
  // The safety property divides into two parts:
  // p1) The memory may not be dereferenceable on entry to the loop.  In this
  //    case, we can't insert the required load in the preheader.
  // p2) The memory model does not allow us to insert a store along any dynamic
  //    path which did not originally have one.
  //
  // If at least one store is guaranteed to execute, both properties are
  // satisfied, and promotion is legal.
  //
  // This, however, is not a necessary condition. Even if no store/load is
  // guaranteed to execute, we can still establish these properties.
  // We can establish (p1) by proving that hoisting the load into the preheader
  // is safe (i.e. proving dereferenceability on all paths through the loop). We
  // can use any access within the alias set to prove dereferenceability,
  // since they're all must alias.
  //
  // There are two ways establish (p2):
  // a) Prove the location is thread-local. In this case the memory model
  // requirement does not apply, and stores are safe to insert.
  // b) Prove a store dominates every exit block. In this case, if an exit
  // blocks is reached, the original dynamic path would have taken us through
  // the store, so inserting a store into the exit block is safe. Note that this
  // is different from the store being guaranteed to execute. For instance,
  // if an exception is thrown on the first iteration of the loop, the original
  // store is never executed, but the exit blocks are not executed either.

  bool DereferenceableInPH = false;
  bool StoreIsGuanteedToExecute = false;
  bool LoadIsGuaranteedToExecute = false;
  bool FoundLoadToPromote = false;

  // Goes from Unknown to either Safe or Unsafe, but can't switch between them.
  enum {
    StoreSafe,
    StoreUnsafe,
    StoreSafetyUnknown,
  } StoreSafety = StoreSafetyUnknown;

  SmallVector<Instruction *, 64> LoopUses;

  // We start with an alignment of one and try to find instructions that allow
  // us to prove better alignment.
  Align Alignment;
  // Keep track of which types of access we see
  bool SawUnorderedAtomic = false;
  bool SawNotAtomic = false;
  AAMDNodes AATags;

  const DataLayout &MDL = Preheader->getDataLayout();

  // If there are reads outside the promoted set, then promoting stores is
  // definitely not safe.
  if (HasReadsOutsideSet)
    StoreSafety = StoreUnsafe;

  if (StoreSafety == StoreSafetyUnknown && SafetyInfo->anyBlockMayThrow()) {
    // If a loop can throw, we have to insert a store along each unwind edge.
    // That said, we can't actually make the unwind edge explicit. Therefore,
    // we have to prove that the store is dead along the unwind edge.  We do
    // this by proving that the caller can't have a reference to the object
    // after return and thus can't possibly load from the object.
    Value *Object = getUnderlyingObject(SomePtr);
    if (!isNotVisibleOnUnwindInLoop(Object, CurLoop, DT))
      StoreSafety = StoreUnsafe;
  }

  // Check that all accesses to pointers in the alias set use the same type.
  // We cannot (yet) promote a memory location that is loaded and stored in
  // different sizes.  While we are at it, collect alignment and AA info.
  Type *AccessTy = nullptr;
  for (Value *ASIV : PointerMustAliases) {
    for (Use &U : ASIV->uses()) {
      // Ignore instructions that are outside the loop.
      Instruction *UI = dyn_cast<Instruction>(U.getUser());
      if (!UI || !CurLoop->contains(UI))
        continue;

      // If there is an non-load/store instruction in the loop, we can't promote
      // it.
      if (LoadInst *Load = dyn_cast<LoadInst>(UI)) {
        if (!Load->isUnordered())
          return false;

        SawUnorderedAtomic |= Load->isAtomic();
        SawNotAtomic |= !Load->isAtomic();
        FoundLoadToPromote = true;

        Align InstAlignment = Load->getAlign();

        if (!LoadIsGuaranteedToExecute)
          LoadIsGuaranteedToExecute =
              SafetyInfo->isGuaranteedToExecute(*UI, DT, CurLoop);

        // Note that proving a load safe to speculate requires proving
        // sufficient alignment at the target location.  Proving it guaranteed
        // to execute does as well.  Thus we can increase our guaranteed
        // alignment as well.
        if (!DereferenceableInPH || (InstAlignment > Alignment))
          if (isSafeToExecuteUnconditionally(
                  *Load, DT, TLI, CurLoop, SafetyInfo, ORE,
                  Preheader->getTerminator(), AC, AllowSpeculation)) {
            DereferenceableInPH = true;
            Alignment = std::max(Alignment, InstAlignment);
          }
      } else if (const StoreInst *Store = dyn_cast<StoreInst>(UI)) {
        // Stores *of* the pointer are not interesting, only stores *to* the
        // pointer.
        if (U.getOperandNo() != StoreInst::getPointerOperandIndex())
          continue;
        if (!Store->isUnordered())
          return false;

        SawUnorderedAtomic |= Store->isAtomic();
        SawNotAtomic |= !Store->isAtomic();

        // If the store is guaranteed to execute, both properties are satisfied.
        // We may want to check if a store is guaranteed to execute even if we
        // already know that promotion is safe, since it may have higher
        // alignment than any other guaranteed stores, in which case we can
        // raise the alignment on the promoted store.
        Align InstAlignment = Store->getAlign();
        bool GuaranteedToExecute =
            SafetyInfo->isGuaranteedToExecute(*UI, DT, CurLoop);
        StoreIsGuanteedToExecute |= GuaranteedToExecute;
        if (GuaranteedToExecute) {
          DereferenceableInPH = true;
          if (StoreSafety == StoreSafetyUnknown)
            StoreSafety = StoreSafe;
          Alignment = std::max(Alignment, InstAlignment);
        }

        // If a store dominates all exit blocks, it is safe to sink.
        // As explained above, if an exit block was executed, a dominating
        // store must have been executed at least once, so we are not
        // introducing stores on paths that did not have them.
        // Note that this only looks at explicit exit blocks. If we ever
        // start sinking stores into unwind edges (see above), this will break.
        if (StoreSafety == StoreSafetyUnknown &&
            llvm::all_of(ExitBlocks, [&](BasicBlock *Exit) {
              return DT->dominates(Store->getParent(), Exit);
            }))
          StoreSafety = StoreSafe;

        // If the store is not guaranteed to execute, we may still get
        // deref info through it.
        if (!DereferenceableInPH) {
          DereferenceableInPH = isDereferenceableAndAlignedPointer(
              Store->getPointerOperand(), Store->getValueOperand()->getType(),
              Store->getAlign(), MDL, Preheader->getTerminator(), AC, DT, TLI);
        }
      } else
        continue; // Not a load or store.

      if (!AccessTy)
        AccessTy = getLoadStoreType(UI);
      else if (AccessTy != getLoadStoreType(UI))
        return false;

      // Merge the AA tags.
      if (LoopUses.empty()) {
        // On the first load/store, just take its AA tags.
        AATags = UI->getAAMetadata();
      } else if (AATags) {
        AATags = AATags.merge(UI->getAAMetadata());
      }

      LoopUses.push_back(UI);
    }
  }

  // If we found both an unordered atomic instruction and a non-atomic memory
  // access, bail.  We can't blindly promote non-atomic to atomic since we
  // might not be able to lower the result.  We can't downgrade since that
  // would violate memory model.  Also, align 0 is an error for atomics.
  if (SawUnorderedAtomic && SawNotAtomic)
    return false;

  // If we're inserting an atomic load in the preheader, we must be able to
  // lower it.  We're only guaranteed to be able to lower naturally aligned
  // atomics.
  if (SawUnorderedAtomic && Alignment < MDL.getTypeStoreSize(AccessTy))
    return false;

  // If we couldn't prove we can hoist the load, bail.
  if (!DereferenceableInPH) {
    LLVM_DEBUG(dbgs() << "Not promoting: Not dereferenceable in preheader\n");
    return false;
  }

  // We know we can hoist the load, but don't have a guaranteed store.
  // Check whether the location is writable and thread-local. If it is, then we
  // can insert stores along paths which originally didn't have them without
  // violating the memory model.
  if (StoreSafety == StoreSafetyUnknown) {
    Value *Object = getUnderlyingObject(SomePtr);
    bool ExplicitlyDereferenceableOnly;
    if (isWritableObject(Object, ExplicitlyDereferenceableOnly) &&
        (!ExplicitlyDereferenceableOnly ||
         isDereferenceablePointer(SomePtr, AccessTy, MDL)) &&
        isThreadLocalObject(Object, CurLoop, DT, TTI))
      StoreSafety = StoreSafe;
  }

  // If we've still failed to prove we can sink the store, hoist the load
  // only, if possible.
  if (StoreSafety != StoreSafe && !FoundLoadToPromote)
    // If we cannot hoist the load either, give up.
    return false;

  // Lets do the promotion!
  if (StoreSafety == StoreSafe) {
    LLVM_DEBUG(dbgs() << "LICM: Promoting load/store of the value: " << *SomePtr
                      << '\n');
    ++NumLoadStorePromoted;
  } else {
    LLVM_DEBUG(dbgs() << "LICM: Promoting load of the value: " << *SomePtr
                      << '\n');
    ++NumLoadPromoted;
  }

  ORE->emit([&]() {
    return OptimizationRemark(DEBUG_TYPE, "PromoteLoopAccessesToScalar",
                              LoopUses[0])
           << "Moving accesses to memory location out of the loop";
  });

  // Look at all the loop uses, and try to merge their locations.
  std::vector<DebugLoc> LoopUsesLocs;
  for (auto U : LoopUses)
    LoopUsesLocs.push_back(U->getDebugLoc());
  auto DL = DebugLoc::getMergedLocations(LoopUsesLocs);

  // We use the SSAUpdater interface to insert phi nodes as required.
  SmallVector<PHINode *, 16> NewPHIs;
  SSAUpdater SSA(&NewPHIs);
  LoopPromoter Promoter(SomePtr, LoopUses, SSA, ExitBlocks, InsertPts,
                        MSSAInsertPts, PIC, MSSAU, *LI, DL, Alignment,
                        SawUnorderedAtomic,
                        StoreIsGuanteedToExecute ? AATags : AAMDNodes(),
                        *SafetyInfo, StoreSafety == StoreSafe);

  // Set up the preheader to have a definition of the value.  It is the live-out
  // value from the preheader that uses in the loop will use.
  LoadInst *PreheaderLoad = nullptr;
  if (FoundLoadToPromote || !StoreIsGuanteedToExecute) {
    PreheaderLoad =
        new LoadInst(AccessTy, SomePtr, SomePtr->getName() + ".promoted",
                     Preheader->getTerminator()->getIterator());
    if (SawUnorderedAtomic)
      PreheaderLoad->setOrdering(AtomicOrdering::Unordered);
    PreheaderLoad->setAlignment(Alignment);
    PreheaderLoad->setDebugLoc(DebugLoc::getDropped());
    if (AATags && LoadIsGuaranteedToExecute)
      PreheaderLoad->setAAMetadata(AATags);

    MemoryAccess *PreheaderLoadMemoryAccess = MSSAU.createMemoryAccessInBB(
        PreheaderLoad, nullptr, PreheaderLoad->getParent(), MemorySSA::End);
    MemoryUse *NewMemUse = cast<MemoryUse>(PreheaderLoadMemoryAccess);
    MSSAU.insertUse(NewMemUse, /*RenameUses=*/true);
    SSA.AddAvailableValue(Preheader, PreheaderLoad);
  } else {
    SSA.AddAvailableValue(Preheader, PoisonValue::get(AccessTy));
  }

  if (VerifyMemorySSA)
    MSSAU.getMemorySSA()->verifyMemorySSA();
  // Rewrite all the loads in the loop and remember all the definitions from
  // stores in the loop.
  Promoter.run(LoopUses);

  if (VerifyMemorySSA)
    MSSAU.getMemorySSA()->verifyMemorySSA();
  // If the SSAUpdater didn't use the load in the preheader, just zap it now.
  if (PreheaderLoad && PreheaderLoad->use_empty())
    eraseInstruction(*PreheaderLoad, *SafetyInfo, MSSAU);

  return true;
}

static void foreachMemoryAccess(MemorySSA *MSSA, Loop *L,
                                function_ref<void(Instruction *)> Fn) {
  for (const BasicBlock *BB : L->blocks())
    if (const auto *Accesses = MSSA->getBlockAccesses(BB))
      for (const auto &Access : *Accesses)
        if (const auto *MUD = dyn_cast<MemoryUseOrDef>(&Access))
          Fn(MUD->getMemoryInst());
}

// The bool indicates whether there might be reads outside the set, in which
// case only loads may be promoted.
static SmallVector<PointersAndHasReadsOutsideSet, 0>
collectPromotionCandidates(MemorySSA *MSSA, AliasAnalysis *AA, Loop *L) {
  BatchAAResults BatchAA(*AA);
  AliasSetTracker AST(BatchAA);

  auto IsPotentiallyPromotable = [L](const Instruction *I) {
    if (const auto *SI = dyn_cast<StoreInst>(I)) {
      const Value *PtrOp = SI->getPointerOperand();
      return !isa<ConstantData>(PtrOp) && L->isLoopInvariant(PtrOp);
    }
    if (const auto *LI = dyn_cast<LoadInst>(I)) {
      const Value *PtrOp = LI->getPointerOperand();
      return !isa<ConstantData>(PtrOp) && L->isLoopInvariant(PtrOp);
    }
    return false;
  };

  // Populate AST with potentially promotable accesses.
  SmallPtrSet<Value *, 16> AttemptingPromotion;
  foreachMemoryAccess(MSSA, L, [&](Instruction *I) {
    if (IsPotentiallyPromotable(I)) {
      AttemptingPromotion.insert(I);
      AST.add(I);
    }
  });

  // We're only interested in must-alias sets that contain a mod.
  SmallVector<PointerIntPair<const AliasSet *, 1, bool>, 8> Sets;
  for (AliasSet &AS : AST)
    if (!AS.isForwardingAliasSet() && AS.isMod() && AS.isMustAlias())
      Sets.push_back({&AS, false});

  if (Sets.empty())
    return {}; // Nothing to promote...

  // Discard any sets for which there is an aliasing non-promotable access.
  foreachMemoryAccess(MSSA, L, [&](Instruction *I) {
    if (AttemptingPromotion.contains(I))
      return;

    llvm::erase_if(Sets, [&](PointerIntPair<const AliasSet *, 1, bool> &Pair) {
      ModRefInfo MR = Pair.getPointer()->aliasesUnknownInst(I, BatchAA);
      // Cannot promote if there are writes outside the set.
      if (isModSet(MR))
        return true;
      if (isRefSet(MR)) {
        // Remember reads outside the set.
        Pair.setInt(true);
        // If this is a mod-only set and there are reads outside the set,
        // we will not be able to promote, so bail out early.
        return !Pair.getPointer()->isRef();
      }
      return false;
    });
  });

  SmallVector<std::pair<SmallSetVector<Value *, 8>, bool>, 0> Result;
  for (auto [Set, HasReadsOutsideSet] : Sets) {
    SmallSetVector<Value *, 8> PointerMustAliases;
    for (const auto &MemLoc : *Set)
      PointerMustAliases.insert(const_cast<Value *>(MemLoc.Ptr));
    Result.emplace_back(std::move(PointerMustAliases), HasReadsOutsideSet);
  }

  return Result;
}

// For a given store instruction or writeonly call instruction, this function
// checks that there are no read or writes that conflict with the memory
// access in the instruction
static bool noConflictingReadWrites(Instruction *I, MemorySSA *MSSA,
                                    AAResults *AA, Loop *CurLoop,
                                    SinkAndHoistLICMFlags &Flags) {
  assert(isa<CallInst>(*I) || isa<StoreInst>(*I));
  // If there are more accesses than the Promotion cap, then give up as we're
  // not walking a list that long.
  if (Flags.tooManyMemoryAccesses())
    return false;

  auto *IMD = MSSA->getMemoryAccess(I);
  BatchAAResults BAA(*AA);
  auto *Source = getClobberingMemoryAccess(*MSSA, BAA, Flags, IMD);
  // Make sure there are no clobbers inside the loop.
  if (!MSSA->isLiveOnEntryDef(Source) && CurLoop->contains(Source->getBlock()))
    return false;

  // If there are interfering Uses (i.e. their defining access is in the
  // loop), or ordered loads (stored as Defs!), don't move this store.
  // Could do better here, but this is conservatively correct.
  // TODO: Cache set of Uses on the first walk in runOnLoop, update when
  // moving accesses. Can also extend to dominating uses.
  for (auto *BB : CurLoop->getBlocks()) {
    auto *Accesses = MSSA->getBlockAccesses(BB);
    if (!Accesses)
      continue;
    for (const auto &MA : *Accesses)
      if (const auto *MU = dyn_cast<MemoryUse>(&MA)) {
        auto *MD = getClobberingMemoryAccess(*MSSA, BAA, Flags,
                                             const_cast<MemoryUse *>(MU));
        if (!MSSA->isLiveOnEntryDef(MD) && CurLoop->contains(MD->getBlock()))
          return false;
        // Disable hoisting past potentially interfering loads. Optimized
        // Uses may point to an access outside the loop, as getClobbering
        // checks the previous iteration when walking the backedge.
        // FIXME: More precise: no Uses that alias I.
        if (!Flags.getIsSink() && !MSSA->dominates(IMD, MU))
          return false;
      } else if (const auto *MD = dyn_cast<MemoryDef>(&MA)) {
        if (auto *LI = dyn_cast<LoadInst>(MD->getMemoryInst())) {
          (void)LI; // Silence warning.
          assert(!LI->isUnordered() && "Expected unordered load");
          return false;
        }
        // Any call, while it may not be clobbering I, it may be a use.
        if (auto *CI = dyn_cast<CallInst>(MD->getMemoryInst())) {
          // Check if the call may read from the memory location written
          // to by I. Check CI's attributes and arguments; the number of
          // such checks performed is limited above by NoOfMemAccTooLarge.
          if (auto *SI = dyn_cast<StoreInst>(I)) {
            ModRefInfo MRI = BAA.getModRefInfo(CI, MemoryLocation::get(SI));
            if (isModOrRefSet(MRI))
              return false;
          } else {
            auto *SCI = cast<CallInst>(I);
            // If the instruction we are wanting to hoist is also a call
            // instruction then we need not check mod/ref info with itself
            if (SCI == CI)
              continue;
            ModRefInfo MRI = BAA.getModRefInfo(CI, SCI);
            if (isModOrRefSet(MRI))
              return false;
          }
        }
      }
  }
  return true;
}

static bool pointerInvalidatedByLoop(MemorySSA *MSSA, MemoryUse *MU,
                                     Loop *CurLoop, Instruction &I,
                                     SinkAndHoistLICMFlags &Flags,
                                     bool InvariantGroup) {
  // For hoisting, use the walker to determine safety
  if (!Flags.getIsSink()) {
    // If hoisting an invariant group, we only need to check that there
    // is no store to the loaded pointer between the start of the loop,
    // and the load (since all values must be the same).

    // This can be checked in two conditions:
    // 1) if the memoryaccess is outside the loop
    // 2) the earliest access is at the loop header,
    // if the memory loaded is the phi node

    BatchAAResults BAA(MSSA->getAA());
    MemoryAccess *Source = getClobberingMemoryAccess(*MSSA, BAA, Flags, MU);
    return !MSSA->isLiveOnEntryDef(Source) &&
           CurLoop->contains(Source->getBlock()) &&
           !(InvariantGroup && Source->getBlock() == CurLoop->getHeader() && isa<MemoryPhi>(Source));
  }

  // For sinking, we'd need to check all Defs below this use. The getClobbering
  // call will look on the backedge of the loop, but will check aliasing with
  // the instructions on the previous iteration.
  // For example:
  // for (i ... )
  //   load a[i] ( Use (LoE)
  //   store a[i] ( 1 = Def (2), with 2 = Phi for the loop.
  //   i++;
  // The load sees no clobbering inside the loop, as the backedge alias check
  // does phi translation, and will check aliasing against store a[i-1].
  // However sinking the load outside the loop, below the store is incorrect.

  // For now, only sink if there are no Defs in the loop, and the existing ones
  // precede the use and are in the same block.
  // FIXME: Increase precision: Safe to sink if Use post dominates the Def;
  // needs PostDominatorTreeAnalysis.
  // FIXME: More precise: no Defs that alias this Use.
  if (Flags.tooManyMemoryAccesses())
    return true;
  for (auto *BB : CurLoop->getBlocks())
    if (pointerInvalidatedByBlock(*BB, *MSSA, *MU))
      return true;
  // When sinking, the source block may not be part of the loop so check it.
  if (!CurLoop->contains(&I))
    return pointerInvalidatedByBlock(*I.getParent(), *MSSA, *MU);

  return false;
}

bool pointerInvalidatedByBlock(BasicBlock &BB, MemorySSA &MSSA, MemoryUse &MU) {
  if (const auto *Accesses = MSSA.getBlockDefs(&BB))
    for (const auto &MA : *Accesses)
      if (const auto *MD = dyn_cast<MemoryDef>(&MA))
        if (MU.getBlock() != MD->getBlock() || !MSSA.locallyDominates(MD, &MU))
          return true;
  return false;
}

/// Try to simplify things like (A < INV_1 AND icmp A < INV_2) into (A <
/// min(INV_1, INV_2)), if INV_1 and INV_2 are both loop invariants and their
/// minimun can be computed outside of loop, and X is not a loop-invariant.
static bool hoistMinMax(Instruction &I, Loop &L, ICFLoopSafetyInfo &SafetyInfo,
                        MemorySSAUpdater &MSSAU) {
  bool Inverse = false;
  using namespace PatternMatch;
  Value *Cond1, *Cond2;
  if (match(&I, m_LogicalOr(m_Value(Cond1), m_Value(Cond2)))) {
    Inverse = true;
  } else if (match(&I, m_LogicalAnd(m_Value(Cond1), m_Value(Cond2)))) {
    // Do nothing
  } else
    return false;

  auto MatchICmpAgainstInvariant = [&](Value *C, CmpPredicate &P, Value *&LHS,
                                       Value *&RHS) {
    if (!match(C, m_OneUse(m_ICmp(P, m_Value(LHS), m_Value(RHS)))))
      return false;
    if (!LHS->getType()->isIntegerTy())
      return false;
    if (!ICmpInst::isRelational(P))
      return false;
    if (L.isLoopInvariant(LHS)) {
      std::swap(LHS, RHS);
      P = ICmpInst::getSwappedPredicate(P);
    }
    if (L.isLoopInvariant(LHS) || !L.isLoopInvariant(RHS))
      return false;
    if (Inverse)
      P = ICmpInst::getInversePredicate(P);
    return true;
  };
  CmpPredicate P1, P2;
  Value *LHS1, *LHS2, *RHS1, *RHS2;
  if (!MatchICmpAgainstInvariant(Cond1, P1, LHS1, RHS1) ||
      !MatchICmpAgainstInvariant(Cond2, P2, LHS2, RHS2))
    return false;
  auto MatchingPred = CmpPredicate::getMatching(P1, P2);
  if (!MatchingPred || LHS1 != LHS2)
    return false;

  // Everything is fine, we can do the transform.
  bool UseMin = ICmpInst::isLT(*MatchingPred) || ICmpInst::isLE(*MatchingPred);
  assert(
      (UseMin || ICmpInst::isGT(*MatchingPred) ||
       ICmpInst::isGE(*MatchingPred)) &&
      "Relational predicate is either less (or equal) or greater (or equal)!");
  Intrinsic::ID id = ICmpInst::isSigned(*MatchingPred)
                         ? (UseMin ? Intrinsic::smin : Intrinsic::smax)
                         : (UseMin ? Intrinsic::umin : Intrinsic::umax);
  auto *Preheader = L.getLoopPreheader();
  assert(Preheader && "Loop is not in simplify form?");
  IRBuilder<> Builder(Preheader->getTerminator());
  // We are about to create a new guaranteed use for RHS2 which might not exist
  // before (if it was a non-taken input of logical and/or instruction). If it
  // was poison, we need to freeze it. Note that no new use for LHS and RHS1 are
  // introduced, so they don't need this.
  if (isa<SelectInst>(I))
    RHS2 = Builder.CreateFreeze(RHS2, RHS2->getName() + ".fr");
  Value *NewRHS = Builder.CreateBinaryIntrinsic(
      id, RHS1, RHS2, nullptr,
      StringRef("invariant.") +
          (ICmpInst::isSigned(*MatchingPred) ? "s" : "u") +
          (UseMin ? "min" : "max"));
  Builder.SetInsertPoint(&I);
  ICmpInst::Predicate P = *MatchingPred;
  if (Inverse)
    P = ICmpInst::getInversePredicate(P);
  Value *NewCond = Builder.CreateICmp(P, LHS1, NewRHS);
  NewCond->takeName(&I);
  I.replaceAllUsesWith(NewCond);
  eraseInstruction(I, SafetyInfo, MSSAU);
  Instruction &CondI1 = *cast<Instruction>(Cond1);
  Instruction &CondI2 = *cast<Instruction>(Cond2);
  salvageDebugInfo(CondI1);
  salvageDebugInfo(CondI2);
  eraseInstruction(CondI1, SafetyInfo, MSSAU);
  eraseInstruction(CondI2, SafetyInfo, MSSAU);
  return true;
}

/// Reassociate gep (gep ptr, idx1), idx2 to gep (gep ptr, idx2), idx1 if
/// this allows hoisting the inner GEP.
static bool hoistGEP(Instruction &I, Loop &L, ICFLoopSafetyInfo &SafetyInfo,
                     MemorySSAUpdater &MSSAU, AssumptionCache *AC,
                     DominatorTree *DT) {
  auto *GEP = dyn_cast<GetElementPtrInst>(&I);
  if (!GEP)
    return false;

  auto *Src = dyn_cast<GetElementPtrInst>(GEP->getPointerOperand());
  if (!Src || !Src->hasOneUse() || !L.contains(Src))
    return false;

  Value *SrcPtr = Src->getPointerOperand();
  auto LoopInvariant = [&](Value *V) { return L.isLoopInvariant(V); };
  if (!L.isLoopInvariant(SrcPtr) || !all_of(GEP->indices(), LoopInvariant))
    return false;

  // This can only happen if !AllowSpeculation, otherwise this would already be
  // handled.
  // FIXME: Should we respect AllowSpeculation in these reassociation folds?
  // The flag exists to prevent metadata dropping, which is not relevant here.
  if (all_of(Src->indices(), LoopInvariant))
    return false;

  // The swapped GEPs are inbounds if both original GEPs are inbounds
  // and the sign of the offsets is the same. For simplicity, only
  // handle both offsets being non-negative.
  const DataLayout &DL = GEP->getDataLayout();
  auto NonNegative = [&](Value *V) {
    return isKnownNonNegative(V, SimplifyQuery(DL, DT, AC, GEP));
  };
  bool IsInBounds = Src->isInBounds() && GEP->isInBounds() &&
                    all_of(Src->indices(), NonNegative) &&
                    all_of(GEP->indices(), NonNegative);

  BasicBlock *Preheader = L.getLoopPreheader();
  IRBuilder<> Builder(Preheader->getTerminator());
  Value *NewSrc = Builder.CreateGEP(GEP->getSourceElementType(), SrcPtr,
                                    SmallVector<Value *>(GEP->indices()),
                                    "invariant.gep", IsInBounds);
  Builder.SetInsertPoint(GEP);
  Value *NewGEP = Builder.CreateGEP(Src->getSourceElementType(), NewSrc,
                                    SmallVector<Value *>(Src->indices()), "gep",
                                    IsInBounds);
  GEP->replaceAllUsesWith(NewGEP);
  eraseInstruction(*GEP, SafetyInfo, MSSAU);
  salvageDebugInfo(*Src);
  eraseInstruction(*Src, SafetyInfo, MSSAU);
  return true;
}

/// Try to turn things like "LV + C1 < C2" into "LV < C2 - C1". Here
/// C1 and C2 are loop invariants and LV is a loop-variant.
static bool hoistAdd(ICmpInst::Predicate Pred, Value *VariantLHS,
                     Value *InvariantRHS, ICmpInst &ICmp, Loop &L,
                     ICFLoopSafetyInfo &SafetyInfo, MemorySSAUpdater &MSSAU,
                     AssumptionCache *AC, DominatorTree *DT) {
  assert(!L.isLoopInvariant(VariantLHS) && "Precondition.");
  assert(L.isLoopInvariant(InvariantRHS) && "Precondition.");

  bool IsSigned = ICmpInst::isSigned(Pred);

  // Try to represent VariantLHS as sum of invariant and variant operands.
  using namespace PatternMatch;
  Value *VariantOp, *InvariantOp;
  if (IsSigned &&
      !match(VariantLHS, m_NSWAdd(m_Value(VariantOp), m_Value(InvariantOp))))
    return false;
  if (!IsSigned &&
      !match(VariantLHS, m_NUWAdd(m_Value(VariantOp), m_Value(InvariantOp))))
    return false;

  // LHS itself is a loop-variant, try to represent it in the form:
  // "VariantOp + InvariantOp". If it is possible, then we can reassociate.
  if (L.isLoopInvariant(VariantOp))
    std::swap(VariantOp, InvariantOp);
  if (L.isLoopInvariant(VariantOp) || !L.isLoopInvariant(InvariantOp))
    return false;

  // In order to turn "LV + C1 < C2" into "LV < C2 - C1", we need to be able to
  // freely move values from left side of inequality to right side (just as in
  // normal linear arithmetics). Overflows make things much more complicated, so
  // we want to avoid this.
  auto &DL = L.getHeader()->getDataLayout();
  SimplifyQuery SQ(DL, DT, AC, &ICmp);
  if (IsSigned && computeOverflowForSignedSub(InvariantRHS, InvariantOp, SQ) !=
                      llvm::OverflowResult::NeverOverflows)
    return false;
  if (!IsSigned &&
      computeOverflowForUnsignedSub(InvariantRHS, InvariantOp, SQ) !=
          llvm::OverflowResult::NeverOverflows)
    return false;
  auto *Preheader = L.getLoopPreheader();
  assert(Preheader && "Loop is not in simplify form?");
  IRBuilder<> Builder(Preheader->getTerminator());
  Value *NewCmpOp =
      Builder.CreateSub(InvariantRHS, InvariantOp, "invariant.op",
                        /*HasNUW*/ !IsSigned, /*HasNSW*/ IsSigned);
  ICmp.setPredicate(Pred);
  ICmp.setOperand(0, VariantOp);
  ICmp.setOperand(1, NewCmpOp);

  Instruction &DeadI = cast<Instruction>(*VariantLHS);
  salvageDebugInfo(DeadI);
  eraseInstruction(DeadI, SafetyInfo, MSSAU);
  return true;
}

/// Try to reassociate and hoist the following two patterns:
/// LV - C1 < C2 --> LV < C1 + C2,
/// C1 - LV < C2 --> LV > C1 - C2.
static bool hoistSub(ICmpInst::Predicate Pred, Value *VariantLHS,
                     Value *InvariantRHS, ICmpInst &ICmp, Loop &L,
                     ICFLoopSafetyInfo &SafetyInfo, MemorySSAUpdater &MSSAU,
                     AssumptionCache *AC, DominatorTree *DT) {
  assert(!L.isLoopInvariant(VariantLHS) && "Precondition.");
  assert(L.isLoopInvariant(InvariantRHS) && "Precondition.");

  bool IsSigned = ICmpInst::isSigned(Pred);

  // Try to represent VariantLHS as sum of invariant and variant operands.
  using namespace PatternMatch;
  Value *VariantOp, *InvariantOp;
  if (IsSigned &&
      !match(VariantLHS, m_NSWSub(m_Value(VariantOp), m_Value(InvariantOp))))
    return false;
  if (!IsSigned &&
      !match(VariantLHS, m_NUWSub(m_Value(VariantOp), m_Value(InvariantOp))))
    return false;

  bool VariantSubtracted = false;
  // LHS itself is a loop-variant, try to represent it in the form:
  // "VariantOp + InvariantOp". If it is possible, then we can reassociate. If
  // the variant operand goes with minus, we use a slightly different scheme.
  if (L.isLoopInvariant(VariantOp)) {
    std::swap(VariantOp, InvariantOp);
    VariantSubtracted = true;
    Pred = ICmpInst::getSwappedPredicate(Pred);
  }
  if (L.isLoopInvariant(VariantOp) || !L.isLoopInvariant(InvariantOp))
    return false;

  // In order to turn "LV - C1 < C2" into "LV < C2 + C1", we need to be able to
  // freely move values from left side of inequality to right side (just as in
  // normal linear arithmetics). Overflows make things much more complicated, so
  // we want to avoid this. Likewise, for "C1 - LV < C2" we need to prove that
  // "C1 - C2" does not overflow.
  auto &DL = L.getHeader()->getDataLayout();
  SimplifyQuery SQ(DL, DT, AC, &ICmp);
  if (VariantSubtracted && IsSigned) {
    // C1 - LV < C2 --> LV > C1 - C2
    if (computeOverflowForSignedSub(InvariantOp, InvariantRHS, SQ) !=
        llvm::OverflowResult::NeverOverflows)
      return false;
  } else if (VariantSubtracted && !IsSigned) {
    // C1 - LV < C2 --> LV > C1 - C2
    if (computeOverflowForUnsignedSub(InvariantOp, InvariantRHS, SQ) !=
        llvm::OverflowResult::NeverOverflows)
      return false;
  } else if (!VariantSubtracted && IsSigned) {
    // LV - C1 < C2 --> LV < C1 + C2
    if (computeOverflowForSignedAdd(InvariantOp, InvariantRHS, SQ) !=
        llvm::OverflowResult::NeverOverflows)
      return false;
  } else { // !VariantSubtracted && !IsSigned
    // LV - C1 < C2 --> LV < C1 + C2
    if (computeOverflowForUnsignedAdd(InvariantOp, InvariantRHS, SQ) !=
        llvm::OverflowResult::NeverOverflows)
      return false;
  }
  auto *Preheader = L.getLoopPreheader();
  assert(Preheader && "Loop is not in simplify form?");
  IRBuilder<> Builder(Preheader->getTerminator());
  Value *NewCmpOp =
      VariantSubtracted
          ? Builder.CreateSub(InvariantOp, InvariantRHS, "invariant.op",
                              /*HasNUW*/ !IsSigned, /*HasNSW*/ IsSigned)
          : Builder.CreateAdd(InvariantOp, InvariantRHS, "invariant.op",
                              /*HasNUW*/ !IsSigned, /*HasNSW*/ IsSigned);
  ICmp.setPredicate(Pred);
  ICmp.setOperand(0, VariantOp);
  ICmp.setOperand(1, NewCmpOp);

  Instruction &DeadI = cast<Instruction>(*VariantLHS);
  salvageDebugInfo(DeadI);
  eraseInstruction(DeadI, SafetyInfo, MSSAU);
  return true;
}

/// Reassociate and hoist add/sub expressions.
static bool hoistAddSub(Instruction &I, Loop &L, ICFLoopSafetyInfo &SafetyInfo,
                        MemorySSAUpdater &MSSAU, AssumptionCache *AC,
                        DominatorTree *DT) {
  using namespace PatternMatch;
  CmpPredicate Pred;
  Value *LHS, *RHS;
  if (!match(&I, m_ICmp(Pred, m_Value(LHS), m_Value(RHS))))
    return false;

  // Put variant operand to LHS position.
  if (L.isLoopInvariant(LHS)) {
    std::swap(LHS, RHS);
    Pred = ICmpInst::getSwappedPredicate(Pred);
  }
  // We want to delete the initial operation after reassociation, so only do it
  // if it has no other uses.
  if (L.isLoopInvariant(LHS) || !L.isLoopInvariant(RHS) || !LHS->hasOneUse())
    return false;

  // TODO: We could go with smarter context, taking common dominator of all I's
  // users instead of I itself.
  if (hoistAdd(Pred, LHS, RHS, cast<ICmpInst>(I), L, SafetyInfo, MSSAU, AC, DT))
    return true;

  if (hoistSub(Pred, LHS, RHS, cast<ICmpInst>(I), L, SafetyInfo, MSSAU, AC, DT))
    return true;

  return false;
}

static bool isReassociableOp(Instruction *I, unsigned IntOpcode,
                             unsigned FPOpcode) {
  if (I->getOpcode() == IntOpcode)
    return true;
  if (I->getOpcode() == FPOpcode && I->hasAllowReassoc() &&
      I->hasNoSignedZeros())
    return true;
  return false;
}

/// Try to reassociate expressions like ((A1 * B1) + (A2 * B2) + ...) * C where
/// A1, A2, ... and C are loop invariants into expressions like
/// ((A1 * C * B1) + (A2 * C * B2) + ...) and hoist the (A1 * C), (A2 * C), ...
/// invariant expressions. This functions returns true only if any hoisting has
/// actually occured.
static bool hoistMulAddAssociation(Instruction &I, Loop &L,
                                   ICFLoopSafetyInfo &SafetyInfo,
                                   MemorySSAUpdater &MSSAU, AssumptionCache *AC,
                                   DominatorTree *DT) {
  if (!isReassociableOp(&I, Instruction::Mul, Instruction::FMul))
    return false;
  Value *VariantOp = I.getOperand(0);
  Value *InvariantOp = I.getOperand(1);
  if (L.isLoopInvariant(VariantOp))
    std::swap(VariantOp, InvariantOp);
  if (L.isLoopInvariant(VariantOp) || !L.isLoopInvariant(InvariantOp))
    return false;
  Value *Factor = InvariantOp;

  // First, we need to make sure we should do the transformation.
  SmallVector<Use *> Changes;
  SmallVector<BinaryOperator *> Adds;
  SmallVector<BinaryOperator *> Worklist;
  if (BinaryOperator *VariantBinOp = dyn_cast<BinaryOperator>(VariantOp))
    Worklist.push_back(VariantBinOp);
  while (!Worklist.empty()) {
    BinaryOperator *BO = Worklist.pop_back_val();
    if (!BO->hasOneUse())
      return false;
    if (isReassociableOp(BO, Instruction::Add, Instruction::FAdd) &&
        isa<BinaryOperator>(BO->getOperand(0)) &&
        isa<BinaryOperator>(BO->getOperand(1))) {
      Worklist.push_back(cast<BinaryOperator>(BO->getOperand(0)));
      Worklist.push_back(cast<BinaryOperator>(BO->getOperand(1)));
      Adds.push_back(BO);
      continue;
    }
    if (!isReassociableOp(BO, Instruction::Mul, Instruction::FMul) ||
        L.isLoopInvariant(BO))
      return false;
    Use &U0 = BO->getOperandUse(0);
    Use &U1 = BO->getOperandUse(1);
    if (L.isLoopInvariant(U0))
      Changes.push_back(&U0);
    else if (L.isLoopInvariant(U1))
      Changes.push_back(&U1);
    else
      return false;
    unsigned Limit = I.getType()->isIntOrIntVectorTy()
                         ? IntAssociationUpperLimit
                         : FPAssociationUpperLimit;
    if (Changes.size() > Limit)
      return false;
  }
  if (Changes.empty())
    return false;

  // Drop the poison flags for any adds we looked through.
  if (I.getType()->isIntOrIntVectorTy()) {
    for (auto *Add : Adds)
      Add->dropPoisonGeneratingFlags();
  }

  // We know we should do it so let's do the transformation.
  auto *Preheader = L.getLoopPreheader();
  assert(Preheader && "Loop is not in simplify form?");
  IRBuilder<> Builder(Preheader->getTerminator());
  for (auto *U : Changes) {
    assert(L.isLoopInvariant(U->get()));
    auto *Ins = cast<BinaryOperator>(U->getUser());
    Value *Mul;
    if (I.getType()->isIntOrIntVectorTy()) {
      Mul = Builder.CreateMul(U->get(), Factor, "factor.op.mul");
      // Drop the poison flags on the original multiply.
      Ins->dropPoisonGeneratingFlags();
    } else
      Mul = Builder.CreateFMulFMF(U->get(), Factor, Ins, "factor.op.fmul");

    // Rewrite the reassociable instruction.
    unsigned OpIdx = U->getOperandNo();
    auto *LHS = OpIdx == 0 ? Mul : Ins->getOperand(0);
    auto *RHS = OpIdx == 1 ? Mul : Ins->getOperand(1);
    auto *NewBO =
        BinaryOperator::Create(Ins->getOpcode(), LHS, RHS,
                               Ins->getName() + ".reass", Ins->getIterator());
    NewBO->setDebugLoc(DebugLoc::getDropped());
    NewBO->copyIRFlags(Ins);
    if (VariantOp == Ins)
      VariantOp = NewBO;
    Ins->replaceAllUsesWith(NewBO);
    eraseInstruction(*Ins, SafetyInfo, MSSAU);
  }

  I.replaceAllUsesWith(VariantOp);
  eraseInstruction(I, SafetyInfo, MSSAU);
  return true;
}

/// Reassociate associative binary expressions of the form
///
/// 1. "(LV op C1) op C2" ==> "LV op (C1 op C2)"
/// 2. "(C1 op LV) op C2" ==> "LV op (C1 op C2)"
/// 3. "C2 op (C1 op LV)" ==> "LV op (C1 op C2)"
/// 4. "C2 op (LV op C1)" ==> "LV op (C1 op C2)"
///
/// where op is an associative BinOp, LV is a loop variant, and C1 and C2 are
/// loop invariants that we want to hoist, noting that associativity implies
/// commutativity.
static bool hoistBOAssociation(Instruction &I, Loop &L,
                               ICFLoopSafetyInfo &SafetyInfo,
                               MemorySSAUpdater &MSSAU, AssumptionCache *AC,
                               DominatorTree *DT) {
  auto *BO = dyn_cast<BinaryOperator>(&I);
  if (!BO || !BO->isAssociative())
    return false;

  Instruction::BinaryOps Opcode = BO->getOpcode();
  bool LVInRHS = L.isLoopInvariant(BO->getOperand(0));
  auto *BO0 = dyn_cast<BinaryOperator>(BO->getOperand(LVInRHS));
  if (!BO0 || BO0->getOpcode() != Opcode || !BO0->isAssociative() ||
      BO0->hasNUsesOrMore(3))
    return false;

  Value *LV = BO0->getOperand(0);
  Value *C1 = BO0->getOperand(1);
  Value *C2 = BO->getOperand(!LVInRHS);

  assert(BO->isCommutative() && BO0->isCommutative() &&
         "Associativity implies commutativity");
  if (L.isLoopInvariant(LV) && !L.isLoopInvariant(C1))
    std::swap(LV, C1);
  if (L.isLoopInvariant(LV) || !L.isLoopInvariant(C1) || !L.isLoopInvariant(C2))
    return false;

  auto *Preheader = L.getLoopPreheader();
  assert(Preheader && "Loop is not in simplify form?");

  IRBuilder<> Builder(Preheader->getTerminator());
  auto *Inv = Builder.CreateBinOp(Opcode, C1, C2, "invariant.op");

  auto *NewBO = BinaryOperator::Create(
      Opcode, LV, Inv, BO->getName() + ".reass", BO->getIterator());
  NewBO->setDebugLoc(DebugLoc::getDropped());

  if (Opcode == Instruction::FAdd || Opcode == Instruction::FMul) {
    // Intersect FMF flags for FADD and FMUL.
    FastMathFlags Intersect = BO->getFastMathFlags() & BO0->getFastMathFlags();
    if (auto *I = dyn_cast<Instruction>(Inv))
      I->setFastMathFlags(Intersect);
    NewBO->setFastMathFlags(Intersect);
  } else {
    OverflowTracking Flags;
    Flags.AllKnownNonNegative = false;
    Flags.AllKnownNonZero = false;
    Flags.mergeFlags(*BO);
    Flags.mergeFlags(*BO0);
    // If `Inv` was not constant-folded, a new Instruction has been created.
    if (auto *I = dyn_cast<Instruction>(Inv))
      Flags.applyFlags(*I);
    Flags.applyFlags(*NewBO);
  }

  BO->replaceAllUsesWith(NewBO);
  eraseInstruction(*BO, SafetyInfo, MSSAU);

  // (LV op C1) might not be erased if it has more uses than the one we just
  // replaced.
  if (BO0->use_empty()) {
    salvageDebugInfo(*BO0);
    eraseInstruction(*BO0, SafetyInfo, MSSAU);
  }

  return true;
}

static bool hoistArithmetics(Instruction &I, Loop &L,
                             ICFLoopSafetyInfo &SafetyInfo,
                             MemorySSAUpdater &MSSAU, AssumptionCache *AC,
                             DominatorTree *DT) {
  // Optimize complex patterns, such as (x < INV1 && x < INV2), turning them
  // into (x < min(INV1, INV2)), and hoisting the invariant part of this
  // expression out of the loop.
  if (hoistMinMax(I, L, SafetyInfo, MSSAU)) {
    ++NumHoisted;
    ++NumMinMaxHoisted;
    return true;
  }

  // Try to hoist GEPs by reassociation.
  if (hoistGEP(I, L, SafetyInfo, MSSAU, AC, DT)) {
    ++NumHoisted;
    ++NumGEPsHoisted;
    return true;
  }

  // Try to hoist add/sub's by reassociation.
  if (hoistAddSub(I, L, SafetyInfo, MSSAU, AC, DT)) {
    ++NumHoisted;
    ++NumAddSubHoisted;
    return true;
  }

  bool IsInt = I.getType()->isIntOrIntVectorTy();
  if (hoistMulAddAssociation(I, L, SafetyInfo, MSSAU, AC, DT)) {
    ++NumHoisted;
    if (IsInt)
      ++NumIntAssociationsHoisted;
    else
      ++NumFPAssociationsHoisted;
    return true;
  }

  if (hoistBOAssociation(I, L, SafetyInfo, MSSAU, AC, DT)) {
    ++NumHoisted;
    ++NumBOAssociationsHoisted;
    return true;
  }

  return false;
}

/// Little predicate that returns true if the specified basic block is in
/// a subloop of the current one, not the current one itself.
///
static bool inSubLoop(BasicBlock *BB, Loop *CurLoop, LoopInfo *LI) {
  assert(CurLoop->contains(BB) && "Only valid if BB is IN the loop");
  return LI->getLoopFor(BB) != CurLoop;
}
