//===- MachineLICM.cpp - Machine 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 on machine instructions. We
// attempt to remove as much code from the body of a loop as possible.
//
// This pass is not intended to be a replacement or a complete alternative
// for the LLVM-IR-level LICM pass. It is only designed to hoist simple
// constructs that are not exposed before lowering and instruction selection.
//
//===----------------------------------------------------------------------===//

#include "llvm/CodeGen/MachineLICM.h"
#include "llvm/ADT/BitVector.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/Statistic.h"
#include "llvm/Analysis/AliasAnalysis.h"
#include "llvm/CodeGen/LazyMachineBlockFrequencyInfo.h"
#include "llvm/CodeGen/MachineBasicBlock.h"
#include "llvm/CodeGen/MachineBlockFrequencyInfo.h"
#include "llvm/CodeGen/MachineDomTreeUpdater.h"
#include "llvm/CodeGen/MachineDominators.h"
#include "llvm/CodeGen/MachineFrameInfo.h"
#include "llvm/CodeGen/MachineFunction.h"
#include "llvm/CodeGen/MachineFunctionPass.h"
#include "llvm/CodeGen/MachineInstr.h"
#include "llvm/CodeGen/MachineLoopInfo.h"
#include "llvm/CodeGen/MachineMemOperand.h"
#include "llvm/CodeGen/MachineOperand.h"
#include "llvm/CodeGen/MachineRegisterInfo.h"
#include "llvm/CodeGen/PseudoSourceValue.h"
#include "llvm/CodeGen/RegisterClassInfo.h"
#include "llvm/CodeGen/TargetInstrInfo.h"
#include "llvm/CodeGen/TargetLowering.h"
#include "llvm/CodeGen/TargetRegisterInfo.h"
#include "llvm/CodeGen/TargetSchedule.h"
#include "llvm/CodeGen/TargetSubtargetInfo.h"
#include "llvm/IR/DebugLoc.h"
#include "llvm/IR/Module.h"
#include "llvm/InitializePasses.h"
#include "llvm/MC/MCInstrDesc.h"
#include "llvm/MC/MCRegister.h"
#include "llvm/Pass.h"
#include "llvm/Support/Casting.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/Target/TargetMachine.h"
#include <cassert>
#include <limits>
#include <vector>

using namespace llvm;

#define DEBUG_TYPE "machinelicm"

static cl::opt<bool>
AvoidSpeculation("avoid-speculation",
                 cl::desc("MachineLICM should avoid speculation"),
                 cl::init(true), cl::Hidden);

static cl::opt<bool>
HoistCheapInsts("hoist-cheap-insts",
                cl::desc("MachineLICM should hoist even cheap instructions"),
                cl::init(false), cl::Hidden);

static cl::opt<bool>
HoistConstStores("hoist-const-stores",
                 cl::desc("Hoist invariant stores"),
                 cl::init(true), cl::Hidden);

static cl::opt<bool> HoistConstLoads("hoist-const-loads",
                                     cl::desc("Hoist invariant loads"),
                                     cl::init(true), cl::Hidden);

// The default threshold of 100 (i.e. if target block is 100 times hotter)
// is based on empirical data on a single target and is subject to tuning.
static cl::opt<unsigned>
BlockFrequencyRatioThreshold("block-freq-ratio-threshold",
                             cl::desc("Do not hoist instructions if target"
                             "block is N times hotter than the source."),
                             cl::init(100), cl::Hidden);

enum class UseBFI { None, PGO, All };

static cl::opt<UseBFI>
DisableHoistingToHotterBlocks("disable-hoisting-to-hotter-blocks",
                              cl::desc("Disable hoisting instructions to"
                              " hotter blocks"),
                              cl::init(UseBFI::PGO), cl::Hidden,
                              cl::values(clEnumValN(UseBFI::None, "none",
                              "disable the feature"),
                              clEnumValN(UseBFI::PGO, "pgo",
                              "enable the feature when using profile data"),
                              clEnumValN(UseBFI::All, "all",
                              "enable the feature with/wo profile data")));

STATISTIC(NumHoisted,
          "Number of machine instructions hoisted out of loops");
STATISTIC(NumLowRP,
          "Number of instructions hoisted in low reg pressure situation");
STATISTIC(NumHighLatency,
          "Number of high latency instructions hoisted");
STATISTIC(NumCSEed,
          "Number of hoisted machine instructions CSEed");
STATISTIC(NumPostRAHoisted,
          "Number of machine instructions hoisted out of loops post regalloc");
STATISTIC(NumStoreConst,
          "Number of stores of const phys reg hoisted out of loops");
STATISTIC(NumNotHoistedDueToHotness,
          "Number of instructions not hoisted due to block frequency");

namespace {
  enum HoistResult { NotHoisted = 1, Hoisted = 2, ErasedMI = 4 };

  class MachineLICMImpl {
    const TargetInstrInfo *TII = nullptr;
    const TargetLoweringBase *TLI = nullptr;
    const TargetRegisterInfo *TRI = nullptr;
    const MachineFrameInfo *MFI = nullptr;
    MachineRegisterInfo *MRI = nullptr;
    const RegisterClassInfo *RegClassInfo = nullptr;
    TargetSchedModel SchedModel;
    bool PreRegAlloc = false;
    bool HasProfileData = false;
    Pass *LegacyPass;
    MachineFunctionAnalysisManager *MFAM;

    // Various analyses that we use...
    AliasAnalysis *AA = nullptr;               // Alias analysis info.
    MachineBlockFrequencyInfo *MBFI = nullptr; // Machine block frequncy info
    MachineLoopInfo *MLI = nullptr;            // Current MachineLoopInfo
    MachineDomTreeUpdater *MDTU = nullptr;     // Wraps current dominator tree

    // State that is updated as we process loops
    bool Changed = false;           // True if a loop is changed.
    bool FirstInLoop = false;       // True if it's the first LICM in the loop.

    // Holds information about whether it is allowed to move load instructions
    // out of the loop
    SmallDenseMap<MachineLoop *, bool> AllowedToHoistLoads;

    // Exit blocks of each Loop.
    DenseMap<MachineLoop *, SmallVector<MachineBasicBlock *, 8>> ExitBlockMap;

    bool isExitBlock(MachineLoop *CurLoop, const MachineBasicBlock *MBB) {
      auto [It, Inserted] = ExitBlockMap.try_emplace(CurLoop);
      if (Inserted) {
        SmallVector<MachineBasicBlock *, 8> ExitBlocks;
        CurLoop->getExitBlocks(ExitBlocks);
        It->second = std::move(ExitBlocks);
      }
      return is_contained(It->second, MBB);
    }

    // Track 'estimated' register pressure.
    SmallDenseSet<Register> RegSeen;
    SmallVector<unsigned, 8> RegPressure;

    // Register pressure "limit" per register pressure set. If the pressure
    // is higher than the limit, then it's considered high.
    SmallVector<unsigned, 8> RegLimit;

    // Register pressure on path leading from loop preheader to current BB.
    SmallVector<SmallVector<unsigned, 8>, 16> BackTrace;

    // For each opcode per preheader, keep a list of potential CSE instructions.
    DenseMap<MachineBasicBlock *,
             DenseMap<unsigned, std::vector<MachineInstr *>>>
        CSEMap;

    // If a MBB does not dominate loop exiting blocks then it may not safe
    // to hoist loads from this block. Cached per loop for the current block,
    // which is checked against both the outermost loop and its subloops.
    SmallDenseMap<MachineLoop *, bool> GuaranteedToExecute;

  public:
    MachineLICMImpl(bool PreRegAlloc, Pass *LegacyPass,
                    MachineFunctionAnalysisManager *MFAM)
        : PreRegAlloc(PreRegAlloc), LegacyPass(LegacyPass), MFAM(MFAM) {
      assert((LegacyPass || MFAM) && "LegacyPass or MFAM must be provided");
      assert(!(LegacyPass && MFAM) &&
             "LegacyPass and MFAM cannot be provided at the same time");
    }

    bool run(MachineFunction &MF);

    void releaseMemory() {
      RegSeen.clear();
      RegPressure.clear();
      RegLimit.clear();
      BackTrace.clear();
      CSEMap.clear();
      ExitBlockMap.clear();
    }

  private:
    /// Keep track of information about hoisting candidates.
    struct CandidateInfo {
      MachineInstr *MI;
      Register      Def;
      int           FI;

      CandidateInfo(MachineInstr *mi, Register def, int fi)
        : MI(mi), Def(def), FI(fi) {}
    };

    void HoistRegionPostRA(MachineLoop *CurLoop);

    void HoistPostRA(MachineInstr *MI, Register Def, MachineLoop *CurLoop);

    void ProcessMI(MachineInstr *MI, BitVector &RUDefs, BitVector &RUClobbers,
                   SmallDenseSet<int> &StoredFIs,
                   SmallVectorImpl<CandidateInfo> &Candidates,
                   MachineLoop *CurLoop);

    void AddToLiveIns(MCRegister Reg, MachineLoop *CurLoop);

    bool IsLICMCandidate(MachineInstr &I, MachineLoop *CurLoop);

    bool IsLoopInvariantInst(MachineInstr &I, MachineLoop *CurLoop);

    bool HasLoopPHIUse(const MachineInstr *MI, MachineLoop *CurLoop);

    bool HasHighOperandLatency(MachineInstr &MI, unsigned DefIdx, Register Reg,
                               MachineLoop *CurLoop) const;

    bool IsCheapInstruction(MachineInstr &MI) const;

    bool CanCauseHighRegPressure(const SmallDenseMap<unsigned, int> &Cost,
                                 bool Cheap);

    void UpdateBackTraceRegPressure(const MachineInstr *MI);

    bool IsProfitableToHoist(MachineInstr &MI, MachineLoop *CurLoop);

    bool IsGuaranteedToExecute(MachineBasicBlock *BB, MachineLoop *CurLoop);

    void EnterScope(MachineBasicBlock *MBB);

    void ExitScope(MachineBasicBlock *MBB);

    void ExitScopeIfDone(
        MachineDomTreeNode *Node,
        DenseMap<MachineDomTreeNode *, unsigned> &OpenChildren,
        const DenseMap<MachineDomTreeNode *, MachineDomTreeNode *> &ParentMap);

    void HoistOutOfLoop(MachineDomTreeNode *HeaderN, MachineLoop *CurLoop);

    void InitRegPressure(MachineBasicBlock *BB);

    SmallDenseMap<unsigned, int> calcRegisterCost(const MachineInstr *MI,
                                                  bool ConsiderSeen,
                                                  bool ConsiderUnseenAsDef);

    void UpdateRegPressure(const MachineInstr *MI,
                           bool ConsiderUnseenAsDef = false);

    MachineInstr *ExtractHoistableLoad(MachineInstr *MI, MachineLoop *CurLoop);

    MachineInstr *LookForDuplicate(const MachineInstr *MI,
                                   std::vector<MachineInstr *> &PrevMIs);

    bool
    EliminateCSE(MachineInstr *MI,
                 DenseMap<unsigned, std::vector<MachineInstr *>>::iterator &CI);

    bool MayCSE(MachineInstr *MI);

    unsigned Hoist(MachineInstr *MI, MachineBasicBlock *Preheader,
                   MachineLoop *CurLoop);

    void InitCSEMap(MachineBasicBlock *BB);

    void InitializeLoadsHoistableLoops();

    bool isTgtHotterThanSrc(MachineBasicBlock *SrcBlock,
                            MachineBasicBlock *TgtBlock);
    MachineBasicBlock *getOrCreatePreheader(MachineLoop *CurLoop);
  };

  class MachineLICMBase : public MachineFunctionPass {
    bool PreRegAlloc;

  public:
    MachineLICMBase(char &ID, bool PreRegAlloc)
        : MachineFunctionPass(ID), PreRegAlloc(PreRegAlloc) {}

    bool runOnMachineFunction(MachineFunction &MF) override;

    void getAnalysisUsage(AnalysisUsage &AU) const override {
      AU.addRequired<MachineLoopInfoWrapperPass>();
      if (DisableHoistingToHotterBlocks != UseBFI::None)
        AU.addRequired<LazyMachineBlockFrequencyInfoPass>();
      AU.addRequired<MachineDominatorTreeWrapperPass>();
      AU.addRequired<MachineRegisterClassInfoWrapperPass>();
      AU.addRequired<AAResultsWrapperPass>();
      AU.addPreserved<MachineLoopInfoWrapperPass>();
      AU.addPreserved<MachineDominatorTreeWrapperPass>();
      AU.addPreserved<MachineRegisterClassInfoWrapperPass>();
      MachineFunctionPass::getAnalysisUsage(AU);
    }
  };

  class MachineLICM : public MachineLICMBase {
  public:
    static char ID;
    MachineLICM() : MachineLICMBase(ID, false) {}
  };

  class EarlyMachineLICM : public MachineLICMBase {
  public:
    static char ID;
    EarlyMachineLICM() : MachineLICMBase(ID, true) {}
  };

} // end anonymous namespace

char MachineLICM::ID;
char EarlyMachineLICM::ID;

char &llvm::MachineLICMID = MachineLICM::ID;
char &llvm::EarlyMachineLICMID = EarlyMachineLICM::ID;

INITIALIZE_PASS_BEGIN(MachineLICM, DEBUG_TYPE,
                      "Machine Loop Invariant Code Motion", false, false)
INITIALIZE_PASS_DEPENDENCY(MachineLoopInfoWrapperPass)
INITIALIZE_PASS_DEPENDENCY(LazyMachineBlockFrequencyInfoPass)
INITIALIZE_PASS_DEPENDENCY(MachineDominatorTreeWrapperPass)
INITIALIZE_PASS_DEPENDENCY(MachineRegisterClassInfoWrapperPass)
INITIALIZE_PASS_DEPENDENCY(AAResultsWrapperPass)
INITIALIZE_PASS_END(MachineLICM, DEBUG_TYPE,
                    "Machine Loop Invariant Code Motion", false, false)

INITIALIZE_PASS_BEGIN(EarlyMachineLICM, "early-machinelicm",
                      "Early Machine Loop Invariant Code Motion", false, false)
INITIALIZE_PASS_DEPENDENCY(MachineLoopInfoWrapperPass)
INITIALIZE_PASS_DEPENDENCY(LazyMachineBlockFrequencyInfoPass)
INITIALIZE_PASS_DEPENDENCY(MachineDominatorTreeWrapperPass)
INITIALIZE_PASS_DEPENDENCY(MachineRegisterClassInfoWrapperPass)
INITIALIZE_PASS_DEPENDENCY(AAResultsWrapperPass)
INITIALIZE_PASS_END(EarlyMachineLICM, "early-machinelicm",
                    "Early Machine Loop Invariant Code Motion", false, false)

bool MachineLICMBase::runOnMachineFunction(MachineFunction &MF) {
  if (skipFunction(MF.getFunction()))
    return false;

  MachineLICMImpl Impl(PreRegAlloc, this, nullptr);
  return Impl.run(MF);
}

#define GET_RESULT(RESULT, GETTER, INFIX)                                      \
  ((LegacyPass)                                                                \
       ? &LegacyPass->getAnalysis<RESULT##INFIX##WrapperPass>().GETTER()       \
       : &MFAM->getResult<RESULT##Analysis>(MF))

bool MachineLICMImpl::run(MachineFunction &MF) {
  AA = MFAM != nullptr
           ? &MFAM->getResult<FunctionAnalysisManagerMachineFunctionProxy>(MF)
                  .getManager()
                  .getResult<AAManager>(MF.getFunction())
           : &LegacyPass->getAnalysis<AAResultsWrapperPass>().getAAResults();

  RegClassInfo =
      MFAM != nullptr
          ? &MFAM->getResult<MachineRegisterClassAnalysis>(MF)
          : &LegacyPass->getAnalysis<MachineRegisterClassInfoWrapperPass>()
                 .getRCI();

  MachineDomTreeUpdater DTU(GET_RESULT(MachineDominatorTree, getDomTree, ),
                            MachineDomTreeUpdater::UpdateStrategy::Lazy);
  MDTU = &DTU;
  MLI = GET_RESULT(MachineLoop, getLI, Info);

  Changed = FirstInLoop = false;
  const TargetSubtargetInfo &ST = MF.getSubtarget();
  TII = ST.getInstrInfo();
  TLI = ST.getTargetLowering();
  TRI = ST.getRegisterInfo();
  MFI = &MF.getFrameInfo();
  MRI = &MF.getRegInfo();
  SchedModel.init(&ST);

  HasProfileData = MF.getFunction().hasProfileData();

  if (DisableHoistingToHotterBlocks == UseBFI::All ||
      (DisableHoistingToHotterBlocks == UseBFI::PGO && HasProfileData))
    MBFI = LegacyPass
               ? &LegacyPass->getAnalysis<LazyMachineBlockFrequencyInfoPass>()
                      .getBFI()
               : &MFAM->getResult<MachineBlockFrequencyAnalysis>(MF);

  if (PreRegAlloc)
    LLVM_DEBUG(dbgs() << "******** Pre-regalloc Machine LICM: ");
  else
    LLVM_DEBUG(dbgs() << "******** Post-regalloc Machine LICM: ");
  LLVM_DEBUG(dbgs() << MF.getName() << " ********\n");

  if (PreRegAlloc) {
    // Estimate register pressure during pre-regalloc pass.
    unsigned NumRPS = TRI->getNumRegPressureSets();
    RegPressure.resize(NumRPS);
    llvm::fill(RegPressure, 0);
    RegLimit.resize(NumRPS);
    for (unsigned i = 0, e = NumRPS; i != e; ++i)
      RegLimit[i] = RegClassInfo->getRegPressureSetLimit(i);
  }

  if (HoistConstLoads)
    InitializeLoadsHoistableLoops();

  SmallVector<MachineLoop *, 8> Worklist(MLI->begin(), MLI->end());
  while (!Worklist.empty()) {
    MachineLoop *CurLoop = Worklist.pop_back_val();

    if (!PreRegAlloc) {
      HoistRegionPostRA(CurLoop);
    } else {
      // CSEMap is initialized for loop header when the first instruction is
      // being hoisted.
      MachineDomTreeNode *N = MDTU->getDomTree().getNode(CurLoop->getHeader());
      FirstInLoop = true;
      HoistOutOfLoop(N, CurLoop);
      CSEMap.clear();
    }
  }
  releaseMemory();
  return Changed;
}

/// Return true if instruction stores to the specified frame.
static bool InstructionStoresToFI(const MachineInstr *MI, int FI) {
  // Check mayStore before memory operands so that e.g. DBG_VALUEs will return
  // true since they have no memory operands.
  if (!MI->mayStore())
     return false;
  // If we lost memory operands, conservatively assume that the instruction
  // writes to all slots.
  if (MI->memoperands_empty())
    return true;
  for (const MachineMemOperand *MemOp : MI->memoperands()) {
    if (!MemOp->isStore() || !MemOp->getPseudoValue())
      continue;
    if (const FixedStackPseudoSourceValue *Value =
        dyn_cast<FixedStackPseudoSourceValue>(MemOp->getPseudoValue())) {
      if (Value->getFrameIndex() == FI)
        return true;
    }
  }
  return false;
}

static void applyBitsNotInRegMaskToRegUnitsMask(const TargetRegisterInfo &TRI,
                                                BitVector &RUs,
                                                const uint32_t *Mask) {
  // FIXME: This intentionally works in reverse due to some issues with the
  // Register Units infrastructure.
  //
  // This is used to apply callee-saved-register masks to the clobbered regunits
  // mask.
  //
  // The right way to approach this is to start with a BitVector full of ones,
  // then reset all the bits of the regunits of each register that is set in the
  // mask (registers preserved), then OR the resulting bits with the Clobbers
  // mask. This correctly prioritizes the saved registers, so if a RU is shared
  // between a register that is preserved, and one that is NOT preserved, that
  // RU will not be set in the output vector (the clobbers).
  //
  // What we have to do for now is the opposite: we have to assume that the
  // regunits of all registers that are NOT preserved are clobbered, even if
  // those regunits are preserved by another register. So if a RU is shared
  // like described previously, that RU will be set.
  //
  // This is to work around an issue which appears in AArch64, but isn't
  // exclusive to that target: AArch64's Qn registers (128 bits) have Dn
  // register (lower 64 bits). A few Dn registers are preserved by some calling
  // conventions, but Qn and Dn share exactly the same reg units.
  //
  // If we do this the right way, Qn will be marked as NOT clobbered even though
  // its upper 64 bits are NOT preserved. The conservative approach handles this
  // correctly at the cost of some missed optimizations on other targets.
  //
  // This is caused by how RegUnits are handled within TableGen. Ideally, Qn
  // should have an extra RegUnit to model the "unknown" bits not covered by the
  // subregs.
  BitVector RUsFromRegsNotInMask(TRI.getNumRegUnits());
  const unsigned NumRegs = TRI.getNumRegs();
  const unsigned MaskWords = (NumRegs + 31) / 32;
  for (unsigned K = 0; K < MaskWords; ++K) {
    const uint32_t Word = Mask[K];
    for (unsigned Bit = 0; Bit < 32; ++Bit) {
      const unsigned PhysReg = (K * 32) + Bit;
      if (PhysReg == NumRegs)
        break;

      if (PhysReg && !((Word >> Bit) & 1)) {
        for (MCRegUnit Unit : TRI.regunits(PhysReg))
          RUsFromRegsNotInMask.set(static_cast<unsigned>(Unit));
      }
    }
  }

  RUs |= RUsFromRegsNotInMask;
}

/// Examine the instruction for potential LICM candidate. Also
/// gather register def and frame object update information.
void MachineLICMImpl::ProcessMI(MachineInstr *MI, BitVector &RUDefs,
                                BitVector &RUClobbers,
                                SmallDenseSet<int> &StoredFIs,
                                SmallVectorImpl<CandidateInfo> &Candidates,
                                MachineLoop *CurLoop) {
  bool RuledOut = false;
  bool HasNonInvariantUse = false;
  Register Def;
  for (const MachineOperand &MO : MI->operands()) {
    if (MO.isFI()) {
      // Remember if the instruction stores to the frame index.
      int FI = MO.getIndex();
      if (!StoredFIs.count(FI) &&
          MFI->isSpillSlotObjectIndex(FI) &&
          InstructionStoresToFI(MI, FI))
        StoredFIs.insert(FI);
      HasNonInvariantUse = true;
      continue;
    }

    // We can't hoist an instruction defining a physreg that is clobbered in
    // the loop.
    if (MO.isRegMask()) {
      applyBitsNotInRegMaskToRegUnitsMask(*TRI, RUClobbers, MO.getRegMask());
      continue;
    }

    if (!MO.isReg())
      continue;
    Register Reg = MO.getReg();
    if (!Reg)
      continue;
    assert(Reg.isPhysical() && "Not expecting virtual register!");

    if (!MO.isDef()) {
      if (!HasNonInvariantUse) {
        for (MCRegUnit Unit : TRI->regunits(Reg)) {
          // If it's using a non-loop-invariant register, then it's obviously
          // not safe to hoist.
          if (RUDefs.test(static_cast<unsigned>(Unit)) ||
              RUClobbers.test(static_cast<unsigned>(Unit))) {
            HasNonInvariantUse = true;
            break;
          }
        }
      }
      continue;
    }

    // FIXME: For now, avoid instructions with multiple defs, unless it's dead.
    if (!MO.isDead()) {
      if (Def)
        RuledOut = true;
      else
        Def = Reg;
    }

    // If we have already seen another instruction that defines the same
    // register, then this is not safe.  Two defs is indicated by setting a
    // PhysRegClobbers bit.
    for (MCRegUnit Unit : TRI->regunits(Reg)) {
      if (RUDefs.test(static_cast<unsigned>(Unit))) {
        RUClobbers.set(static_cast<unsigned>(Unit));
        RuledOut = true;
      } else if (RUClobbers.test(static_cast<unsigned>(Unit))) {
        // MI defined register is seen defined by another instruction in
        // the loop, it cannot be a LICM candidate.
        RuledOut = true;
      }

      RUDefs.set(static_cast<unsigned>(Unit));
    }
  }

  // Only consider reloads for now and remats which do not have register
  // operands. FIXME: Consider unfold load folding instructions.
  if (Def && !RuledOut) {
    int FI = std::numeric_limits<int>::min();
    if ((!HasNonInvariantUse && IsLICMCandidate(*MI, CurLoop)) ||
        (TII->isLoadFromStackSlot(*MI, FI) && MFI->isSpillSlotObjectIndex(FI)))
      Candidates.push_back(CandidateInfo(MI, Def, FI));
  }
}

/// Walk the specified region of the CFG and hoist loop invariants out to the
/// preheader.
void MachineLICMImpl::HoistRegionPostRA(MachineLoop *CurLoop) {
  MachineBasicBlock *Preheader = getOrCreatePreheader(CurLoop);
  if (!Preheader)
    return;

  unsigned NumRegUnits = TRI->getNumRegUnits();
  BitVector RUDefs(NumRegUnits);     // RUs defined once in the loop.
  BitVector RUClobbers(NumRegUnits); // RUs defined more than once.

  SmallVector<CandidateInfo, 32> Candidates;
  SmallDenseSet<int> StoredFIs;

  // Walk the entire region, count number of defs for each register, and
  // collect potential LICM candidates.
  for (MachineBasicBlock *BB : CurLoop->getBlocks()) {
    // If the header of the loop containing this basic block is a landing pad,
    // then don't try to hoist instructions out of this loop.
    const MachineLoop *ML = MLI->getLoopFor(BB);
    if (ML && ML->getHeader()->isEHPad()) continue;

    // Conservatively treat live-in's as an external def.
    // FIXME: That means a reload that're reused in successor block(s) will not
    // be LICM'ed.
    for (const auto &LI : BB->liveins()) {
      for (MCRegUnit Unit : TRI->regunits(LI.PhysReg))
        RUDefs.set(static_cast<unsigned>(Unit));
    }

    // Funclet entry blocks will clobber all registers
    if (const uint32_t *Mask = BB->getBeginClobberMask(TRI))
      applyBitsNotInRegMaskToRegUnitsMask(*TRI, RUClobbers, Mask);

    // EH landing pads clobber exception pointer/selector registers.
    if (BB->isEHPad()) {
      const MachineFunction &MF = *BB->getParent();
      const Constant *PersonalityFn = MF.getFunction().getPersonalityFn();
      const TargetLowering &TLI = *MF.getSubtarget().getTargetLowering();
      ExceptionHandling EH = MF.getFunction().getParent()->getExceptionModel();
      if (MCRegister Reg = TLI.getExceptionPointerRegister(EH, PersonalityFn))
        for (MCRegUnit Unit : TRI->regunits(Reg))
          RUClobbers.set(static_cast<unsigned>(Unit));
      if (MCRegister Reg = TLI.getExceptionSelectorRegister(EH, PersonalityFn))
        for (MCRegUnit Unit : TRI->regunits(Reg))
          RUClobbers.set(static_cast<unsigned>(Unit));
    }

    GuaranteedToExecute.clear();
    for (MachineInstr &MI : *BB)
      ProcessMI(&MI, RUDefs, RUClobbers, StoredFIs, Candidates, CurLoop);
  }

  // Gather the registers read / clobbered by the terminator.
  BitVector TermRUs(NumRegUnits);
  MachineBasicBlock::iterator TI = Preheader->getFirstTerminator();
  if (TI != Preheader->end()) {
    for (const MachineOperand &MO : TI->operands()) {
      if (!MO.isReg())
        continue;
      Register Reg = MO.getReg();
      if (!Reg)
        continue;
      for (MCRegUnit Unit : TRI->regunits(Reg))
        TermRUs.set(static_cast<unsigned>(Unit));
    }
  }

  // Now evaluate whether the potential candidates qualify.
  // 1. Check if the candidate defined register is defined by another
  //    instruction in the loop.
  // 2. If the candidate is a load from stack slot (always true for now),
  //    check if the slot is stored anywhere in the loop.
  // 3. Make sure candidate def should not clobber
  //    registers read by the terminator. Similarly its def should not be
  //    clobbered by the terminator.
  for (CandidateInfo &Candidate : Candidates) {
    if (Candidate.FI != std::numeric_limits<int>::min() &&
        StoredFIs.count(Candidate.FI))
      continue;

    Register Def = Candidate.Def;
    bool Safe = true;
    for (MCRegUnit Unit : TRI->regunits(Def)) {
      if (RUClobbers.test(static_cast<unsigned>(Unit)) ||
          TermRUs.test(static_cast<unsigned>(Unit))) {
        Safe = false;
        break;
      }
    }

    if (!Safe)
      continue;

    MachineInstr *MI = Candidate.MI;
    for (const MachineOperand &MO : MI->all_uses()) {
      if (!MO.getReg())
        continue;
      for (MCRegUnit Unit : TRI->regunits(MO.getReg())) {
        if (RUDefs.test(static_cast<unsigned>(Unit)) ||
            RUClobbers.test(static_cast<unsigned>(Unit))) {
          // If it's using a non-loop-invariant register, then it's obviously
          // not safe to hoist.
          Safe = false;
          break;
        }
      }

      if (!Safe)
        break;
    }

    if (Safe)
      HoistPostRA(MI, Candidate.Def, CurLoop);
  }
}

/// Add register 'Reg' to the livein sets of BBs in the current loop, and make
/// sure it is not killed by any instructions in the loop.
void MachineLICMImpl::AddToLiveIns(MCRegister Reg, MachineLoop *CurLoop) {
  for (MachineBasicBlock *BB : CurLoop->getBlocks()) {
    if (!BB->isLiveIn(Reg))
      BB->addLiveIn(Reg);
    for (MachineInstr &MI : *BB) {
      for (MachineOperand &MO : MI.all_uses()) {
        if (!MO.getReg())
          continue;
        if (TRI->regsOverlap(Reg, MO.getReg()))
          MO.setIsKill(false);
      }
    }
  }
}

/// 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.
void MachineLICMImpl::HoistPostRA(MachineInstr *MI, Register Def,
                                  MachineLoop *CurLoop) {
  MachineBasicBlock *Preheader = CurLoop->getLoopPreheader();

  // Now move the instructions to the predecessor, inserting it before any
  // terminator instructions.
  LLVM_DEBUG(dbgs() << "Hoisting to " << printMBBReference(*Preheader)
                    << " from " << printMBBReference(*MI->getParent()) << ": "
                    << *MI);

  // Splice the instruction to the preheader.
  MachineBasicBlock *MBB = MI->getParent();
  Preheader->splice(Preheader->getFirstTerminator(), MBB, MI);

  // Since we are moving the instruction out of its basic block, we do not
  // retain its debug location. Doing so would degrade the debugging
  // experience and adversely affect the accuracy of profiling information.
  assert(!MI->isDebugInstr() && "Should not hoist debug inst");
  MI->setDebugLoc(DebugLoc());

  // Add register to livein list to all the BBs in the current loop since a
  // loop invariant must be kept live throughout the whole loop. This is
  // important to ensure later passes do not scavenge the def register.
  AddToLiveIns(Def, CurLoop);

  ++NumPostRAHoisted;
  Changed = true;
}

/// Check if this mbb is guaranteed to execute. If not then a load from this mbb
/// may not be safe to hoist.
bool MachineLICMImpl::IsGuaranteedToExecute(MachineBasicBlock *BB,
                                            MachineLoop *CurLoop) {
  auto [It, Inserted] = GuaranteedToExecute.try_emplace(CurLoop, true);
  if (!Inserted)
    return It->second;

  if (BB != CurLoop->getHeader()) {
    // Check loop exiting blocks.
    SmallVector<MachineBasicBlock*, 8> CurrentLoopExitingBlocks;
    CurLoop->getExitingBlocks(CurrentLoopExitingBlocks);
    for (MachineBasicBlock *CurrentLoopExitingBlock : CurrentLoopExitingBlocks)
      if (!MDTU->getDomTree().dominates(BB, CurrentLoopExitingBlock)) {
        It->second = false;
        return false;
      }
  }

  return true;
}

void MachineLICMImpl::EnterScope(MachineBasicBlock *MBB) {
  LLVM_DEBUG(dbgs() << "Entering " << printMBBReference(*MBB) << '\n');

  // Remember livein register pressure.
  BackTrace.push_back(RegPressure);
}

void MachineLICMImpl::ExitScope(MachineBasicBlock *MBB) {
  LLVM_DEBUG(dbgs() << "Exiting " << printMBBReference(*MBB) << '\n');
  BackTrace.pop_back();
}

/// Destroy scope for the MBB that corresponds to the given dominator tree node
/// if its a leaf or all of its children are done. Walk up the dominator tree to
/// destroy ancestors which are now done.
void MachineLICMImpl::ExitScopeIfDone(
    MachineDomTreeNode *Node,
    DenseMap<MachineDomTreeNode *, unsigned> &OpenChildren,
    const DenseMap<MachineDomTreeNode *, MachineDomTreeNode *> &ParentMap) {
  if (OpenChildren[Node])
    return;

  for(;;) {
    ExitScope(Node->getBlock());
    // Now traverse upwards to pop ancestors whose offsprings are all done.
    MachineDomTreeNode *Parent = ParentMap.lookup(Node);
    if (!Parent || --OpenChildren[Parent] != 0)
      break;
    Node = Parent;
  }
}

/// Walk the specified loop in the CFG (defined by all blocks dominated by the
/// specified header 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.
void MachineLICMImpl::HoistOutOfLoop(MachineDomTreeNode *HeaderN,
                                     MachineLoop *CurLoop) {
  MachineBasicBlock *Preheader = getOrCreatePreheader(CurLoop);
  if (!Preheader)
    return;

  SmallVector<MachineDomTreeNode*, 32> Scopes;
  SmallVector<MachineDomTreeNode*, 8> WorkList;
  DenseMap<MachineDomTreeNode*, MachineDomTreeNode*> ParentMap;
  DenseMap<MachineDomTreeNode*, unsigned> OpenChildren;

  // Perform a DFS walk to determine the order of visit.
  WorkList.push_back(HeaderN);
  while (!WorkList.empty()) {
    MachineDomTreeNode *Node = WorkList.pop_back_val();
    assert(Node && "Null dominator tree node?");
    MachineBasicBlock *BB = Node->getBlock();

    // If the header of the loop containing this basic block is a landing pad,
    // then don't try to hoist instructions out of this loop.
    const MachineLoop *ML = MLI->getLoopFor(BB);
    if (ML && ML->getHeader()->isEHPad())
      continue;

    // If this subregion is not in the top level loop at all, exit.
    if (!CurLoop->contains(BB))
      continue;

    Scopes.push_back(Node);

    // Don't hoist things out of a large switch statement.  This often causes
    // code to be hoisted that wasn't going to be executed, and increases
    // register pressure in a situation where it's likely to matter.
    if (BB->succ_size() >= 25) {
      OpenChildren[Node] = 0;
      continue;
    }

    // Add children in reverse order as then the next popped worklist node is
    // the first child of this node.  This means we ultimately traverse the
    // DOM tree in exactly the same order as if we'd recursed.
    size_t WorkListStart = WorkList.size();
    for (MachineDomTreeNode *Child : Node->children()) {
      ParentMap[Child] = Node;
      WorkList.push_back(Child);
    }
    std::reverse(WorkList.begin() + WorkListStart, WorkList.end());
    OpenChildren[Node] = WorkList.size() - WorkListStart;
  }

  if (Scopes.size() == 0)
    return;

  // Compute registers which are livein into the loop headers.
  RegSeen.clear();
  BackTrace.clear();
  InitRegPressure(Preheader);

  // Now perform LICM.
  for (MachineDomTreeNode *Node : Scopes) {
    MachineBasicBlock *MBB = Node->getBlock();

    EnterScope(MBB);

    // Process the block
    GuaranteedToExecute.clear();
    for (MachineInstr &MI : llvm::make_early_inc_range(*MBB)) {
      unsigned HoistRes = HoistResult::NotHoisted;
      HoistRes = Hoist(&MI, Preheader, CurLoop);
      if (HoistRes & HoistResult::NotHoisted) {
        // We have failed to hoist MI to outermost loop's preheader. If MI is in
        // a subloop, try to hoist it to subloop's preheader.
        SmallVector<MachineLoop *> InnerLoopWorkList;
        for (MachineLoop *L = MLI->getLoopFor(MI.getParent()); L != CurLoop;
             L = L->getParentLoop())
          InnerLoopWorkList.push_back(L);

        while (!InnerLoopWorkList.empty()) {
          MachineLoop *InnerLoop = InnerLoopWorkList.pop_back_val();
          MachineBasicBlock *InnerLoopPreheader = InnerLoop->getLoopPreheader();
          if (InnerLoopPreheader) {
            HoistRes = Hoist(&MI, InnerLoopPreheader, InnerLoop);
            if (HoistRes & HoistResult::Hoisted)
              break;
          }
        }
      }

      if (HoistRes & HoistResult::ErasedMI)
        continue;

      UpdateRegPressure(&MI);
    }

    // If it's a leaf node, it's done. Traverse upwards to pop ancestors.
    ExitScopeIfDone(Node, OpenChildren, ParentMap);
  }
}

/// Find all virtual register references that are liveout of the preheader to
/// initialize the starting "register pressure". Note this does not count live
/// through (livein but not used) registers.
void MachineLICMImpl::InitRegPressure(MachineBasicBlock *BB) {
  llvm::fill(RegPressure, 0);

  // If the preheader has only a single predecessor and it ends with a
  // fallthrough or an unconditional branch, then scan its predecessor for live
  // defs as well. This happens whenever the preheader is created by splitting
  // the critical edge from the loop predecessor to the loop header.
  if (BB->pred_size() == 1) {
    MachineBasicBlock *TBB = nullptr, *FBB = nullptr;
    SmallVector<MachineOperand, 4> Cond;
    if (!TII->analyzeBranch(*BB, TBB, FBB, Cond, false) && Cond.empty())
      InitRegPressure(*BB->pred_begin());
  }

  for (const MachineInstr &MI : *BB)
    UpdateRegPressure(&MI, /*ConsiderUnseenAsDef=*/true);
}

/// Update estimate of register pressure after the specified instruction.
void MachineLICMImpl::UpdateRegPressure(const MachineInstr *MI,
                                        bool ConsiderUnseenAsDef) {
  auto Cost = calcRegisterCost(MI, /*ConsiderSeen=*/true, ConsiderUnseenAsDef);
  for (const auto &[Class, Weight] : Cost) {
    if (static_cast<int>(RegPressure[Class]) < -Weight)
      RegPressure[Class] = 0;
    else
      RegPressure[Class] += Weight;
  }
}

/// Calculate the additional register pressure that the registers used in MI
/// cause.
///
/// If 'ConsiderSeen' is true, updates 'RegSeen' and uses the information to
/// figure out which usages are live-ins.
/// FIXME: Figure out a way to consider 'RegSeen' from all code paths.
SmallDenseMap<unsigned, int>
MachineLICMImpl::calcRegisterCost(const MachineInstr *MI, bool ConsiderSeen,
                                  bool ConsiderUnseenAsDef) {
  SmallDenseMap<unsigned, int> Cost;
  if (MI->isImplicitDef())
    return Cost;
  for (unsigned i = 0, e = MI->getDesc().getNumOperands(); i != e; ++i) {
    const MachineOperand &MO = MI->getOperand(i);
    if (!MO.isReg() || MO.isImplicit())
      continue;
    Register Reg = MO.getReg();
    if (!Reg.isVirtual())
      continue;

    // FIXME: It seems bad to use RegSeen only for some of these calculations.
    bool isNew = ConsiderSeen ? RegSeen.insert(Reg).second : false;
    const TargetRegisterClass *RC = MRI->getRegClass(Reg);

    RegClassWeight W = TRI->getRegClassWeight(RC);
    int RCCost = 0;
    if (MO.isDef())
      RCCost = W.RegWeight;
    else {
      bool isKill = MRI->hasOneNonDBGUse(Reg);
      if (isNew && !isKill && ConsiderUnseenAsDef)
        // Haven't seen this, it must be a livein.
        RCCost = W.RegWeight;
      else if (!isNew && isKill)
        RCCost = -W.RegWeight;
    }
    if (RCCost == 0)
      continue;
    const int *PS = TRI->getRegClassPressureSets(RC);
    for (; *PS != -1; ++PS)
      Cost[*PS] += RCCost;
  }
  return Cost;
}

/// Return true if this machine instruction loads from global offset table or
/// constant pool.
static bool mayLoadFromGOTOrConstantPool(MachineInstr &MI) {
  assert(MI.mayLoad() && "Expected MI that loads!");

  // If we lost memory operands, conservatively assume that the instruction
  // reads from everything..
  if (MI.memoperands_empty())
    return true;

  for (MachineMemOperand *MemOp : MI.memoperands())
    if (const PseudoSourceValue *PSV = MemOp->getPseudoValue())
      if (PSV->isGOT() || PSV->isConstantPool())
        return true;

  return false;
}

// This function iterates through all the operands of the input store MI and
// checks that each register operand statisfies isCallerPreservedPhysReg.
// This means, the value being stored and the address where it is being stored
// is constant throughout the body of the function (not including prologue and
// epilogue). When called with an MI that isn't a store, it returns false.
// A future improvement can be to check if the store registers are constant
// throughout the loop rather than throughout the funtion.
static bool isInvariantStore(const MachineInstr &MI,
                             const TargetRegisterInfo *TRI,
                             const MachineRegisterInfo *MRI) {

  bool FoundCallerPresReg = false;
  if (!MI.mayStore() || MI.hasUnmodeledSideEffects() ||
      (MI.getNumOperands() == 0))
    return false;

  // Check that all register operands are caller-preserved physical registers.
  for (const MachineOperand &MO : MI.operands()) {
    if (MO.isReg()) {
      Register Reg = MO.getReg();
      // If operand is a virtual register, check if it comes from a copy of a
      // physical register.
      if (Reg.isVirtual())
        Reg = TRI->lookThruCopyLike(MO.getReg(), MRI);
      if (Reg.isVirtual())
        return false;
      if (!TRI->isCallerPreservedPhysReg(Reg.asMCReg(), *MI.getMF()))
        return false;
      else
        FoundCallerPresReg = true;
    } else if (!MO.isImm()) {
        return false;
    }
  }
  return FoundCallerPresReg;
}

// Return true if the input MI is a copy instruction that feeds an invariant
// store instruction. This means that the src of the copy has to satisfy
// isCallerPreservedPhysReg and atleast one of it's users should satisfy
// isInvariantStore.
static bool isCopyFeedingInvariantStore(const MachineInstr &MI,
                                        const MachineRegisterInfo *MRI,
                                        const TargetRegisterInfo *TRI) {

  // FIXME: If targets would like to look through instructions that aren't
  // pure copies, this can be updated to a query.
  if (!MI.isCopy())
    return false;

  const MachineFunction *MF = MI.getMF();
  // Check that we are copying a constant physical register.
  Register CopySrcReg = MI.getOperand(1).getReg();
  if (CopySrcReg.isVirtual())
    return false;

  if (!TRI->isCallerPreservedPhysReg(CopySrcReg.asMCReg(), *MF))
    return false;

  Register CopyDstReg = MI.getOperand(0).getReg();
  // Check if any of the uses of the copy are invariant stores.
  assert(CopyDstReg.isVirtual() && "copy dst is not a virtual reg");

  for (MachineInstr &UseMI : MRI->use_instructions(CopyDstReg)) {
    if (UseMI.mayStore() && isInvariantStore(UseMI, TRI, MRI))
      return true;
  }
  return false;
}

/// Returns true if the instruction may be a suitable candidate for LICM.
/// e.g. If the instruction is a call, then it's obviously not safe to hoist it.
bool MachineLICMImpl::IsLICMCandidate(MachineInstr &I, MachineLoop *CurLoop) {
  // Check if it's safe to move the instruction.
  bool DontMoveAcrossStore = !HoistConstLoads || !AllowedToHoistLoads[CurLoop];
  if ((!I.isSafeToMove(DontMoveAcrossStore)) &&
      !(HoistConstStores && isInvariantStore(I, TRI, MRI))) {
    LLVM_DEBUG(dbgs() << "LICM: Instruction not safe to move.\n");
    return false;
  }

  // If it is a load then check if it is guaranteed to execute by making sure
  // that it dominates all exiting blocks. If it doesn't, then there is a path
  // out of the loop which does not execute this load, so we can't hoist it.
  // Loads from constant memory are safe to speculate, for example indexed load
  // from a jump table.
  // Stores and side effects are already checked by isSafeToMove.
  if (I.mayLoad() && !mayLoadFromGOTOrConstantPool(I) &&
      !IsGuaranteedToExecute(I.getParent(), CurLoop)) {
    LLVM_DEBUG(dbgs() << "LICM: Load not guaranteed to execute.\n");
    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 (I.isConvergent())
    return false;

  if (!TII->shouldHoist(I, CurLoop))
    return false;

  return true;
}

/// Returns true if the instruction is loop invariant.
bool MachineLICMImpl::IsLoopInvariantInst(MachineInstr &I,
                                          MachineLoop *CurLoop) {
  if (!IsLICMCandidate(I, CurLoop)) {
    LLVM_DEBUG(dbgs() << "LICM: Instruction not a LICM candidate\n");
    return false;
  }
  return CurLoop->isLoopInvariant(I);
}

/// Return true if the specified instruction is used by a phi node and hoisting
/// it could cause a copy to be inserted.
bool MachineLICMImpl::HasLoopPHIUse(const MachineInstr *MI,
                                    MachineLoop *CurLoop) {
  SmallVector<const MachineInstr *, 8> Work(1, MI);
  do {
    MI = Work.pop_back_val();
    for (const MachineOperand &MO : MI->all_defs()) {
      Register Reg = MO.getReg();
      if (!Reg.isVirtual())
        continue;
      for (MachineInstr &UseMI : MRI->use_instructions(Reg)) {
        // A PHI may cause a copy to be inserted.
        if (UseMI.isPHI()) {
          // A PHI inside the loop causes a copy because the live range of Reg is
          // extended across the PHI.
          if (CurLoop->contains(&UseMI))
            return true;
          // A PHI in an exit block can cause a copy to be inserted if the PHI
          // has multiple predecessors in the loop with different values.
          // For now, approximate by rejecting all exit blocks.
          if (isExitBlock(CurLoop, UseMI.getParent()))
            return true;
          continue;
        }
        // Look past copies as well.
        if (UseMI.isCopy() && CurLoop->contains(&UseMI))
          Work.push_back(&UseMI);
      }
    }
  } while (!Work.empty());
  return false;
}

/// Compute operand latency between a def of 'Reg' and an use in the current
/// loop, return true if the target considered it high.
bool MachineLICMImpl::HasHighOperandLatency(MachineInstr &MI, unsigned DefIdx,
                                            Register Reg,
                                            MachineLoop *CurLoop) const {
  if (MRI->use_nodbg_empty(Reg))
    return false;

  for (MachineInstr &UseMI : MRI->use_nodbg_instructions(Reg)) {
    if (UseMI.isCopyLike())
      continue;
    if (!CurLoop->contains(UseMI.getParent()))
      continue;
    for (unsigned i = 0, e = UseMI.getNumOperands(); i != e; ++i) {
      const MachineOperand &MO = UseMI.getOperand(i);
      if (!MO.isReg() || !MO.isUse())
        continue;
      Register MOReg = MO.getReg();
      if (MOReg != Reg)
        continue;

      if (TII->hasHighOperandLatency(SchedModel, MRI, MI, DefIdx, UseMI, i))
        return true;
    }

    // Only look at the first in loop use.
    break;
  }

  return false;
}

/// Return true if the instruction is marked "cheap" or the operand latency
/// between its def and a use is one or less.
bool MachineLICMImpl::IsCheapInstruction(MachineInstr &MI) const {
  if (TII->isAsCheapAsAMove(MI) || MI.isSubregToReg())
    return true;

  bool isCheap = false;
  unsigned NumDefs = MI.getDesc().getNumDefs();
  for (unsigned i = 0, e = MI.getNumOperands(); NumDefs && i != e; ++i) {
    MachineOperand &DefMO = MI.getOperand(i);
    if (!DefMO.isReg() || !DefMO.isDef())
      continue;
    --NumDefs;
    Register Reg = DefMO.getReg();
    if (Reg.isPhysical())
      continue;

    if (!TII->hasLowDefLatency(SchedModel, MI, i))
      return false;
    isCheap = true;
  }

  return isCheap;
}

/// Visit BBs from header to current BB, check if hoisting an instruction of the
/// given cost matrix can cause high register pressure.
bool MachineLICMImpl::CanCauseHighRegPressure(
    const SmallDenseMap<unsigned, int> &Cost, bool CheapInstr) {
  for (const auto &[Class, Weight] : Cost) {
    if (Weight <= 0)
      continue;

    int Limit = RegLimit[Class];

    // Don't hoist cheap instructions if they would increase register pressure,
    // even if we're under the limit.
    if (CheapInstr && !HoistCheapInsts)
      return true;

    for (const auto &RP : BackTrace)
      if (static_cast<int>(RP[Class]) + Weight >= Limit)
        return true;
  }

  return false;
}

/// Traverse the back trace from header to the current block and update their
/// register pressures to reflect the effect of hoisting MI from the current
/// block to the preheader.
void MachineLICMImpl::UpdateBackTraceRegPressure(const MachineInstr *MI) {
  // First compute the 'cost' of the instruction, i.e. its contribution
  // to register pressure.
  auto Cost = calcRegisterCost(MI, /*ConsiderSeen=*/false,
                               /*ConsiderUnseenAsDef=*/false);

  // Update register pressure of blocks from loop header to current block.
  for (auto &RP : BackTrace)
    for (const auto &[Class, Weight] : Cost)
      RP[Class] += Weight;
}

/// Return true if it is potentially profitable to hoist the given loop
/// invariant.
bool MachineLICMImpl::IsProfitableToHoist(MachineInstr &MI,
                                          MachineLoop *CurLoop) {
  if (MI.isImplicitDef())
    return true;

  // Besides removing computation from the loop, hoisting an instruction has
  // these effects:
  //
  // - The value defined by the instruction becomes live across the entire
  //   loop. This increases register pressure in the loop.
  //
  // - If the value is used by a PHI in the loop, a copy will be required for
  //   lowering the PHI after extending the live range.
  //
  // - When hoisting the last use of a value in the loop, that value no longer
  //   needs to be live in the loop. This lowers register pressure in the loop.

  if (HoistConstStores &&  isCopyFeedingInvariantStore(MI, MRI, TRI))
    return true;

  bool CheapInstr = IsCheapInstruction(MI);
  bool CreatesCopy = HasLoopPHIUse(&MI, CurLoop);

  // Don't hoist a cheap instruction if it would create a copy in the loop.
  if (CheapInstr && CreatesCopy) {
    LLVM_DEBUG(dbgs() << "Won't hoist cheap instr with loop PHI use: " << MI);
    return false;
  }

  // Trivially rematerializable instructions should always be hoisted
  // providing the register allocator can just pull them down again when needed.
  if (TII->isTriviallyReMaterializable(MI))
    return true;

  // FIXME: If there are long latency loop-invariant instructions inside the
  // loop at this point, why didn't the optimizer's LICM hoist them?
  for (unsigned i = 0, e = MI.getDesc().getNumOperands(); i != e; ++i) {
    const MachineOperand &MO = MI.getOperand(i);
    if (!MO.isReg() || MO.isImplicit())
      continue;
    Register Reg = MO.getReg();
    if (!Reg.isVirtual())
      continue;
    if (MO.isDef() && HasHighOperandLatency(MI, i, Reg, CurLoop)) {
      LLVM_DEBUG(dbgs() << "Hoist High Latency: " << MI);
      ++NumHighLatency;
      return true;
    }
  }

  // Estimate register pressure to determine whether to LICM the instruction.
  // In low register pressure situation, we can be more aggressive about
  // hoisting. Also, favors hoisting long latency instructions even in
  // moderately high pressure situation.
  // Cheap instructions will only be hoisted if they don't increase register
  // pressure at all.
  auto Cost = calcRegisterCost(&MI, /*ConsiderSeen=*/false,
                               /*ConsiderUnseenAsDef=*/false);

  // Visit BBs from header to current BB, if hoisting this doesn't cause
  // high register pressure, then it's safe to proceed.
  if (!CanCauseHighRegPressure(Cost, CheapInstr)) {
    LLVM_DEBUG(dbgs() << "Hoist non-reg-pressure: " << MI);
    ++NumLowRP;
    return true;
  }

  // Don't risk increasing register pressure if it would create copies.
  if (CreatesCopy) {
    LLVM_DEBUG(dbgs() << "Won't hoist instr with loop PHI use: " << MI);
    return false;
  }

  // Do not "speculate" in high register pressure situation. If an
  // instruction is not guaranteed to be executed in the loop, it's best to be
  // conservative.
  if (AvoidSpeculation &&
      (!IsGuaranteedToExecute(MI.getParent(), CurLoop) && !MayCSE(&MI))) {
    LLVM_DEBUG(dbgs() << "Won't speculate: " << MI);
    return false;
  }

  // If we have a COPY with other uses in the loop, hoist to allow the users to
  // also be hoisted.
  // TODO: Handle all isCopyLike?
  if (MI.isCopy() || MI.isRegSequence()) {
    Register DefReg = MI.getOperand(0).getReg();
    if (DefReg.isVirtual() &&
        all_of(MI.uses(),
               [this](const MachineOperand &UseOp) {
                 return !UseOp.isReg() || UseOp.getReg().isVirtual() ||
                        MRI->isConstantPhysReg(UseOp.getReg());
               }) &&
        IsLoopInvariantInst(MI, CurLoop) &&
        any_of(MRI->use_nodbg_instructions(DefReg),
               [&CurLoop, this, DefReg,
                Cost = std::move(Cost)](MachineInstr &UseMI) {
                 if (!CurLoop->contains(&UseMI))
                   return false;

                 // COPY is a cheap instruction, but if moving it won't cause
                 // high RP we're fine to hoist it even if the user can't be
                 // hoisted later Otherwise we want to check the user if it's
                 // hoistable
                 if (CanCauseHighRegPressure(Cost, false) &&
                     !CurLoop->isLoopInvariant(UseMI, DefReg))
                   return false;

                 return true;
               }))
      return true;
  }

  // High register pressure situation, only hoist if the instruction is going
  // to be remat'ed.
  if (!TII->isTriviallyReMaterializable(MI) &&
      !MI.isDereferenceableInvariantLoad()) {
    LLVM_DEBUG(dbgs() << "Can't remat / high reg-pressure: " << MI);
    return false;
  }

  return true;
}

/// Unfold a load from the given machineinstr if the load itself could be
/// hoisted. Return the unfolded and hoistable load, or null if the load
/// couldn't be unfolded or if it wouldn't be hoistable.
MachineInstr *MachineLICMImpl::ExtractHoistableLoad(MachineInstr *MI,
                                                    MachineLoop *CurLoop) {
  // Don't unfold simple loads.
  if (MI->canFoldAsLoad())
    return nullptr;

  // If not, we may be able to unfold a load and hoist that.
  // First test whether the instruction is loading from an amenable
  // memory location.
  if (!MI->isDereferenceableInvariantLoad())
    return nullptr;

  // Next determine the register class for a temporary register.
  unsigned LoadRegIndex;
  unsigned NewOpc =
    TII->getOpcodeAfterMemoryUnfold(MI->getOpcode(),
                                    /*UnfoldLoad=*/true,
                                    /*UnfoldStore=*/false,
                                    &LoadRegIndex);
  if (NewOpc == 0) return nullptr;
  const MCInstrDesc &MID = TII->get(NewOpc);
  MachineFunction &MF = *MI->getMF();
  const TargetRegisterClass *RC = TII->getRegClass(MID, LoadRegIndex);
  // Ok, we're unfolding. Create a temporary register and do the unfold.
  Register Reg = MRI->createVirtualRegister(RC);

  SmallVector<MachineInstr *, 2> NewMIs;
  bool Success = TII->unfoldMemoryOperand(MF, *MI, Reg,
                                          /*UnfoldLoad=*/true,
                                          /*UnfoldStore=*/false, NewMIs);
  (void)Success;
  assert(Success &&
         "unfoldMemoryOperand failed when getOpcodeAfterMemoryUnfold "
         "succeeded!");
  assert(NewMIs.size() == 2 &&
         "Unfolded a load into multiple instructions!");
  MachineBasicBlock *MBB = MI->getParent();
  MachineBasicBlock::iterator Pos = MI;
  MBB->insert(Pos, NewMIs[0]);
  MBB->insert(Pos, NewMIs[1]);
  // If unfolding produced a load that wasn't loop-invariant or profitable to
  // hoist, discard the new instructions and bail.
  if (!IsLoopInvariantInst(*NewMIs[0], CurLoop) ||
      !IsProfitableToHoist(*NewMIs[0], CurLoop)) {
    NewMIs[0]->eraseFromParent();
    NewMIs[1]->eraseFromParent();
    return nullptr;
  }

  // Update register pressure for the unfolded instruction.
  UpdateRegPressure(NewMIs[1]);

  // Otherwise we successfully unfolded a load that we can hoist.

  // Update the call info.
  if (MI->shouldUpdateAdditionalCallInfo())
    MF.eraseAdditionalCallInfo(MI);

  MI->eraseFromParent();
  return NewMIs[0];
}

/// Initialize the CSE map with instructions that are in the current loop
/// preheader that may become duplicates of instructions that are hoisted
/// out of the loop.
void MachineLICMImpl::InitCSEMap(MachineBasicBlock *BB) {
  for (MachineInstr &MI : *BB)
    CSEMap[BB][MI.getOpcode()].push_back(&MI);
}

/// Initialize AllowedToHoistLoads with information about whether invariant
/// loads can be moved outside a given loop
void MachineLICMImpl::InitializeLoadsHoistableLoops() {
  SmallVector<MachineLoop *, 8> Worklist(MLI->begin(), MLI->end());
  SmallVector<MachineLoop *, 8> LoopsInPreOrder;

  // Mark all loops as hoistable initially and prepare a list of loops in
  // pre-order DFS.
  while (!Worklist.empty()) {
    auto *L = Worklist.pop_back_val();
    AllowedToHoistLoads[L] = true;
    LoopsInPreOrder.push_back(L);
    llvm::append_range(Worklist, L->getSubLoops());
  }

  // Going from the innermost to outermost loops, check if a loop has
  // instructions preventing invariant load hoisting. If such instruction is
  // found, mark this loop and its parent as non-hoistable and continue
  // investigating the next loop.
  // Visiting in a reversed pre-ordered DFS manner
  // allows us to not process all the instructions of the outer loop if the
  // inner loop is proved to be non-load-hoistable.
  for (auto *Loop : reverse(LoopsInPreOrder)) {
    for (auto *MBB : Loop->blocks()) {
      // If this loop has already been marked as non-hoistable, skip it.
      if (!AllowedToHoistLoads[Loop])
        continue;
      for (auto &MI : *MBB) {
        if (!MI.isLoadFoldBarrier() && !MI.mayStore() && !MI.isCall() &&
            !(MI.mayLoad() && MI.hasOrderedMemoryRef()))
          continue;
        for (MachineLoop *L = Loop; L != nullptr; L = L->getParentLoop())
          AllowedToHoistLoads[L] = false;
        break;
      }
    }
  }
}

/// Find an instruction amount PrevMIs that is a duplicate of MI.
/// Return this instruction if it's found.
MachineInstr *
MachineLICMImpl::LookForDuplicate(const MachineInstr *MI,
                                  std::vector<MachineInstr *> &PrevMIs) {
  for (MachineInstr *PrevMI : PrevMIs)
    if (TII->produceSameValue(*MI, *PrevMI, (PreRegAlloc ? MRI : nullptr)))
      return PrevMI;

  return nullptr;
}

/// Given a LICM'ed instruction, look for an instruction on the preheader that
/// computes the same value. If it's found, do a RAU on with the definition of
/// the existing instruction rather than hoisting the instruction to the
/// preheader.
bool MachineLICMImpl::EliminateCSE(
    MachineInstr *MI,
    DenseMap<unsigned, std::vector<MachineInstr *>>::iterator &CI) {
  // Do not CSE implicit_def so ProcessImplicitDefs can properly propagate
  // the undef property onto uses.
  if (MI->isImplicitDef())
    return false;

  // Do not CSE normal loads because between them could be store instructions
  // that change the loaded value
  if (MI->mayLoad() && !MI->isDereferenceableInvariantLoad())
    return false;

  if (MachineInstr *Dup = LookForDuplicate(MI, CI->second)) {
    LLVM_DEBUG(dbgs() << "CSEing " << *MI << " with " << *Dup);

    // Replace virtual registers defined by MI by their counterparts defined
    // by Dup.
    SmallVector<unsigned, 2> Defs;
    for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) {
      const MachineOperand &MO = MI->getOperand(i);

      // Physical registers may not differ here.
      assert((!MO.isReg() || MO.getReg() == 0 || !MO.getReg().isPhysical() ||
              MO.getReg() == Dup->getOperand(i).getReg()) &&
             "Instructions with different phys regs are not identical!");

      if (MO.isReg() && MO.isDef() && !MO.getReg().isPhysical())
        Defs.push_back(i);
    }

    SmallVector<const TargetRegisterClass*, 2> OrigRCs;
    for (unsigned i = 0, e = Defs.size(); i != e; ++i) {
      unsigned Idx = Defs[i];
      Register Reg = MI->getOperand(Idx).getReg();
      Register DupReg = Dup->getOperand(Idx).getReg();
      OrigRCs.push_back(MRI->getRegClass(DupReg));

      if (!MRI->constrainRegClass(DupReg, MRI->getRegClass(Reg))) {
        // Restore old RCs if more than one defs.
        for (unsigned j = 0; j != i; ++j)
          MRI->setRegClass(Dup->getOperand(Defs[j]).getReg(), OrigRCs[j]);
        return false;
      }
    }

    for (unsigned Idx : Defs) {
      Register Reg = MI->getOperand(Idx).getReg();
      Register DupReg = Dup->getOperand(Idx).getReg();
      MRI->replaceRegWith(Reg, DupReg);
      // Clear Dup dead flag if any, we reuse it for Reg.
      if (!MRI->use_nodbg_empty(DupReg))
        Dup->getOperand(Idx).setIsDead(false);
    }

    MI->eraseFromParent();
    ++NumCSEed;
    return true;
  }
  return false;
}

/// Return true if the given instruction will be CSE'd if it's hoisted out of
/// the loop.
bool MachineLICMImpl::MayCSE(MachineInstr *MI) {
  if (MI->mayLoad() && !MI->isDereferenceableInvariantLoad())
    return false;

  unsigned Opcode = MI->getOpcode();
  for (auto &Map : CSEMap) {
    // Check this CSEMap's preheader dominates MI's basic block.
    if (MDTU->getDomTree().dominates(Map.first, MI->getParent())) {
      DenseMap<unsigned, std::vector<MachineInstr *>>::iterator CI =
          Map.second.find(Opcode);
      // Do not CSE implicit_def so ProcessImplicitDefs can properly propagate
      // the undef property onto uses.
      if (CI == Map.second.end() || MI->isImplicitDef())
        continue;
      if (LookForDuplicate(MI, CI->second) != nullptr)
        return true;
    }
  }

  return false;
}

/// When an instruction is found to use only loop invariant operands
/// that are safe to hoist, this instruction is called to do the dirty work.
/// It returns true if the instruction is hoisted.
unsigned MachineLICMImpl::Hoist(MachineInstr *MI, MachineBasicBlock *Preheader,
                                MachineLoop *CurLoop) {
  MachineBasicBlock *SrcBlock = MI->getParent();

  // Disable the instruction hoisting due to block hotness
  if ((DisableHoistingToHotterBlocks == UseBFI::All ||
      (DisableHoistingToHotterBlocks == UseBFI::PGO && HasProfileData)) &&
      isTgtHotterThanSrc(SrcBlock, Preheader)) {
    ++NumNotHoistedDueToHotness;
    return HoistResult::NotHoisted;
  }
  // First check whether we should hoist this instruction.
  bool HasExtractHoistableLoad = false;
  if (!IsLoopInvariantInst(*MI, CurLoop) ||
      !IsProfitableToHoist(*MI, CurLoop)) {
    // If not, try unfolding a hoistable load.
    MI = ExtractHoistableLoad(MI, CurLoop);
    if (!MI)
      return HoistResult::NotHoisted;
    HasExtractHoistableLoad = true;
  }

  // If we have hoisted an instruction that may store, it can only be a constant
  // store.
  if (MI->mayStore())
    NumStoreConst++;

  // Now move the instructions to the predecessor, inserting it before any
  // terminator instructions.
  LLVM_DEBUG({
    dbgs() << "Hoisting " << *MI;
    if (MI->getParent()->getBasicBlock())
      dbgs() << " from " << printMBBReference(*MI->getParent());
    if (Preheader->getBasicBlock())
      dbgs() << " to " << printMBBReference(*Preheader);
    dbgs() << "\n";
  });

  // If this is the first instruction being hoisted to the preheader,
  // initialize the CSE map with potential common expressions.
  if (FirstInLoop) {
    InitCSEMap(Preheader);
    FirstInLoop = false;
  }

  // Look for opportunity to CSE the hoisted instruction.
  unsigned Opcode = MI->getOpcode();
  bool HasCSEDone = false;
  for (auto &Map : CSEMap) {
    // Check this CSEMap's preheader dominates MI's basic block.
    if (MDTU->getDomTree().dominates(Map.first, MI->getParent())) {
      DenseMap<unsigned, std::vector<MachineInstr *>>::iterator CI =
          Map.second.find(Opcode);
      if (CI != Map.second.end()) {
        if (EliminateCSE(MI, CI)) {
          HasCSEDone = true;
          break;
        }
      }
    }
  }

  if (!HasCSEDone) {
    // Otherwise, splice the instruction to the preheader.
    Preheader->splice(Preheader->getFirstTerminator(),MI->getParent(),MI);

    // Since we are moving the instruction out of its basic block, we do not
    // retain its debug location. Doing so would degrade the debugging
    // experience and adversely affect the accuracy of profiling information.
    assert(!MI->isDebugInstr() && "Should not hoist debug inst");
    MI->setDebugLoc(DebugLoc());

    // Update register pressure for BBs from header to this block.
    UpdateBackTraceRegPressure(MI);

    CSEMap[Preheader][Opcode].push_back(MI);
  }

  ++NumHoisted;
  Changed = true;

  if (HasCSEDone || HasExtractHoistableLoad)
    return HoistResult::Hoisted | HoistResult::ErasedMI;
  return HoistResult::Hoisted;
}

/// Get the preheader for the current loop, splitting a critical edge if needed.
MachineBasicBlock *MachineLICMImpl::getOrCreatePreheader(MachineLoop *CurLoop) {
  // Determine the block to which to hoist instructions. If we can't find a
  // suitable loop predecessor, we can't do any hoisting.
  if (MachineBasicBlock *Preheader = CurLoop->getLoopPreheader())
    return Preheader;

  // Try forming a preheader by splitting the critical edge between the single
  // predecessor and the loop header.
  if (MachineBasicBlock *Pred = CurLoop->getLoopPredecessor()) {
    MachineBasicBlock *NewPreheader = Pred->SplitCriticalEdge(
        CurLoop->getHeader(), {nullptr, nullptr, MLI}, MDTU);
    if (NewPreheader)
      Changed = true;
    return NewPreheader;
  }

  return nullptr;
}

/// Is the target basic block at least "BlockFrequencyRatioThreshold"
/// times hotter than the source basic block.
bool MachineLICMImpl::isTgtHotterThanSrc(MachineBasicBlock *SrcBlock,
                                         MachineBasicBlock *TgtBlock) {
  // Parse source and target basic block frequency from MBFI
  uint64_t SrcBF = MBFI->getBlockFreq(SrcBlock).getFrequency();
  uint64_t DstBF = MBFI->getBlockFreq(TgtBlock).getFrequency();

  // Disable the hoisting if source block frequency is zero
  if (!SrcBF)
    return true;

  double Ratio = (double)DstBF / SrcBF;

  // Compare the block frequency ratio with the threshold
  return Ratio > BlockFrequencyRatioThreshold;
}

template <typename DerivedT, bool PreRegAlloc>
PreservedAnalyses MachineLICMBasePass<DerivedT, PreRegAlloc>::run(
    MachineFunction &MF, MachineFunctionAnalysisManager &MFAM) {
  bool Changed = MachineLICMImpl(PreRegAlloc, nullptr, &MFAM).run(MF);
  if (!Changed)
    return PreservedAnalyses::all();
  auto PA = getMachineFunctionPassPreservedAnalyses();
  PA.preserve<MachineLoopAnalysis>();
  PA.preserve<MachineDominatorTreeAnalysis>();
  return PA;
}

template class llvm::MachineLICMBasePass<EarlyMachineLICMPass, true>;
template class llvm::MachineLICMBasePass<MachineLICMPass, false>;
