//===-- 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."));

extern cl::opt<bool> ProfcheckDisableMetadataFixes;

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, HasCoroSuspendInst);

  // 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.
    auto *NewBI =
        BranchInst::Create(HoistTrueDest, HoistFalseDest, BI->getCondition(),
                           HoistTarget->getTerminator()->getIterator());
    HoistTarget->getTerminator()->eraseFromParent();
    // md_prof should also come from the original branch - since the
    // condition was hoisted, the branch probabilities shouldn't change.
    if (!ProfcheckDisableMetadataFixes)
      NewBI->copyMetadata(*BI, {LLVMContext::MD_prof});
    // FIXME: Issue #152767: debug info should also be the same as the
    // original branch, **if** the user explicitly indicated that.
    NewBI->setDebugLoc(HoistTarget->getTerminator()->getDebugLoc());

    ++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, bool HasCoroSuspendInst) {
  // 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, HasCoroSuspendInst) &&
          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, HasCoroSuspendInst) &&
          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()) {
      // Might have stale MemoryDef for call that was later inferred to be
      // read-only.
      auto *MU = dyn_cast<MemoryUse>(MSSA->getMemoryAccess(CI));
      if (!MU)
        return false;

      // If we can prove there are no writes to the memory read by the call, we
      // can hoist or sink.
      return !pointerInvalidatedByLoop(
          MSSA, MU, 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)) {
    if (ProfcheckDisableMetadataFixes)
      I.dropUBImplyingAttrsAndMetadata();
    else
      I.dropUBImplyingAttrsAndMetadata({LLVMContext::MD_prof});
  }

  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;

  // Do not try to hoist a constant GEP out of the loop via reassociation.
  // Constant GEPs can often be folded into addressing modes, and reassociating
  // them may inhibit CSE of a common base.
  if (GEP->hasAllConstantIndices())
    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(BO0->getType()->isIntegerTy() ? 2 : 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;
}
