//===- MachineSink.cpp - Sinking for machine instructions -----------------===//
//
// 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 moves instructions into successor blocks when possible, so that
// they aren't executed on paths where their results aren't needed.
//
// This pass is not intended to be a replacement or a complete alternative
// for an LLVM-IR-level sinking pass. It is only designed to sink simple
// constructs that are not exposed before lowering and instruction selection.
//
//===----------------------------------------------------------------------===//

#include "llvm/CodeGen/MachineSink.h"
#include "llvm/ADT/DenseSet.h"
#include "llvm/ADT/DepthFirstIterator.h"
#include "llvm/ADT/MapVector.h"
#include "llvm/ADT/PointerIntPair.h"
#include "llvm/ADT/SetVector.h"
#include "llvm/ADT/SmallSet.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/Statistic.h"
#include "llvm/Analysis/AliasAnalysis.h"
#include "llvm/Analysis/CFG.h"
#include "llvm/Analysis/ProfileSummaryInfo.h"
#include "llvm/CodeGen/LiveIntervals.h"
#include "llvm/CodeGen/MachineBasicBlock.h"
#include "llvm/CodeGen/MachineBlockFrequencyInfo.h"
#include "llvm/CodeGen/MachineBranchProbabilityInfo.h"
#include "llvm/CodeGen/MachineCycleAnalysis.h"
#include "llvm/CodeGen/MachineDomTreeUpdater.h"
#include "llvm/CodeGen/MachineDominators.h"
#include "llvm/CodeGen/MachineFunction.h"
#include "llvm/CodeGen/MachineFunctionPass.h"
#include "llvm/CodeGen/MachineInstr.h"
#include "llvm/CodeGen/MachineLoopInfo.h"
#include "llvm/CodeGen/MachineOperand.h"
#include "llvm/CodeGen/MachinePostDominators.h"
#include "llvm/CodeGen/MachineRegisterInfo.h"
#include "llvm/CodeGen/MachineSizeOpts.h"
#include "llvm/CodeGen/PostRAMachineSink.h"
#include "llvm/CodeGen/RegisterClassInfo.h"
#include "llvm/CodeGen/RegisterPressure.h"
#include "llvm/CodeGen/SlotIndexes.h"
#include "llvm/CodeGen/TargetInstrInfo.h"
#include "llvm/CodeGen/TargetPassConfig.h"
#include "llvm/CodeGen/TargetRegisterInfo.h"
#include "llvm/CodeGen/TargetSchedule.h"
#include "llvm/CodeGen/TargetSubtargetInfo.h"
#include "llvm/IR/BasicBlock.h"
#include "llvm/IR/DebugInfoMetadata.h"
#include "llvm/IR/LLVMContext.h"
#include "llvm/InitializePasses.h"
#include "llvm/Pass.h"
#include "llvm/Support/BranchProbability.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/raw_ostream.h"
#include <cassert>
#include <cstdint>
#include <utility>
#include <vector>

using namespace llvm;

#define DEBUG_TYPE "machine-sink"

static cl::opt<bool>
    SplitEdges("machine-sink-split",
               cl::desc("Split critical edges during machine sinking"),
               cl::init(true), cl::Hidden);

static cl::opt<bool> UseBlockFreqInfo(
    "machine-sink-bfi",
    cl::desc("Use block frequency info to find successors to sink"),
    cl::init(true), cl::Hidden);

static cl::opt<unsigned> SplitEdgeProbabilityThreshold(
    "machine-sink-split-probability-threshold",
    cl::desc(
        "Percentage threshold for splitting single-instruction critical edge. "
        "If the branch threshold is higher than this threshold, we allow "
        "speculative execution of up to 1 instruction to avoid branching to "
        "splitted critical edge"),
    cl::init(40), cl::Hidden);

static cl::opt<unsigned> SinkLoadInstsPerBlockThreshold(
    "machine-sink-load-instrs-threshold",
    cl::desc("Do not try to find alias store for a load if there is a in-path "
             "block whose instruction number is higher than this threshold."),
    cl::init(2000), cl::Hidden);

static cl::opt<unsigned> SinkLoadBlocksThreshold(
    "machine-sink-load-blocks-threshold",
    cl::desc("Do not try to find alias store for a load if the block number in "
             "the straight line is higher than this threshold."),
    cl::init(20), cl::Hidden);

static cl::opt<bool>
    SinkInstsIntoCycle("sink-insts-to-avoid-spills",
                       cl::desc("Sink instructions into cycles to avoid "
                                "register spills"),
                       cl::init(false), cl::Hidden);

static cl::opt<unsigned> SinkIntoCycleLimit(
    "machine-sink-cycle-limit",
    cl::desc(
        "The maximum number of instructions considered for cycle sinking."),
    cl::init(50), cl::Hidden);

STATISTIC(NumSunk, "Number of machine instructions sunk");
STATISTIC(NumCycleSunk, "Number of machine instructions sunk into a cycle");
STATISTIC(NumSplit, "Number of critical edges split");
STATISTIC(NumCoalesces, "Number of copies coalesced");
STATISTIC(NumPostRACopySink, "Number of copies sunk after RA");

using RegSubRegPair = TargetInstrInfo::RegSubRegPair;

namespace {

class MachineSinking {
  const TargetSubtargetInfo *STI = nullptr;
  const TargetInstrInfo *TII = nullptr;
  const TargetRegisterInfo *TRI = nullptr;
  MachineRegisterInfo *MRI = nullptr;      // Machine register information
  MachineDominatorTree *DT = nullptr;      // Machine dominator tree
  MachinePostDominatorTree *PDT = nullptr; // Machine post dominator tree
  MachineCycleInfo *CI = nullptr;
  ProfileSummaryInfo *PSI = nullptr;
  MachineBlockFrequencyInfo *MBFI = nullptr;
  const MachineBranchProbabilityInfo *MBPI = nullptr;
  AliasAnalysis *AA = nullptr;
  RegisterClassInfo *RegClassInfo = nullptr;
  TargetSchedModel SchedModel;
  // Required for split critical edge
  LiveIntervals *LIS;
  SlotIndexes *SI;
  MachineLoopInfo *MLI;

  // Remember which edges have been considered for breaking.
  SmallSet<std::pair<MachineBasicBlock *, MachineBasicBlock *>, 8>
      CEBCandidates;
  // Memorize the register that also wanted to sink into the same block along
  // a different critical edge.
  // {register to sink, sink-to block} -> the first sink-from block.
  // We're recording the first sink-from block because that (critical) edge
  // was deferred until we see another register that's going to sink into the
  // same block.
  DenseMap<std::pair<Register, MachineBasicBlock *>, MachineBasicBlock *>
      CEMergeCandidates;
  // Remember which edges we are about to split.
  // This is different from CEBCandidates since those edges
  // will be split.
  SetVector<std::pair<MachineBasicBlock *, MachineBasicBlock *>> ToSplit;

  DenseSet<Register> RegsToClearKillFlags;

  using AllSuccsCache =
      SmallDenseMap<MachineBasicBlock *, SmallVector<MachineBasicBlock *, 4>>;

  /// DBG_VALUE pointer and flag. The flag is true if this DBG_VALUE is
  /// post-dominated by another DBG_VALUE of the same variable location.
  /// This is necessary to detect sequences such as:
  ///     %0 = someinst
  ///     DBG_VALUE %0, !123, !DIExpression()
  ///     %1 = anotherinst
  ///     DBG_VALUE %1, !123, !DIExpression()
  /// Where if %0 were to sink, the DBG_VAUE should not sink with it, as that
  /// would re-order assignments.
  using SeenDbgUser = PointerIntPair<MachineInstr *, 1>;

  using SinkItem = std::pair<MachineInstr *, MachineBasicBlock *>;

  /// Record of DBG_VALUE uses of vregs in a block, so that we can identify
  /// debug instructions to sink.
  SmallDenseMap<Register, TinyPtrVector<SeenDbgUser>> SeenDbgUsers;

  /// Record of debug variables that have had their locations set in the
  /// current block.
  DenseSet<DebugVariable> SeenDbgVars;

  DenseMap<std::pair<MachineBasicBlock *, MachineBasicBlock *>, bool>
      HasStoreCache;

  DenseMap<std::pair<MachineBasicBlock *, MachineBasicBlock *>,
           SmallVector<MachineInstr *>>
      StoreInstrCache;

  /// Cached BB's register pressure.
  DenseMap<const MachineBasicBlock *, std::vector<unsigned>>
      CachedRegisterPressure;

  bool EnableSinkAndFold;

public:
  MachineSinking(bool EnableSinkAndFold, MachineDominatorTree *DT,
                 MachinePostDominatorTree *PDT, MachineLoopInfo *MLI,
                 SlotIndexes *SI, LiveIntervals *LIS, MachineCycleInfo *CI,
                 ProfileSummaryInfo *PSI, MachineBlockFrequencyInfo *MBFI,
                 const MachineBranchProbabilityInfo *MBPI, AliasAnalysis *AA,
                 RegisterClassInfo *RegClassInfo)
      : DT(DT), PDT(PDT), CI(CI), PSI(PSI), MBFI(MBFI), MBPI(MBPI), AA(AA),
        RegClassInfo(RegClassInfo), LIS(LIS), SI(SI), MLI(MLI),
        EnableSinkAndFold(EnableSinkAndFold) {}

  bool run(MachineFunction &MF);

  void releaseMemory() {
    CEBCandidates.clear();
    CEMergeCandidates.clear();
  }

private:
  bool ProcessBlock(MachineBasicBlock &MBB);
  void ProcessDbgInst(MachineInstr &MI);
  bool isLegalToBreakCriticalEdge(MachineInstr &MI, MachineBasicBlock *From,
                                  MachineBasicBlock *To, bool BreakPHIEdge);
  bool isWorthBreakingCriticalEdge(MachineInstr &MI, MachineBasicBlock *From,
                                   MachineBasicBlock *To,
                                   MachineBasicBlock *&DeferredFromBlock);

  bool hasStoreBetween(MachineBasicBlock *From, MachineBasicBlock *To,
                       MachineInstr &MI);

  /// Postpone the splitting of the given critical
  /// edge (\p From, \p To).
  ///
  /// We do not split the edges on the fly. Indeed, this invalidates
  /// the dominance information and thus triggers a lot of updates
  /// of that information underneath.
  /// Instead, we postpone all the splits after each iteration of
  /// the main loop. That way, the information is at least valid
  /// for the lifetime of an iteration.
  ///
  /// \return True if the edge is marked as toSplit, false otherwise.
  /// False can be returned if, for instance, this is not profitable.
  bool PostponeSplitCriticalEdge(MachineInstr &MI, MachineBasicBlock *From,
                                 MachineBasicBlock *To, bool BreakPHIEdge);
  bool SinkInstruction(MachineInstr &MI, bool &SawStore,
                       AllSuccsCache &AllSuccessors);

  /// If we sink a COPY inst, some debug users of it's destination may no
  /// longer be dominated by the COPY, and will eventually be dropped.
  /// This is easily rectified by forwarding the non-dominated debug uses
  /// to the copy source.
  void SalvageUnsunkDebugUsersOfCopy(MachineInstr &,
                                     MachineBasicBlock *TargetBlock);
  bool AllUsesDominatedByBlock(Register Reg, MachineBasicBlock *MBB,
                               MachineBasicBlock *DefMBB, bool &BreakPHIEdge,
                               bool &LocalUse) const;
  MachineBasicBlock *FindSuccToSinkTo(MachineInstr &MI, MachineBasicBlock *MBB,
                                      bool &BreakPHIEdge,
                                      AllSuccsCache &AllSuccessors);

  void FindCycleSinkCandidates(CycleRef Cycle, MachineBasicBlock *BB,
                               SmallVectorImpl<MachineInstr *> &Candidates);

  bool
  aggressivelySinkIntoCycle(CycleRef Cycle, MachineInstr &I,
                            DenseMap<SinkItem, MachineInstr *> &SunkInstrs);

  bool isProfitableToSinkTo(Register Reg, MachineInstr &MI,
                            MachineBasicBlock *MBB,
                            MachineBasicBlock *SuccToSinkTo,
                            AllSuccsCache &AllSuccessors);

  bool PerformTrivialForwardCoalescing(MachineInstr &MI,
                                       MachineBasicBlock *MBB);

  bool PerformSinkAndFold(MachineInstr &MI, MachineBasicBlock *MBB);

  SmallVector<MachineBasicBlock *, 4> &
  GetAllSortedSuccessors(MachineInstr &MI, MachineBasicBlock *MBB,
                         AllSuccsCache &AllSuccessors) const;

  std::vector<unsigned> &getBBRegisterPressure(const MachineBasicBlock &MBB,
                                               bool UseCache = true);

  bool registerPressureSetExceedsLimit(unsigned NRegs,
                                       const TargetRegisterClass *RC,
                                       const MachineBasicBlock &MBB);

  bool registerPressureExceedsLimit(const MachineBasicBlock &MBB);
};

class MachineSinkingLegacy : public MachineFunctionPass {
public:
  static char ID;

  MachineSinkingLegacy() : MachineFunctionPass(ID) {}

  bool runOnMachineFunction(MachineFunction &MF) override;

  void getAnalysisUsage(AnalysisUsage &AU) const override {
    MachineFunctionPass::getAnalysisUsage(AU);
    AU.addRequired<AAResultsWrapperPass>();
    AU.addRequired<MachineDominatorTreeWrapperPass>();
    AU.addRequired<MachinePostDominatorTreeWrapperPass>();
    AU.addRequired<MachineCycleInfoWrapperPass>();
    AU.addRequired<MachineBranchProbabilityInfoWrapperPass>();
    AU.addRequired<MachineRegisterClassInfoWrapperPass>();
    AU.addPreserved<MachineCycleInfoWrapperPass>();
    AU.addPreserved<MachineLoopInfoWrapperPass>();
    AU.addPreserved<MachineRegisterClassInfoWrapperPass>();
    AU.addRequired<ProfileSummaryInfoWrapperPass>();
    if (UseBlockFreqInfo) {
      AU.addRequired<MachineBlockFrequencyInfoWrapperPass>();
      AU.addPreserved<MachineBlockFrequencyInfoWrapperPass>();
    }
    AU.addRequired<TargetPassConfig>();
  }
};

} // end anonymous namespace

char MachineSinkingLegacy::ID = 0;

char &llvm::MachineSinkingLegacyID = MachineSinkingLegacy::ID;

INITIALIZE_PASS_BEGIN(MachineSinkingLegacy, DEBUG_TYPE, "Machine code sinking",
                      false, false)
INITIALIZE_PASS_DEPENDENCY(ProfileSummaryInfoWrapperPass)
INITIALIZE_PASS_DEPENDENCY(MachineBranchProbabilityInfoWrapperPass)
INITIALIZE_PASS_DEPENDENCY(MachineDominatorTreeWrapperPass)
INITIALIZE_PASS_DEPENDENCY(MachineCycleInfoWrapperPass)
INITIALIZE_PASS_DEPENDENCY(MachineRegisterClassInfoWrapperPass)
INITIALIZE_PASS_DEPENDENCY(AAResultsWrapperPass)
INITIALIZE_PASS_END(MachineSinkingLegacy, DEBUG_TYPE, "Machine code sinking",
                    false, false)

/// Return true if a target defined block prologue instruction interferes
/// with a sink candidate.
static bool blockPrologueInterferes(const MachineBasicBlock *BB,
                                    MachineBasicBlock::const_iterator End,
                                    const MachineInstr &MI,
                                    const TargetRegisterInfo *TRI,
                                    const TargetInstrInfo *TII,
                                    const MachineRegisterInfo *MRI) {
  for (MachineBasicBlock::const_iterator PI = BB->getFirstNonPHI(); PI != End;
       ++PI) {
    // Only check target defined prologue instructions
    if (!TII->isBasicBlockPrologue(*PI))
      continue;
    for (auto &MO : MI.operands()) {
      if (!MO.isReg())
        continue;
      Register Reg = MO.getReg();
      if (!Reg)
        continue;
      if (MO.isUse()) {
        if (Reg.isPhysical() &&
            (TII->isIgnorableUse(MI, MI.getOperandNo(&MO)) ||
             (MRI && MRI->isConstantPhysReg(Reg))))
          continue;
        if (PI->modifiesRegister(Reg, TRI))
          return true;
      } else {
        if (PI->readsRegister(Reg, TRI))
          return true;
        // Check for interference with non-dead defs
        auto *DefOp = PI->findRegisterDefOperand(Reg, TRI, false, true);
        if (DefOp && !DefOp->isDead())
          return true;
      }
    }
  }

  return false;
}

bool MachineSinking::PerformTrivialForwardCoalescing(MachineInstr &MI,
                                                     MachineBasicBlock *MBB) {
  if (!MI.isCopy())
    return false;

  Register SrcReg = MI.getOperand(1).getReg();
  Register DstReg = MI.getOperand(0).getReg();
  if (!SrcReg.isVirtual() || !DstReg.isVirtual() ||
      !MRI->hasOneNonDBGUse(SrcReg))
    return false;

  const TargetRegisterClass *SRC = MRI->getRegClass(SrcReg);
  const TargetRegisterClass *DRC = MRI->getRegClass(DstReg);
  if (SRC != DRC)
    return false;

  MachineInstr *DefMI = MRI->getVRegDef(SrcReg);
  if (!DefMI || DefMI->isCopyLike())
    return false;
  LLVM_DEBUG(dbgs() << "Coalescing: " << *DefMI);
  LLVM_DEBUG(dbgs() << "*** to: " << MI);
  MRI->replaceRegWith(DstReg, SrcReg);
  MI.eraseFromParent();

  // Conservatively, clear any kill flags, since it's possible that they are no
  // longer correct.
  MRI->clearKillFlags(SrcReg);

  ++NumCoalesces;
  return true;
}

bool MachineSinking::PerformSinkAndFold(MachineInstr &MI,
                                        MachineBasicBlock *MBB) {
  if (MI.isCopy() || MI.mayLoadOrStore() ||
      MI.getOpcode() == TargetOpcode::REG_SEQUENCE)
    return false;

  // Don't sink instructions that the target prefers not to sink.
  if (!TII->shouldSink(MI))
    return false;

  // Check if it's safe to move the instruction.
  bool SawStore = true;
  if (!MI.isSafeToMove(SawStore))
    return false;

  // Convergent operations may not be made control-dependent on additional
  // values.
  if (MI.isConvergent())
    return false;

  // Don't sink defs/uses of hard registers or if the instruction defines more
  // than one register.
  // Don't sink more than two register uses - it'll cover most of the cases and
  // greatly simplifies the register pressure checks.
  Register DefReg;
  Register UsedRegA, UsedRegB;
  for (const MachineOperand &MO : MI.operands()) {
    if (MO.isImm() || MO.isRegMask() || MO.isRegLiveOut() || MO.isMetadata() ||
        MO.isMCSymbol() || MO.isDbgInstrRef() || MO.isCFIIndex() ||
        MO.isIntrinsicID() || MO.isPredicate() || MO.isShuffleMask())
      continue;
    if (!MO.isReg())
      return false;

    Register Reg = MO.getReg();
    if (Reg == 0)
      continue;

    if (Reg.isVirtual()) {
      if (MO.isDef()) {
        if (DefReg)
          return false;
        DefReg = Reg;
        continue;
      }

      if (UsedRegA == 0)
        UsedRegA = Reg;
      else if (UsedRegB == 0)
        UsedRegB = Reg;
      else
        return false;
      continue;
    }

    if (Reg.isPhysical() && MO.isUse() &&
        (MRI->isConstantPhysReg(Reg) ||
         TII->isIgnorableUse(MI, MI.getOperandNo(&MO))))
      continue;

    return false;
  }

  // Scan uses of the destination register. Every use, except the last, must be
  // a copy, with a chain of copies terminating with either a copy into a hard
  // register, or a load/store instruction where the use is part of the
  // address (*not* the stored value).
  using SinkInfo = std::pair<MachineInstr *, ExtAddrMode>;
  SmallVector<SinkInfo> SinkInto;
  SmallVector<Register> Worklist;

  const TargetRegisterClass *RC = MRI->getRegClass(DefReg);
  const TargetRegisterClass *RCA =
      UsedRegA == 0 ? nullptr : MRI->getRegClass(UsedRegA);
  const TargetRegisterClass *RCB =
      UsedRegB == 0 ? nullptr : MRI->getRegClass(UsedRegB);

  Worklist.push_back(DefReg);
  while (!Worklist.empty()) {
    Register Reg = Worklist.pop_back_val();

    for (MachineOperand &MO : MRI->use_nodbg_operands(Reg)) {
      ExtAddrMode MaybeAM;
      MachineInstr &UseInst = *MO.getParent();
      if (UseInst.isCopy()) {
        Register DstReg;
        if (const MachineOperand &O = UseInst.getOperand(0); O.isReg())
          DstReg = O.getReg();
        if (DstReg == 0)
          return false;
        if (DstReg.isVirtual()) {
          Worklist.push_back(DstReg);
          continue;
        }
        // If we are going to replace a copy, the original instruction must be
        // as cheap as a copy.
        if (!TII->isAsCheapAsAMove(MI))
          return false;
        // The hard register must be in the register class of the original
        // instruction's destination register.
        if (!RC->contains(DstReg))
          return false;
      } else if (UseInst.mayLoadOrStore()) {
        // If the destination instruction contains more than one use of the
        // register, we won't be able to remove the original instruction, so
        // don't sink.
        if (llvm::count_if(UseInst.operands(), [Reg](const MachineOperand &MO) {
              return MO.isReg() && MO.getReg() == Reg;
            }) > 1)
          return false;
        ExtAddrMode AM;
        if (!TII->canFoldIntoAddrMode(UseInst, Reg, MI, AM))
          return false;
        MaybeAM = AM;
      } else {
        return false;
      }

      if (UseInst.getParent() != MI.getParent()) {
        // If the register class of the register we are replacing is a superset
        // of any of the register classes of the operands of the materialized
        // instruction don't consider that live range extended.
        const TargetRegisterClass *RCS = MRI->getRegClass(Reg);
        if (RCA && RCA->hasSuperClassEq(RCS))
          RCA = nullptr;
        else if (RCB && RCB->hasSuperClassEq(RCS))
          RCB = nullptr;
        if (RCA || RCB) {
          if (RCA == nullptr) {
            RCA = RCB;
            RCB = nullptr;
          }

          unsigned NRegs = !!RCA + !!RCB;
          if (RCA == RCB)
            RCB = nullptr;

          // Check we don't exceed register pressure at the destination.
          const MachineBasicBlock &MBB = *UseInst.getParent();
          if (RCB == nullptr) {
            if (registerPressureSetExceedsLimit(NRegs, RCA, MBB))
              return false;
          } else if (registerPressureSetExceedsLimit(1, RCA, MBB) ||
                     registerPressureSetExceedsLimit(1, RCB, MBB)) {
            return false;
          }
        }
      }

      SinkInto.emplace_back(&UseInst, MaybeAM);
    }
  }

  if (SinkInto.empty())
    return false;

  // Now we know we can fold the instruction in all its users.
  for (auto &[SinkDst, MaybeAM] : SinkInto) {
    MachineInstr *New = nullptr;
    LLVM_DEBUG(dbgs() << "Sinking copy of"; MI.dump(); dbgs() << "into";
               SinkDst->dump());
    if (SinkDst->isCopy()) {
      // TODO: After performing the sink-and-fold, the original instruction is
      // deleted. Its value is still available (in a hard register), so if there
      // are debug instructions which refer to the (now deleted) virtual
      // register they could be updated to refer to the hard register, in
      // principle. However, it's not clear how to do that, moreover in some
      // cases the debug instructions may need to be replicated proportionally
      // to the number of the COPY instructions replaced and in some extreme
      // cases we can end up with quadratic increase in the number of debug
      // instructions.

      // Sink a copy of the instruction, replacing a COPY instruction.
      MachineBasicBlock::iterator InsertPt = SinkDst->getIterator();
      Register DstReg = SinkDst->getOperand(0).getReg();
      TII->reMaterialize(*SinkDst->getParent(), InsertPt, DstReg, 0, MI);
      New = &*std::prev(InsertPt);
      if (!New->getDebugLoc())
        New->setDebugLoc(SinkDst->getDebugLoc());

      // The operand registers of the "sunk" instruction have their live range
      // extended and their kill flags may no longer be correct. Conservatively
      // clear the kill flags.
      if (UsedRegA)
        MRI->clearKillFlags(UsedRegA);
      if (UsedRegB)
        MRI->clearKillFlags(UsedRegB);
    } else {
      // Fold instruction into the addressing mode of a memory instruction.
      New = TII->emitLdStWithAddr(*SinkDst, MaybeAM);

      // The registers of the addressing mode may have their live range extended
      // and their kill flags may no longer be correct. Conservatively clear the
      // kill flags.
      if (Register R = MaybeAM.BaseReg; R.isValid() && R.isVirtual())
        MRI->clearKillFlags(R);
      if (Register R = MaybeAM.ScaledReg; R.isValid() && R.isVirtual())
        MRI->clearKillFlags(R);
    }
    LLVM_DEBUG(dbgs() << "yielding"; New->dump());
    // Clear the StoreInstrCache, since we may invalidate it by erasing.
    if (SinkDst->mayStore() && !SinkDst->hasOrderedMemoryRef())
      StoreInstrCache.clear();
    SinkDst->eraseFromParent();
  }

  // Collect operands that need to be cleaned up because the registers no longer
  // exist (in COPYs and debug instructions). We cannot delete instructions or
  // clear operands while traversing register uses.
  SmallVector<MachineOperand *> Cleanup;
  Worklist.push_back(DefReg);
  while (!Worklist.empty()) {
    Register Reg = Worklist.pop_back_val();
    for (MachineOperand &MO : MRI->use_operands(Reg)) {
      MachineInstr *U = MO.getParent();
      assert((U->isCopy() || U->isDebugInstr()) &&
             "Only debug uses and copies must remain");
      if (U->isCopy())
        Worklist.push_back(U->getOperand(0).getReg());
      Cleanup.push_back(&MO);
    }
  }

  // Delete the dead COPYs and clear operands in debug instructions
  for (MachineOperand *MO : Cleanup) {
    MachineInstr *I = MO->getParent();
    if (I->isCopy()) {
      I->eraseFromParent();
    } else {
      MO->setReg(0);
      MO->setSubReg(0);
    }
  }

  MI.eraseFromParent();
  return true;
}

/// AllUsesDominatedByBlock - Return true if all uses of the specified register
/// occur in blocks dominated by the specified block. If any use is in the
/// definition block, then return false since it is never legal to move def
/// after uses.
bool MachineSinking::AllUsesDominatedByBlock(Register Reg,
                                             MachineBasicBlock *MBB,
                                             MachineBasicBlock *DefMBB,
                                             bool &BreakPHIEdge,
                                             bool &LocalUse) const {
  assert(Reg.isVirtual() && "Only makes sense for vregs");

  // Ignore debug uses because debug info doesn't affect the code.
  if (MRI->use_nodbg_empty(Reg))
    return true;

  // BreakPHIEdge is true if all the uses are in the successor MBB being sunken
  // into and they are all PHI nodes. In this case, machine-sink must break
  // the critical edge first. e.g.
  //
  // %bb.1:
  //   Predecessors according to CFG: %bb.0
  //     ...
  //     %def = DEC64_32r %x, implicit-def dead %eflags
  //     ...
  //     JE_4 <%bb.37>, implicit %eflags
  //   Successors according to CFG: %bb.37 %bb.2
  //
  // %bb.2:
  //     %p = PHI %y, %bb.0, %def, %bb.1
  if (all_of(MRI->use_nodbg_operands(Reg), [&](MachineOperand &MO) {
        MachineInstr *UseInst = MO.getParent();
        unsigned OpNo = MO.getOperandNo();
        MachineBasicBlock *UseBlock = UseInst->getParent();
        return UseBlock == MBB && UseInst->isPHI() &&
               UseInst->getOperand(OpNo + 1).getMBB() == DefMBB;
      })) {
    BreakPHIEdge = true;
    return true;
  }

  for (MachineOperand &MO : MRI->use_nodbg_operands(Reg)) {
    // Determine the block of the use.
    MachineInstr *UseInst = MO.getParent();
    unsigned OpNo = &MO - &UseInst->getOperand(0);
    MachineBasicBlock *UseBlock = UseInst->getParent();
    if (UseInst->isPHI()) {
      // PHI nodes use the operand in the predecessor block, not the block with
      // the PHI.
      UseBlock = UseInst->getOperand(OpNo + 1).getMBB();
    } else if (UseBlock == DefMBB) {
      LocalUse = true;
      return false;
    }

    // Check that it dominates.
    if (!DT->dominates(MBB, UseBlock))
      return false;
  }

  return true;
}

/// 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;
}

void MachineSinking::FindCycleSinkCandidates(
    CycleRef Cycle, MachineBasicBlock *BB,
    SmallVectorImpl<MachineInstr *> &Candidates) {
  for (auto &MI : *BB) {
    LLVM_DEBUG(dbgs() << "CycleSink: Analysing candidate: " << MI);
    if (MI.isMetaInstruction()) {
      LLVM_DEBUG(dbgs() << "CycleSink: not sinking meta instruction\n");
      continue;
    }
    if (!TII->shouldSink(MI)) {
      LLVM_DEBUG(dbgs() << "CycleSink: Instruction not a candidate for this "
                           "target\n");
      continue;
    }
    if (!isCycleInvariant(*CI, Cycle, MI)) {
      LLVM_DEBUG(dbgs() << "CycleSink: Instruction is not cycle invariant\n");
      continue;
    }
    bool DontMoveAcrossStore = true;
    if (!MI.isSafeToMove(DontMoveAcrossStore)) {
      LLVM_DEBUG(dbgs() << "CycleSink: Instruction not safe to move.\n");
      continue;
    }
    if (MI.mayLoad() && !mayLoadFromGOTOrConstantPool(MI)) {
      LLVM_DEBUG(dbgs() << "CycleSink: Dont sink GOT or constant pool loads\n");
      continue;
    }
    if (MI.isConvergent())
      continue;

    const MachineOperand &MO = MI.getOperand(0);
    if (!MO.isReg() || !MO.getReg() || !MO.isDef())
      continue;
    if (!MRI->hasOneDef(MO.getReg()))
      continue;

    LLVM_DEBUG(dbgs() << "CycleSink: Instruction added as candidate.\n");
    Candidates.push_back(&MI);
  }
}

PreservedAnalyses
MachineSinkingPass::run(MachineFunction &MF,
                        MachineFunctionAnalysisManager &MFAM) {
  auto *DT = &MFAM.getResult<MachineDominatorTreeAnalysis>(MF);
  auto *PDT = &MFAM.getResult<MachinePostDominatorTreeAnalysis>(MF);
  auto *CI = &MFAM.getResult<MachineCycleAnalysis>(MF);
  auto *PSI = MFAM.getResult<ModuleAnalysisManagerMachineFunctionProxy>(MF)
                  .getCachedResult<ProfileSummaryAnalysis>(
                      *MF.getFunction().getParent());
  auto *MBFI = UseBlockFreqInfo
                   ? &MFAM.getResult<MachineBlockFrequencyAnalysis>(MF)
                   : nullptr;
  auto *MBPI = &MFAM.getResult<MachineBranchProbabilityAnalysis>(MF);
  auto *AA = &MFAM.getResult<FunctionAnalysisManagerMachineFunctionProxy>(MF)
                  .getManager()
                  .getResult<AAManager>(MF.getFunction());
  auto *LIS = MFAM.getCachedResult<LiveIntervalsAnalysis>(MF);
  auto *SI = MFAM.getCachedResult<SlotIndexesAnalysis>(MF);
  auto *MLI = MFAM.getCachedResult<MachineLoopAnalysis>(MF);
  auto *RegClassInfo = &MFAM.getResult<MachineRegisterClassAnalysis>(MF);
  MachineSinking Impl(EnableSinkAndFold, DT, PDT, MLI, SI, LIS, CI, PSI, MBFI,
                      MBPI, AA, RegClassInfo);
  bool Changed = Impl.run(MF);
  if (!Changed)
    return PreservedAnalyses::all();
  auto PA = getMachineFunctionPassPreservedAnalyses();
  PA.preserve<MachineCycleAnalysis>();
  PA.preserve<MachineLoopAnalysis>();
  if (UseBlockFreqInfo)
    PA.preserve<MachineBlockFrequencyAnalysis>();
  return PA;
}

void MachineSinkingPass::printPipeline(
    raw_ostream &OS, function_ref<StringRef(StringRef)> MapClassName2PassName) {
  OS << MapClassName2PassName(name()); // ideally machine-sink
  if (EnableSinkAndFold)
    OS << "<enable-sink-fold>";
}

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

  TargetPassConfig *PassConfig = &getAnalysis<TargetPassConfig>();
  bool EnableSinkAndFold = PassConfig->getEnableSinkAndFold();

  auto *DT = &getAnalysis<MachineDominatorTreeWrapperPass>().getDomTree();
  auto *PDT =
      &getAnalysis<MachinePostDominatorTreeWrapperPass>().getPostDomTree();
  auto *CI = &getAnalysis<MachineCycleInfoWrapperPass>().getCycleInfo();
  auto *PSI = &getAnalysis<ProfileSummaryInfoWrapperPass>().getPSI();
  auto *MBFI =
      UseBlockFreqInfo
          ? &getAnalysis<MachineBlockFrequencyInfoWrapperPass>().getMBFI()
          : nullptr;
  auto *MBPI =
      &getAnalysis<MachineBranchProbabilityInfoWrapperPass>().getMBPI();
  auto *AA = &getAnalysis<AAResultsWrapperPass>().getAAResults();
  // Get analyses for split critical edge.
  auto *LISWrapper = getAnalysisIfAvailable<LiveIntervalsWrapperPass>();
  auto *LIS = LISWrapper ? &LISWrapper->getLIS() : nullptr;
  auto *SIWrapper = getAnalysisIfAvailable<SlotIndexesWrapperPass>();
  auto *SI = SIWrapper ? &SIWrapper->getSI() : nullptr;
  auto *MLIWrapper = getAnalysisIfAvailable<MachineLoopInfoWrapperPass>();
  auto *MLI = MLIWrapper ? &MLIWrapper->getLI() : nullptr;
  auto *RegClassInfo =
      &getAnalysis<MachineRegisterClassInfoWrapperPass>().getRCI();

  MachineSinking Impl(EnableSinkAndFold, DT, PDT, MLI, SI, LIS, CI, PSI, MBFI,
                      MBPI, AA, RegClassInfo);
  return Impl.run(MF);
}

bool MachineSinking::run(MachineFunction &MF) {
  LLVM_DEBUG(dbgs() << "******** Machine Sinking ********\n");

  STI = &MF.getSubtarget();
  TII = STI->getInstrInfo();
  TRI = STI->getRegisterInfo();
  MRI = &MF.getRegInfo();

  bool EverMadeChange = false;

  while (true) {
    bool MadeChange = false;

    // Process all basic blocks.
    CEBCandidates.clear();
    CEMergeCandidates.clear();
    ToSplit.clear();
    for (auto &MBB : MF)
      MadeChange |= ProcessBlock(MBB);

    // If we have anything we marked as toSplit, split it now.
    MachineDomTreeUpdater MDTU(DT, PDT,
                               MachineDomTreeUpdater::UpdateStrategy::Lazy);
    for (const auto &Pair : ToSplit) {
      auto NewSucc = Pair.first->SplitCriticalEdge(
          Pair.second, {LIS, SI, /*LV=*/nullptr, MLI}, nullptr, &MDTU);
      if (NewSucc != nullptr) {
        LLVM_DEBUG(dbgs() << " *** Splitting critical edge: "
                          << printMBBReference(*Pair.first) << " -- "
                          << printMBBReference(*NewSucc) << " -- "
                          << printMBBReference(*Pair.second) << '\n');
        if (MBFI)
          MBFI->onEdgeSplit(*Pair.first, *NewSucc, *MBPI);

        MadeChange = true;
        ++NumSplit;
        CI->splitCriticalEdge(Pair.first, Pair.second, NewSucc);
      } else
        LLVM_DEBUG(dbgs() << " *** Not legal to break critical edge\n");
    }
    // If this iteration over the code changed anything, keep iterating.
    if (!MadeChange)
      break;
    EverMadeChange = true;
  }

  if (SinkInstsIntoCycle) {
    SmallVector<CycleRef, 8> Cycles(CI->toplevel_cycles());
    SchedModel.init(STI);
    bool HasHighPressure;

    DenseMap<SinkItem, MachineInstr *> SunkInstrs;

    enum CycleSinkStage { COPY, LOW_LATENCY, AGGRESSIVE, END };
    for (unsigned Stage = CycleSinkStage::COPY; Stage != CycleSinkStage::END;
         ++Stage, SunkInstrs.clear()) {
      HasHighPressure = false;

      for (auto Cycle : Cycles) {
        MachineBasicBlock *Preheader = CI->getCyclePreheader(Cycle);
        if (!Preheader) {
          LLVM_DEBUG(dbgs() << "CycleSink: Can't find preheader\n");
          continue;
        }
        SmallVector<MachineInstr *, 8> Candidates;
        FindCycleSinkCandidates(Cycle, Preheader, Candidates);

        unsigned i = 0;

        // Walk the candidates in reverse order so that we start with the use
        // of a def-use chain, if there is any.
        // TODO: Sort the candidates using a cost-model.
        for (MachineInstr *I : llvm::reverse(Candidates)) {
          // CycleSinkStage::COPY: Sink a limited number of copies
          if (Stage == CycleSinkStage::COPY) {
            if (i++ == SinkIntoCycleLimit) {
              LLVM_DEBUG(dbgs()
                         << "CycleSink:   Limit reached of instructions to "
                            "be analyzed.");
              break;
            }

            if (!I->isCopy())
              continue;
          }

          // CycleSinkStage::LOW_LATENCY: sink unlimited number of instructions
          // which the target specifies as low-latency
          if (Stage == CycleSinkStage::LOW_LATENCY &&
              !TII->hasLowDefLatency(SchedModel, *I, 0))
            continue;

          if (!aggressivelySinkIntoCycle(Cycle, *I, SunkInstrs))
            continue;
          EverMadeChange = true;
          ++NumCycleSunk;
        }

        // Recalculate the pressure after sinking
        if (!HasHighPressure)
          HasHighPressure = registerPressureExceedsLimit(*Preheader);
      }
      if (!HasHighPressure)
        break;
    }
  }

  HasStoreCache.clear();
  StoreInstrCache.clear();

  // Now clear any kill flags for recorded registers.
  for (auto I : RegsToClearKillFlags)
    MRI->clearKillFlags(I);
  RegsToClearKillFlags.clear();

  releaseMemory();
  return EverMadeChange;
}

bool MachineSinking::ProcessBlock(MachineBasicBlock &MBB) {
  if ((!EnableSinkAndFold && MBB.succ_size() <= 1) || MBB.empty())
    return false;

  // Don't bother sinking code out of unreachable blocks. In addition to being
  // unprofitable, it can also lead to infinite looping, because in an
  // unreachable cycle there may be nowhere to stop.
  if (!DT->isReachableFromEntry(&MBB))
    return false;

  bool MadeChange = false;

  // Cache all successors, sorted by frequency info and cycle depth.
  AllSuccsCache AllSuccessors;

  // Walk the basic block bottom-up.  Remember if we saw a store.
  MachineBasicBlock::iterator I = MBB.end();
  --I;
  bool ProcessedBegin, SawStore = false;
  do {
    MachineInstr &MI = *I; // The instruction to sink.

    // Predecrement I (if it's not begin) so that it isn't invalidated by
    // sinking.
    ProcessedBegin = I == MBB.begin();
    if (!ProcessedBegin)
      --I;

    if (MI.isDebugOrPseudoInstr() || MI.isFakeUse()) {
      if (MI.isDebugValue())
        ProcessDbgInst(MI);
      continue;
    }

    if (EnableSinkAndFold && PerformSinkAndFold(MI, &MBB)) {
      MadeChange = true;
      continue;
    }

    // Can't sink anything out of a block that has less than two successors.
    if (MBB.succ_size() <= 1)
      continue;

    if (PerformTrivialForwardCoalescing(MI, &MBB)) {
      MadeChange = true;
      continue;
    }

    if (SinkInstruction(MI, SawStore, AllSuccessors)) {
      ++NumSunk;
      MadeChange = true;
    }

    // If we just processed the first instruction in the block, we're done.
  } while (!ProcessedBegin);

  SeenDbgUsers.clear();
  SeenDbgVars.clear();
  // recalculate the bb register pressure after sinking one BB.
  CachedRegisterPressure.clear();
  return MadeChange;
}

void MachineSinking::ProcessDbgInst(MachineInstr &MI) {
  // When we see DBG_VALUEs for registers, record any vreg it reads, so that
  // we know what to sink if the vreg def sinks.
  assert(MI.isDebugValue() && "Expected DBG_VALUE for processing");

  DebugVariable Var(MI.getDebugVariable(), MI.getDebugExpression(),
                    MI.getDebugLoc()->getInlinedAt());
  bool SeenBefore = SeenDbgVars.contains(Var);

  for (MachineOperand &MO : MI.debug_operands()) {
    if (MO.isReg() && MO.getReg().isVirtual())
      SeenDbgUsers[MO.getReg()].push_back(SeenDbgUser(&MI, SeenBefore));
  }

  // Record the variable for any DBG_VALUE, to avoid re-ordering any of them.
  SeenDbgVars.insert(Var);
}

bool MachineSinking::isWorthBreakingCriticalEdge(
    MachineInstr &MI, MachineBasicBlock *From, MachineBasicBlock *To,
    MachineBasicBlock *&DeferredFromBlock) {
  // FIXME: Need much better heuristics.

  // If the pass has already considered breaking this edge (during this pass
  // through the function), then let's go ahead and break it. This means
  // sinking multiple "cheap" instructions into the same block.
  if (!CEBCandidates.insert(std::make_pair(From, To)).second)
    return true;

  if (!MI.isCopy() && !TII->isAsCheapAsAMove(MI))
    return true;

  // Check and record the register and the destination block we want to sink
  // into. Note that we want to do the following before the next check on branch
  // probability. Because we want to record the initial candidate even if it's
  // on hot edge, so that other candidates that might not on hot edges can be
  // sinked as well.
  for (const auto &MO : MI.all_defs()) {
    Register Reg = MO.getReg();
    if (!Reg)
      continue;
    Register SrcReg = Reg.isVirtual() ? TRI->lookThruCopyLike(Reg, MRI) : Reg;
    auto Key = std::make_pair(SrcReg, To);
    auto Res = CEMergeCandidates.try_emplace(Key, From);
    // We wanted to sink the same register into the same block, consider it to
    // be profitable.
    if (!Res.second) {
      // Return the source block that was previously held off.
      DeferredFromBlock = Res.first->second;
      return true;
    }
  }

  if (From->isSuccessor(To) &&
      MBPI->getEdgeProbability(From, To) <=
          BranchProbability(SplitEdgeProbabilityThreshold, 100))
    return true;

  // MI is cheap, we probably don't want to break the critical edge for it.
  // However, if this would allow some definitions of its source operands
  // to be sunk then it's probably worth it.
  for (const MachineOperand &MO : MI.all_uses()) {
    Register Reg = MO.getReg();
    if (Reg == 0)
      continue;

    // We don't move live definitions of physical registers,
    // so sinking their uses won't enable any opportunities.
    if (Reg.isPhysical())
      continue;

    // If this instruction is the only user of a virtual register,
    // check if breaking the edge will enable sinking
    // both this instruction and the defining instruction.
    if (MRI->hasOneNonDBGUse(Reg)) {
      // If the definition resides in same MBB,
      // claim it's likely we can sink these together.
      // If definition resides elsewhere, we aren't
      // blocking it from being sunk so don't break the edge.
      if (MRI->getDefBlock(Reg) == MI.getParent())
        return true;
    }
  }

  // Let the target decide if it's worth breaking this
  // critical edge for a "cheap" instruction.
  return TII->shouldBreakCriticalEdgeToSink(MI);
}

bool MachineSinking::isLegalToBreakCriticalEdge(MachineInstr &MI,
                                                MachineBasicBlock *FromBB,
                                                MachineBasicBlock *ToBB,
                                                bool BreakPHIEdge) {
  // Avoid breaking back edge. From == To means backedge for single BB cycle.
  if (!SplitEdges || FromBB == ToBB || !FromBB->isSuccessor(ToBB))
    return false;

  CycleRef FromCycle = CI->getCycle(FromBB);
  CycleRef ToCycle = CI->getCycle(ToBB);

  // Check for backedges of more "complex" cycles.
  if (FromCycle == ToCycle && FromCycle &&
      (!CI->isReducible(FromCycle) || CI->getHeader(FromCycle) == ToBB))
    return false;

  // It's not always legal to break critical edges and sink the computation
  // to the edge.
  //
  // %bb.1:
  // v1024
  // Beq %bb.3
  // <fallthrough>
  // %bb.2:
  // ... no uses of v1024
  // <fallthrough>
  // %bb.3:
  // ...
  //       = v1024
  //
  // If %bb.1 -> %bb.3 edge is broken and computation of v1024 is inserted:
  //
  // %bb.1:
  // ...
  // Bne %bb.2
  // %bb.4:
  // v1024 =
  // B %bb.3
  // %bb.2:
  // ... no uses of v1024
  // <fallthrough>
  // %bb.3:
  // ...
  //       = v1024
  //
  // This is incorrect since v1024 is not computed along the %bb.1->%bb.2->%bb.3
  // flow. We need to ensure the new basic block where the computation is
  // sunk to dominates all the uses.
  // It's only legal to break critical edge and sink the computation to the
  // new block if all the predecessors of "To", except for "From", are
  // not dominated by "From". Given SSA property, this means these
  // predecessors are dominated by "To".
  //
  // There is no need to do this check if all the uses are PHI nodes. PHI
  // sources are only defined on the specific predecessor edges.
  if (!BreakPHIEdge) {
    for (MachineBasicBlock *Pred : ToBB->predecessors())
      if (Pred != FromBB && !DT->dominates(ToBB, Pred))
        return false;
  }

  return true;
}

bool MachineSinking::PostponeSplitCriticalEdge(MachineInstr &MI,
                                               MachineBasicBlock *FromBB,
                                               MachineBasicBlock *ToBB,
                                               bool BreakPHIEdge) {
  bool Status = false;
  MachineBasicBlock *DeferredFromBB = nullptr;
  if (isWorthBreakingCriticalEdge(MI, FromBB, ToBB, DeferredFromBB)) {
    // If there is a DeferredFromBB, we consider FromBB only if _both_
    // of them are legal to split.
    if ((!DeferredFromBB ||
         ToSplit.count(std::make_pair(DeferredFromBB, ToBB)) ||
         isLegalToBreakCriticalEdge(MI, DeferredFromBB, ToBB, BreakPHIEdge)) &&
        isLegalToBreakCriticalEdge(MI, FromBB, ToBB, BreakPHIEdge)) {
      ToSplit.insert(std::make_pair(FromBB, ToBB));
      if (DeferredFromBB)
        ToSplit.insert(std::make_pair(DeferredFromBB, ToBB));
      Status = true;
    }
  }

  return Status;
}

std::vector<unsigned> &
MachineSinking::getBBRegisterPressure(const MachineBasicBlock &MBB,
                                      bool UseCache) {
  // Currently to save compiling time, MBB's register pressure will not change
  // in one ProcessBlock iteration because of CachedRegisterPressure. but MBB's
  // register pressure is changed after sinking any instructions into it.
  // FIXME: need a accurate and cheap register pressure estiminate model here.

  auto RP = CachedRegisterPressure.find(&MBB);
  if (UseCache && RP != CachedRegisterPressure.end())
    return RP->second;

  RegionPressure Pressure;
  RegPressureTracker RPTracker(Pressure);

  // Initialize the register pressure tracker.
  RPTracker.init(MBB.getParent(), RegClassInfo, nullptr, &MBB, MBB.end(),
                 /*TrackLaneMasks*/ false, /*TrackUntiedDefs=*/true);

  for (MachineBasicBlock::const_iterator MII = MBB.instr_end(),
                                         MIE = MBB.instr_begin();
       MII != MIE; --MII) {
    const MachineInstr &MI = *std::prev(MII);
    if (MI.isDebugOrPseudoInstr())
      continue;
    RegisterOperands RegOpers;
    RegOpers.collect(MI, *TRI, *MRI, false, false);
    RPTracker.recedeSkipDebugValues();
    assert(&*RPTracker.getPos() == &MI && "RPTracker sync error!");
    RPTracker.recede(RegOpers);
  }

  RPTracker.closeRegion();

  if (RP != CachedRegisterPressure.end()) {
    CachedRegisterPressure[&MBB] = RPTracker.getPressure().MaxSetPressure;
    return CachedRegisterPressure[&MBB];
  }

  auto It = CachedRegisterPressure.insert(
      std::make_pair(&MBB, RPTracker.getPressure().MaxSetPressure));
  return It.first->second;
}

bool MachineSinking::registerPressureSetExceedsLimit(
    unsigned NRegs, const TargetRegisterClass *RC,
    const MachineBasicBlock &MBB) {
  unsigned Weight = NRegs * TRI->getRegClassWeight(RC).RegWeight;
  const int *PS = TRI->getRegClassPressureSets(RC);
  std::vector<unsigned> BBRegisterPressure = getBBRegisterPressure(MBB);
  for (; *PS != -1; PS++)
    if (Weight + BBRegisterPressure[*PS] >=
        RegClassInfo->getRegPressureSetLimit(*PS))
      return true;
  return false;
}

// Recalculate RP and check if any pressure set exceeds the set limit.
bool MachineSinking::registerPressureExceedsLimit(
    const MachineBasicBlock &MBB) {
  std::vector<unsigned> BBRegisterPressure = getBBRegisterPressure(MBB, false);

  for (unsigned PS = 0; PS < BBRegisterPressure.size(); ++PS) {
    if (BBRegisterPressure[PS] >= RegClassInfo->getRegPressureSetLimit(PS)) {
      return true;
    }
  }

  return false;
}

/// isProfitableToSinkTo - Return true if it is profitable to sink MI.
bool MachineSinking::isProfitableToSinkTo(Register Reg, MachineInstr &MI,
                                          MachineBasicBlock *MBB,
                                          MachineBasicBlock *SuccToSinkTo,
                                          AllSuccsCache &AllSuccessors) {
  assert(SuccToSinkTo && "Invalid SinkTo Candidate BB");

  if (MBB == SuccToSinkTo)
    return false;

  // It is profitable if SuccToSinkTo does not post dominate current block.
  if (!PDT->dominates(SuccToSinkTo, MBB))
    return true;

  // It is profitable to sink an instruction from a deeper cycle to a shallower
  // cycle, even if the latter post-dominates the former (PR21115).
  if (CI->getCycleDepth(MBB) > CI->getCycleDepth(SuccToSinkTo))
    return true;

  // Check if only use in post dominated block is PHI instruction.
  bool NonPHIUse = false;
  for (MachineInstr &UseInst : MRI->use_nodbg_instructions(Reg)) {
    MachineBasicBlock *UseBlock = UseInst.getParent();
    if (UseBlock == SuccToSinkTo && !UseInst.isPHI())
      NonPHIUse = true;
  }
  if (!NonPHIUse)
    return true;

  // If SuccToSinkTo post dominates then also it may be profitable if MI
  // can further profitably sinked into another block in next round.
  bool BreakPHIEdge = false;
  // FIXME - If finding successor is compile time expensive then cache results.
  if (MachineBasicBlock *MBB2 =
          FindSuccToSinkTo(MI, SuccToSinkTo, BreakPHIEdge, AllSuccessors))
    return isProfitableToSinkTo(Reg, MI, SuccToSinkTo, MBB2, AllSuccessors);

  CycleRef MCycle = CI->getCycle(MBB);

  // If the instruction is not inside a cycle, it is not profitable to sink MI
  // to a post dominate block SuccToSinkTo.
  if (!MCycle)
    return false;

  // If this instruction is inside a Cycle and sinking this instruction can make
  // more registers live range shorten, it is still prifitable.
  for (const MachineOperand &MO : MI.operands()) {
    // Ignore non-register operands.
    if (!MO.isReg())
      continue;
    Register Reg = MO.getReg();
    if (Reg == 0)
      continue;

    if (Reg.isPhysical()) {
      // Don't handle non-constant and non-ignorable physical register uses.
      if (MO.isUse() && !MRI->isConstantPhysReg(Reg) &&
          !TII->isIgnorableUse(MI, MI.getOperandNo(&MO)))
        return false;
      continue;
    }

    // Users for the defs are all dominated by SuccToSinkTo.
    if (MO.isDef()) {
      // This def register's live range is shortened after sinking.
      bool LocalUse = false;
      if (!AllUsesDominatedByBlock(Reg, SuccToSinkTo, MBB, BreakPHIEdge,
                                   LocalUse))
        return false;
    } else {
      MachineInstr *DefMI = MRI->getVRegDef(Reg);
      if (!DefMI)
        continue;
      CycleRef Cycle = CI->getCycle(DefMI->getParent());
      // DefMI is defined outside of cycle. There should be no live range
      // impact for this operand. Defination outside of cycle means:
      // 1: defination is outside of cycle.
      // 2: defination is in this cycle, but it is a PHI in the cycle header.
      if (Cycle != MCycle ||
          (DefMI->isPHI() && Cycle && CI->isReducible(Cycle) &&
           CI->getHeader(Cycle) == DefMI->getParent()))
        continue;
      // The DefMI is defined inside the cycle.
      // If sinking this operand makes some register pressure set exceed limit,
      // it is not profitable.
      if (registerPressureSetExceedsLimit(1, MRI->getRegClass(Reg),
                                          *SuccToSinkTo)) {
        LLVM_DEBUG(dbgs() << "register pressure exceed limit, not profitable.");
        return false;
      }
    }
  }

  // If MI is in cycle and all its operands are alive across the whole cycle or
  // if no operand sinking make register pressure set exceed limit, it is
  // profitable to sink MI.
  return true;
}

/// Get the sorted sequence of successors for this MachineBasicBlock, possibly
/// computing it if it was not already cached.
SmallVector<MachineBasicBlock *, 4> &
MachineSinking::GetAllSortedSuccessors(MachineInstr &MI, MachineBasicBlock *MBB,
                                       AllSuccsCache &AllSuccessors) const {
  // Do we have the sorted successors in cache ?
  auto Succs = AllSuccessors.find(MBB);
  if (Succs != AllSuccessors.end())
    return Succs->second;

  SmallVector<MachineBasicBlock *, 4> AllSuccs(MBB->successors());

  // Handle cases where sinking can happen but where the sink point isn't a
  // successor. For example:
  //
  //   x = computation
  //   if () {} else {}
  //   use x
  //
  for (MachineDomTreeNode *DTChild : DT->getNode(MBB)->children()) {
    // DomTree children of MBB that have MBB as immediate dominator are added.
    if (DTChild->getIDom()->getBlock() == MI.getParent() &&
        // Skip MBBs already added to the AllSuccs vector above.
        !MBB->isSuccessor(DTChild->getBlock()))
      AllSuccs.push_back(DTChild->getBlock());
  }

  // Sort Successors according to their cycle depth or block frequency info.
  llvm::stable_sort(
      AllSuccs, [&](const MachineBasicBlock *L, const MachineBasicBlock *R) {
        uint64_t LHSFreq = MBFI ? MBFI->getBlockFreq(L).getFrequency() : 0;
        uint64_t RHSFreq = MBFI ? MBFI->getBlockFreq(R).getFrequency() : 0;
        if (llvm::shouldOptimizeForSize(MBB, PSI, MBFI) ||
            (!LHSFreq && !RHSFreq))
          return CI->getCycleDepth(L) < CI->getCycleDepth(R);
        return LHSFreq < RHSFreq;
      });

  auto it = AllSuccessors.insert(std::make_pair(MBB, AllSuccs));

  return it.first->second;
}

/// FindSuccToSinkTo - Find a successor to sink this instruction to.
MachineBasicBlock *
MachineSinking::FindSuccToSinkTo(MachineInstr &MI, MachineBasicBlock *MBB,
                                 bool &BreakPHIEdge,
                                 AllSuccsCache &AllSuccessors) {
  assert(MBB && "Invalid MachineBasicBlock!");

  // loop over all the operands of the specified instruction.  If there is
  // anything we can't handle, bail out.

  // SuccToSinkTo - This is the successor to sink this instruction to, once we
  // decide.
  MachineBasicBlock *SuccToSinkTo = nullptr;
  for (const MachineOperand &MO : MI.operands()) {
    if (!MO.isReg())
      continue; // Ignore non-register operands.

    Register Reg = MO.getReg();
    if (Reg == 0)
      continue;

    if (Reg.isPhysical()) {
      if (MO.isUse()) {
        // If the physreg has no defs anywhere, it's just an ambient register
        // and we can freely move its uses. Alternatively, if it's allocatable,
        // it could get allocated to something with a def during allocation.
        if (!MRI->isConstantPhysReg(Reg) &&
            !TII->isIgnorableUse(MI, MI.getOperandNo(&MO)))
          return nullptr;
      } else if (!MO.isDead()) {
        // A def that isn't dead. We can't move it.
        return nullptr;
      }
    } else {
      // Virtual register uses are always safe to sink.
      if (MO.isUse())
        continue;

      // If it's not safe to move defs of the register class, then abort.
      if (!TII->isSafeToMoveRegClassDefs(MRI->getRegClass(Reg)))
        return nullptr;

      // Virtual register defs can only be sunk if all their uses are in blocks
      // dominated by one of the successors.
      if (SuccToSinkTo) {
        // If a previous operand picked a block to sink to, then this operand
        // must be sinkable to the same block.
        bool LocalUse = false;
        if (!AllUsesDominatedByBlock(Reg, SuccToSinkTo, MBB, BreakPHIEdge,
                                     LocalUse))
          return nullptr;

        continue;
      }

      // Otherwise, we should look at all the successors and decide which one
      // we should sink to. If we have reliable block frequency information
      // (frequency != 0) available, give successors with smaller frequencies
      // higher priority, otherwise prioritize smaller cycle depths.
      for (MachineBasicBlock *SuccBlock :
           GetAllSortedSuccessors(MI, MBB, AllSuccessors)) {
        bool LocalUse = false;
        if (AllUsesDominatedByBlock(Reg, SuccBlock, MBB, BreakPHIEdge,
                                    LocalUse)) {
          SuccToSinkTo = SuccBlock;
          break;
        }
        if (LocalUse)
          // Def is used locally, it's never safe to move this def.
          return nullptr;
      }

      // If we couldn't find a block to sink to, ignore this instruction.
      if (!SuccToSinkTo)
        return nullptr;
      if (!isProfitableToSinkTo(Reg, MI, MBB, SuccToSinkTo, AllSuccessors))
        return nullptr;
    }
  }

  // It is not possible to sink an instruction into its own block.  This can
  // happen with cycles.
  if (MBB == SuccToSinkTo)
    return nullptr;

  // It's not safe to sink instructions to EH landing pad. Control flow into
  // landing pad is implicitly defined.
  if (SuccToSinkTo && SuccToSinkTo->isEHPad())
    return nullptr;

  // It ought to be okay to sink instructions into an INLINEASM_BR target, but
  // only if we make sure that MI occurs _before_ an INLINEASM_BR instruction in
  // the source block (which this code does not yet do). So for now, forbid
  // doing so.
  if (SuccToSinkTo && SuccToSinkTo->isInlineAsmBrIndirectTarget())
    return nullptr;

  if (SuccToSinkTo && !TII->isSafeToSink(MI, SuccToSinkTo, CI))
    return nullptr;

  return SuccToSinkTo;
}

/// Return true if MI is likely to be usable as a memory operation by the
/// implicit null check optimization.
///
/// This is a "best effort" heuristic, and should not be relied upon for
/// correctness.  This returning true does not guarantee that the implicit null
/// check optimization is legal over MI, and this returning false does not
/// guarantee MI cannot possibly be used to do a null check.
static bool SinkingPreventsImplicitNullCheck(MachineInstr &MI,
                                             const TargetInstrInfo *TII,
                                             const TargetRegisterInfo *TRI) {
  using MachineBranchPredicate = TargetInstrInfo::MachineBranchPredicate;

  auto *MBB = MI.getParent();
  if (MBB->pred_size() != 1)
    return false;

  auto *PredMBB = *MBB->pred_begin();
  auto *PredBB = PredMBB->getBasicBlock();

  // Frontends that don't use implicit null checks have no reason to emit
  // branches with make.implicit metadata, and this function should always
  // return false for them.
  if (!PredBB ||
      !PredBB->getTerminator()->getMetadata(LLVMContext::MD_make_implicit))
    return false;

  const MachineOperand *BaseOp;
  int64_t Offset;
  bool OffsetIsScalable;
  if (!TII->getMemOperandWithOffset(MI, BaseOp, Offset, OffsetIsScalable, TRI))
    return false;

  if (!BaseOp->isReg())
    return false;

  if (!(MI.mayLoad() && !MI.isPredicable()))
    return false;

  MachineBranchPredicate MBP;
  if (TII->analyzeBranchPredicate(*PredMBB, MBP, false))
    return false;

  return MBP.LHS.isReg() && MBP.RHS.isImm() && MBP.RHS.getImm() == 0 &&
         (MBP.Predicate == MachineBranchPredicate::PRED_NE ||
          MBP.Predicate == MachineBranchPredicate::PRED_EQ) &&
         MBP.LHS.getReg() == BaseOp->getReg();
}

/// If the sunk instruction is a copy, try to forward the copy instead of
/// leaving an 'undef' DBG_VALUE in the original location. Don't do this if
/// there's any subregister weirdness involved. Returns true if copy
/// propagation occurred.
static bool attemptDebugCopyProp(MachineInstr &SinkInst, MachineInstr &DbgMI,
                                 Register Reg) {
  const MachineRegisterInfo &MRI = SinkInst.getMF()->getRegInfo();
  const TargetInstrInfo &TII = *SinkInst.getMF()->getSubtarget().getInstrInfo();

  // Copy DBG_VALUE operand and set the original to undef. We then check to
  // see whether this is something that can be copy-forwarded. If it isn't,
  // continue around the loop.

  const MachineOperand *SrcMO = nullptr, *DstMO = nullptr;
  auto CopyOperands = TII.isCopyInstr(SinkInst);
  if (!CopyOperands)
    return false;
  SrcMO = CopyOperands->Source;
  DstMO = CopyOperands->Destination;

  // Check validity of forwarding this copy.
  bool PostRA = MRI.getNumVirtRegs() == 0;

  // Trying to forward between physical and virtual registers is too hard.
  if (Reg.isVirtual() != SrcMO->getReg().isVirtual())
    return false;

  // Only try virtual register copy-forwarding before regalloc, and physical
  // register copy-forwarding after regalloc.
  bool arePhysRegs = !Reg.isVirtual();
  if (arePhysRegs != PostRA)
    return false;

  // Pre-regalloc, only forward if all subregisters agree (or there are no
  // subregs at all). More analysis might recover some forwardable copies.
  if (!PostRA)
    for (auto &DbgMO : DbgMI.getDebugOperandsForReg(Reg))
      if (DbgMO.getSubReg() != SrcMO->getSubReg() ||
          DbgMO.getSubReg() != DstMO->getSubReg())
        return false;

  // Post-regalloc, we may be sinking a DBG_VALUE of a sub or super-register
  // of this copy. Only forward the copy if the DBG_VALUE operand exactly
  // matches the copy destination.
  if (PostRA && Reg != DstMO->getReg())
    return false;

  for (auto &DbgMO : DbgMI.getDebugOperandsForReg(Reg)) {
    DbgMO.setReg(SrcMO->getReg());
    DbgMO.setSubReg(SrcMO->getSubReg());
  }
  return true;
}

using MIRegs = std::pair<MachineInstr *, SmallVector<Register, 2>>;
/// Sink an instruction and its associated debug instructions.
static void performSink(MachineInstr &MI, MachineBasicBlock &SuccToSinkTo,
                        MachineBasicBlock::iterator InsertPos,
                        ArrayRef<MIRegs> DbgValuesToSink) {
  // If we cannot find a location to use (merge with), then we erase the debug
  // location to prevent debug-info driven tools from potentially reporting
  // wrong location information.
  if (SuccToSinkTo.empty())
    MI.setDebugLoc(DebugLoc::getDropped());
  else
    MI.setDebugLoc(DebugLoc::getMergedLocation(
        MI.getDebugLoc(), SuccToSinkTo.findDebugLoc(InsertPos)));

  // Move the instruction.
  MachineBasicBlock *ParentBlock = MI.getParent();
  SuccToSinkTo.splice(InsertPos, ParentBlock, MI,
                      ++MachineBasicBlock::iterator(MI));

  // Sink a copy of debug users to the insert position. Mark the original
  // DBG_VALUE location as 'undef', indicating that any earlier variable
  // location should be terminated as we've optimised away the value at this
  // point.
  for (const auto &DbgValueToSink : DbgValuesToSink) {
    MachineInstr *DbgMI = DbgValueToSink.first;
    MachineInstr *NewDbgMI = DbgMI->getMF()->CloneMachineInstr(DbgMI);
    SuccToSinkTo.insert(InsertPos, NewDbgMI);

    bool PropagatedAllSunkOps = true;
    for (Register Reg : DbgValueToSink.second) {
      if (DbgMI->hasDebugOperandForReg(Reg)) {
        if (!attemptDebugCopyProp(MI, *DbgMI, Reg)) {
          PropagatedAllSunkOps = false;
          break;
        }
      }
    }
    if (!PropagatedAllSunkOps)
      DbgMI->setDebugValueUndef();
  }
}

/// hasStoreBetween - check if there is store betweeen straight line blocks From
/// and To.
bool MachineSinking::hasStoreBetween(MachineBasicBlock *From,
                                     MachineBasicBlock *To, MachineInstr &MI) {
  // Make sure From and To are in straight line which means From dominates To
  // and To post dominates From.
  if (!DT->dominates(From, To) || !PDT->dominates(To, From))
    return true;

  auto BlockPair = std::make_pair(From, To);

  // Does these two blocks pair be queried before and have a definite cached
  // result?
  if (auto It = HasStoreCache.find(BlockPair); It != HasStoreCache.end())
    return It->second;

  if (auto It = StoreInstrCache.find(BlockPair); It != StoreInstrCache.end())
    return llvm::any_of(It->second, [&](MachineInstr *I) {
      return I->mayAlias(AA, MI, false);
    });

  bool SawStore = false;
  bool HasAliasedStore = false;
  DenseSet<MachineBasicBlock *> HandledBlocks;
  DenseSet<MachineBasicBlock *> HandledDomBlocks;
  // Go through all reachable blocks from From.
  for (MachineBasicBlock *BB : depth_first(From)) {
    // We insert the instruction at the start of block To, so no need to worry
    // about stores inside To.
    // Store in block From should be already considered when just enter function
    // SinkInstruction.
    if (BB == To || BB == From)
      continue;

    // We already handle this BB in previous iteration.
    if (HandledBlocks.count(BB))
      continue;

    HandledBlocks.insert(BB);
    // To post dominates BB, it must be a path from block From.
    if (PDT->dominates(To, BB)) {
      if (!HandledDomBlocks.count(BB))
        HandledDomBlocks.insert(BB);

      // If this BB is too big or the block number in straight line between From
      // and To is too big, stop searching to save compiling time.
      if (BB->sizeWithoutDebugLargerThan(SinkLoadInstsPerBlockThreshold) ||
          HandledDomBlocks.size() > SinkLoadBlocksThreshold) {
        for (auto *DomBB : HandledDomBlocks) {
          if (DomBB != BB && DT->dominates(DomBB, BB))
            HasStoreCache[std::make_pair(DomBB, To)] = true;
          else if (DomBB != BB && DT->dominates(BB, DomBB))
            HasStoreCache[std::make_pair(From, DomBB)] = true;
        }
        HasStoreCache[BlockPair] = true;
        return true;
      }

      for (MachineInstr &I : *BB) {
        // Treat as alias conservatively for a call or an ordered memory
        // operation.
        if (I.isCall() || I.hasOrderedMemoryRef()) {
          for (auto *DomBB : HandledDomBlocks) {
            if (DomBB != BB && DT->dominates(DomBB, BB))
              HasStoreCache[std::make_pair(DomBB, To)] = true;
            else if (DomBB != BB && DT->dominates(BB, DomBB))
              HasStoreCache[std::make_pair(From, DomBB)] = true;
          }
          HasStoreCache[BlockPair] = true;
          return true;
        }

        if (I.mayStore()) {
          SawStore = true;
          // We still have chance to sink MI if all stores between are not
          // aliased to MI.
          // Cache all store instructions, so that we don't need to go through
          // all From reachable blocks for next load instruction.
          if (I.mayAlias(AA, MI, false))
            HasAliasedStore = true;
          StoreInstrCache[BlockPair].push_back(&I);
        }
      }
    }
  }
  // If there is no store at all, cache the result.
  if (!SawStore)
    HasStoreCache[BlockPair] = false;
  return HasAliasedStore;
}

/// Aggressively sink instructions into cycles. This will aggressively try to
/// sink all instructions in the top-most preheaders in an attempt to reduce RP.
/// In particular, it will sink into multiple successor blocks without limits
/// based on the amount of sinking, or the type of ops being sunk (so long as
/// they are safe to sink).
bool MachineSinking::aggressivelySinkIntoCycle(
    CycleRef Cycle, MachineInstr &I,
    DenseMap<SinkItem, MachineInstr *> &SunkInstrs) {
  // TODO: support instructions with multiple defs
  if (I.getNumDefs() > 1)
    return false;

  LLVM_DEBUG(dbgs() << "AggressiveCycleSink: Finding sink block for: " << I);
  assert(CI->getCyclePreheader(Cycle) && "Cycle sink needs a preheader block");
  SmallVector<std::pair<RegSubRegPair, MachineInstr *>> Uses;

  MachineOperand &DefMO = I.getOperand(0);
  for (MachineInstr &MI : MRI->use_instructions(DefMO.getReg())) {
    Uses.push_back({{DefMO.getReg(), DefMO.getSubReg()}, &MI});
  }

  for (std::pair<RegSubRegPair, MachineInstr *> Entry : Uses) {
    MachineInstr *MI = Entry.second;
    LLVM_DEBUG(dbgs() << "AggressiveCycleSink:   Analysing use: " << MI);
    if (MI->isPHI()) {
      LLVM_DEBUG(
          dbgs() << "AggressiveCycleSink:   Not attempting to sink for PHI.\n");
      continue;
    }
    // We cannot sink before the prologue
    if (MI->isPosition() || TII->isBasicBlockPrologue(*MI)) {
      LLVM_DEBUG(dbgs() << "AggressiveCycleSink:   Use is BasicBlock prologue, "
                           "can't sink.\n");
      continue;
    }
    if (!CI->contains(Cycle, MI->getParent())) {
      LLVM_DEBUG(
          dbgs() << "AggressiveCycleSink:   Use not in cycle, can't sink.\n");
      continue;
    }

    MachineBasicBlock *SinkBlock = MI->getParent();
    MachineInstr *NewMI = nullptr;
    SinkItem MapEntry(&I, SinkBlock);

    auto SI = SunkInstrs.find(MapEntry);

    // Check for the case in which we have already sunk a copy of this
    // instruction into the user block.
    if (SI != SunkInstrs.end()) {
      LLVM_DEBUG(dbgs() << "AggressiveCycleSink:   Already sunk to block: "
                        << printMBBReference(*SinkBlock) << "\n");
      NewMI = SI->second;
    }

    // Create a copy of the instruction in the use block.
    if (!NewMI) {
      LLVM_DEBUG(dbgs() << "AggressiveCycleSink: Sinking instruction to block: "
                        << printMBBReference(*SinkBlock) << "\n");

      NewMI = I.getMF()->CloneMachineInstr(&I);
      if (DefMO.getReg().isVirtual()) {
        const TargetRegisterClass *TRC = MRI->getRegClass(DefMO.getReg());
        Register DestReg = MRI->createVirtualRegister(TRC);
        NewMI->substituteRegister(DefMO.getReg(), DestReg, DefMO.getSubReg(),
                                  *TRI);
      }
      SinkBlock->insert(SinkBlock->SkipPHIsAndLabels(SinkBlock->begin()),
                        NewMI);
      SunkInstrs.insert({MapEntry, NewMI});
    }

    // Conservatively clear any kill flags on uses of sunk instruction
    for (MachineOperand &MO : NewMI->all_uses()) {
      assert(MO.isReg() && MO.isUse());
      RegsToClearKillFlags.insert(MO.getReg());
    }

    // The instruction is moved from its basic block, so do not retain the
    // debug information.
    assert(!NewMI->isDebugInstr() && "Should not sink debug inst");
    NewMI->setDebugLoc(DebugLoc());

    // Replace the use with the newly created virtual register.
    RegSubRegPair &UseReg = Entry.first;
    MI->substituteRegister(UseReg.Reg, NewMI->getOperand(0).getReg(),
                           UseReg.SubReg, *TRI);
  }
  // If we have replaced all uses, then delete the dead instruction
  if (I.isDead(*MRI))
    I.eraseFromParent();
  return true;
}

/// SinkInstruction - Determine whether it is safe to sink the specified machine
/// instruction out of its current block into a successor.
bool MachineSinking::SinkInstruction(MachineInstr &MI, bool &SawStore,
                                     AllSuccsCache &AllSuccessors) {
  // Don't sink instructions that the target prefers not to sink.
  if (!TII->shouldSink(MI))
    return false;

  // Check if it's safe to move the instruction.
  if (!MI.isSafeToMove(SawStore))
    return false;

  // Convergent operations may not be made control-dependent on additional
  // values.
  if (MI.isConvergent())
    return false;

  // Don't break implicit null checks.  This is a performance heuristic, and not
  // required for correctness.
  if (SinkingPreventsImplicitNullCheck(MI, TII, TRI))
    return false;

  // FIXME: This should include support for sinking instructions within the
  // block they are currently in to shorten the live ranges.  We often get
  // instructions sunk into the top of a large block, but it would be better to
  // also sink them down before their first use in the block.  This xform has to
  // be careful not to *increase* register pressure though, e.g. sinking
  // "x = y + z" down if it kills y and z would increase the live ranges of y
  // and z and only shrink the live range of x.

  bool BreakPHIEdge = false;
  MachineBasicBlock *ParentBlock = MI.getParent();
  MachineBasicBlock *SuccToSinkTo =
      FindSuccToSinkTo(MI, ParentBlock, BreakPHIEdge, AllSuccessors);

  // If there are no outputs, it must have side-effects.
  if (!SuccToSinkTo)
    return false;

  // If the instruction to move defines a dead physical register which is live
  // when leaving the basic block, don't move it because it could turn into a
  // "zombie" define of that preg. E.g., EFLAGS.
  for (const MachineOperand &MO : MI.all_defs()) {
    Register Reg = MO.getReg();
    if (Reg == 0 || !Reg.isPhysical())
      continue;
    if (SuccToSinkTo->isLiveIn(Reg))
      return false;
  }

  LLVM_DEBUG(dbgs() << "Sink instr " << MI << "\tinto block " << *SuccToSinkTo);

  // If the block has multiple predecessors, this is a critical edge.
  // Decide if we can sink along it or need to break the edge.
  if (SuccToSinkTo->pred_size() > 1) {
    // We cannot sink a load across a critical edge - there may be stores in
    // other code paths.
    bool TryBreak = false;
    bool Store =
        MI.mayLoad() ? hasStoreBetween(ParentBlock, SuccToSinkTo, MI) : true;
    if (!MI.isSafeToMove(Store)) {
      LLVM_DEBUG(dbgs() << " *** NOTE: Won't sink load along critical edge.\n");
      TryBreak = true;
    }

    // We don't want to sink across a critical edge if we don't dominate the
    // successor. We could be introducing calculations to new code paths.
    if (!TryBreak && !DT->dominates(ParentBlock, SuccToSinkTo)) {
      LLVM_DEBUG(dbgs() << " *** NOTE: Critical edge found\n");
      TryBreak = true;
    }

    // Don't sink instructions into a cycle.
    if (!TryBreak && CI->getCycle(SuccToSinkTo) &&
        (!CI->isReducible(CI->getCycle(SuccToSinkTo)) ||
         CI->getHeader(CI->getCycle(SuccToSinkTo)) == SuccToSinkTo)) {
      LLVM_DEBUG(dbgs() << " *** NOTE: cycle header found\n");
      TryBreak = true;
    }

    // Otherwise we are OK with sinking along a critical edge.
    if (!TryBreak)
      LLVM_DEBUG(dbgs() << "Sinking along critical edge.\n");
    else {
      // Mark this edge as to be split.
      // If the edge can actually be split, the next iteration of the main loop
      // will sink MI in the newly created block.
      bool Status = PostponeSplitCriticalEdge(MI, ParentBlock, SuccToSinkTo,
                                              BreakPHIEdge);
      if (!Status)
        LLVM_DEBUG(dbgs() << " *** PUNTING: Not legal or profitable to "
                             "break critical edge\n");
      // The instruction will not be sunk this time.
      return false;
    }
  }

  if (BreakPHIEdge) {
    // BreakPHIEdge is true if all the uses are in the successor MBB being
    // sunken into and they are all PHI nodes. In this case, machine-sink must
    // break the critical edge first.
    bool Status =
        PostponeSplitCriticalEdge(MI, ParentBlock, SuccToSinkTo, BreakPHIEdge);
    if (!Status)
      LLVM_DEBUG(dbgs() << " *** PUNTING: Not legal or profitable to "
                           "break critical edge\n");
    // The instruction will not be sunk this time.
    return false;
  }

  // Determine where to insert into. Skip phi nodes.
  MachineBasicBlock::iterator InsertPos =
      SuccToSinkTo->SkipPHIsAndLabels(SuccToSinkTo->begin());
  if (blockPrologueInterferes(SuccToSinkTo, InsertPos, MI, TRI, TII, MRI)) {
    LLVM_DEBUG(dbgs() << " *** Not sinking: prologue interference\n");
    return false;
  }

  // Collect debug users of any vreg that this inst defines.
  SmallVector<MIRegs, 4> DbgUsersToSink;
  for (auto &MO : MI.all_defs()) {
    if (!MO.getReg().isVirtual())
      continue;
    auto It = SeenDbgUsers.find(MO.getReg());
    if (It == SeenDbgUsers.end())
      continue;

    // Sink any users that don't pass any other DBG_VALUEs for this variable.
    auto &Users = It->second;
    for (auto &User : Users) {
      MachineInstr *DbgMI = User.getPointer();
      if (User.getInt()) {
        // This DBG_VALUE would re-order assignments. If we can't copy-propagate
        // it, it can't be recovered. Set it undef.
        if (!attemptDebugCopyProp(MI, *DbgMI, MO.getReg()))
          DbgMI->setDebugValueUndef();
      } else {
        DbgUsersToSink.push_back(
            {DbgMI, SmallVector<Register, 2>(1, MO.getReg())});
      }
    }
  }

  // After sinking, some debug users may not be dominated any more. If possible,
  // copy-propagate their operands. As it's expensive, don't do this if there's
  // no debuginfo in the program.
  if (MI.getMF()->getFunction().getSubprogram() && MI.isCopy())
    SalvageUnsunkDebugUsersOfCopy(MI, SuccToSinkTo);

  performSink(MI, *SuccToSinkTo, InsertPos, DbgUsersToSink);

  // Conservatively, clear any kill flags, since it's possible that they are no
  // longer correct.
  // Note that we have to clear the kill flags for any register this instruction
  // uses as we may sink over another instruction which currently kills the
  // used registers.
  for (MachineOperand &MO : MI.all_uses())
    RegsToClearKillFlags.insert(MO.getReg()); // Remember to clear kill flags.

  return true;
}

void MachineSinking::SalvageUnsunkDebugUsersOfCopy(
    MachineInstr &MI, MachineBasicBlock *TargetBlock) {
  assert(MI.isCopy());
  assert(MI.getOperand(1).isReg());

  // Enumerate all users of vreg operands that are def'd. Skip those that will
  // be sunk. For the rest, if they are not dominated by the block we will sink
  // MI into, propagate the copy source to them.
  SmallVector<MachineInstr *, 4> DbgDefUsers;
  SmallVector<Register, 4> DbgUseRegs;
  const MachineRegisterInfo &MRI = MI.getMF()->getRegInfo();
  for (auto &MO : MI.all_defs()) {
    if (!MO.getReg().isVirtual())
      continue;
    DbgUseRegs.push_back(MO.getReg());
    for (auto &User : MRI.use_instructions(MO.getReg())) {
      if (!User.isDebugValue() || DT->dominates(TargetBlock, User.getParent()))
        continue;

      // If is in same block, will either sink or be use-before-def.
      if (User.getParent() == MI.getParent())
        continue;

      assert(User.hasDebugOperandForReg(MO.getReg()) &&
             "DBG_VALUE user of vreg, but has no operand for it?");
      DbgDefUsers.push_back(&User);
    }
  }

  // Point the users of this copy that are no longer dominated, at the source
  // of the copy.
  for (auto *User : DbgDefUsers) {
    for (auto &Reg : DbgUseRegs) {
      for (auto &DbgOp : User->getDebugOperandsForReg(Reg)) {
        DbgOp.setReg(MI.getOperand(1).getReg());
        DbgOp.setSubReg(MI.getOperand(1).getSubReg());
      }
    }
  }
}

//===----------------------------------------------------------------------===//
// This pass is not intended to be a replacement or a complete alternative
// for the pre-ra machine sink pass. It is only designed to sink COPY
// instructions which should be handled after RA.
//
// This pass sinks COPY instructions into a successor block, if the COPY is not
// used in the current block and the COPY is live-in to a single successor
// (i.e., doesn't require the COPY to be duplicated).  This avoids executing the
// copy on paths where their results aren't needed.  This also exposes
// additional opportunites for dead copy elimination and shrink wrapping.
//
// These copies were either not handled by or are inserted after the MachineSink
// pass. As an example of the former case, the MachineSink pass cannot sink
// COPY instructions with allocatable source registers; for AArch64 these type
// of copy instructions are frequently used to move function parameters (PhyReg)
// into virtual registers in the entry block.
//
// For the machine IR below, this pass will sink %w19 in the entry into its
// successor (%bb.1) because %w19 is only live-in in %bb.1.
// %bb.0:
//   %wzr = SUBSWri %w1, 1
//   %w19 = COPY %w0
//   Bcc 11, %bb.2
// %bb.1:
//   Live Ins: %w19
//   BL @fun
//   %w0 = ADDWrr %w0, %w19
//   RET %w0
// %bb.2:
//   %w0 = COPY %wzr
//   RET %w0
// As we sink %w19 (CSR in AArch64) into %bb.1, the shrink-wrapping pass will be
// able to see %bb.0 as a candidate.
//===----------------------------------------------------------------------===//
namespace {

class PostRAMachineSinkingImpl {
  /// Track which register units have been modified and used.
  LiveRegUnits ModifiedRegUnits, UsedRegUnits;

  /// Track DBG_VALUEs of (unmodified) register units. Each DBG_VALUE has an
  /// entry in this map for each unit it touches. The DBG_VALUE's entry
  /// consists of a pointer to the instruction itself, and a vector of registers
  /// referred to by the instruction that overlap the key register unit.
  DenseMap<MCRegUnit, SmallVector<MIRegs, 2>> SeenDbgInstrs;

  /// Sink Copy instructions unused in the same block close to their uses in
  /// successors.
  bool tryToSinkCopy(MachineBasicBlock &BB, MachineFunction &MF,
                     const TargetRegisterInfo *TRI, const TargetInstrInfo *TII);

public:
  bool run(MachineFunction &MF);
};

class PostRAMachineSinkingLegacy : public MachineFunctionPass {
public:
  bool runOnMachineFunction(MachineFunction &MF) override;

  static char ID;
  PostRAMachineSinkingLegacy() : MachineFunctionPass(ID) {}
  StringRef getPassName() const override { return "PostRA Machine Sink"; }

  void getAnalysisUsage(AnalysisUsage &AU) const override {
    AU.setPreservesCFG();
    MachineFunctionPass::getAnalysisUsage(AU);
  }

  MachineFunctionProperties getRequiredProperties() const override {
    return MachineFunctionProperties().setNoVRegs();
  }
};

} // namespace

char PostRAMachineSinkingLegacy::ID = 0;
char &llvm::PostRAMachineSinkingID = PostRAMachineSinkingLegacy::ID;

INITIALIZE_PASS(PostRAMachineSinkingLegacy, "postra-machine-sink",
                "PostRA Machine Sink", false, false)

static bool aliasWithRegsInLiveIn(MachineBasicBlock &MBB, Register Reg,
                                  const TargetRegisterInfo *TRI) {
  LiveRegUnits LiveInRegUnits(*TRI);
  LiveInRegUnits.addLiveIns(MBB);
  return !LiveInRegUnits.available(Reg);
}

static MachineBasicBlock *
getSingleLiveInSuccBB(MachineBasicBlock &CurBB,
                      const SmallPtrSetImpl<MachineBasicBlock *> &SinkableBBs,
                      Register Reg, const TargetRegisterInfo *TRI) {
  // Try to find a single sinkable successor in which Reg is live-in.
  MachineBasicBlock *BB = nullptr;
  for (auto *SI : SinkableBBs) {
    if (aliasWithRegsInLiveIn(*SI, Reg, TRI)) {
      // If BB is set here, Reg is live-in to at least two sinkable successors,
      // so quit.
      if (BB)
        return nullptr;
      BB = SI;
    }
  }
  // Reg is not live-in to any sinkable successors.
  if (!BB)
    return nullptr;

  // Check if any register aliased with Reg is live-in in other successors.
  for (auto *SI : CurBB.successors()) {
    if (!SinkableBBs.count(SI) && aliasWithRegsInLiveIn(*SI, Reg, TRI))
      return nullptr;
  }
  return BB;
}

static MachineBasicBlock *
getSingleLiveInSuccBB(MachineBasicBlock &CurBB,
                      const SmallPtrSetImpl<MachineBasicBlock *> &SinkableBBs,
                      ArrayRef<Register> DefedRegsInCopy,
                      const TargetRegisterInfo *TRI) {
  MachineBasicBlock *SingleBB = nullptr;
  for (auto DefReg : DefedRegsInCopy) {
    MachineBasicBlock *BB =
        getSingleLiveInSuccBB(CurBB, SinkableBBs, DefReg, TRI);
    if (!BB || (SingleBB && SingleBB != BB))
      return nullptr;
    SingleBB = BB;
  }
  return SingleBB;
}

static void clearKillFlags(MachineInstr *MI, MachineBasicBlock &CurBB,
                           const SmallVectorImpl<unsigned> &UsedOpsInCopy,
                           const LiveRegUnits &UsedRegUnits,
                           const TargetRegisterInfo *TRI) {
  for (auto U : UsedOpsInCopy) {
    MachineOperand &MO = MI->getOperand(U);
    Register SrcReg = MO.getReg();
    if (!UsedRegUnits.available(SrcReg)) {
      MachineBasicBlock::iterator NI = std::next(MI->getIterator());
      for (MachineInstr &UI : make_range(NI, CurBB.end())) {
        if (UI.killsRegister(SrcReg, TRI)) {
          UI.clearRegisterKills(SrcReg, TRI);
          MO.setIsKill(true);
          break;
        }
      }
    }
  }
}

static void updateLiveIn(MachineInstr *MI, MachineBasicBlock *SuccBB,
                         const SmallVectorImpl<unsigned> &UsedOpsInCopy,
                         const SmallVectorImpl<Register> &DefedRegsInCopy) {
  for (Register DefReg : DefedRegsInCopy)
    SuccBB->removeLiveInOverlappedWith(DefReg);

  for (auto U : UsedOpsInCopy)
    SuccBB->addLiveIn(MI->getOperand(U).getReg());
  SuccBB->sortUniqueLiveIns();
}

static bool hasRegisterDependency(MachineInstr *MI,
                                  SmallVectorImpl<unsigned> &UsedOpsInCopy,
                                  SmallVectorImpl<Register> &DefedRegsInCopy,
                                  LiveRegUnits &ModifiedRegUnits,
                                  LiveRegUnits &UsedRegUnits) {
  bool HasRegDependency = false;
  for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) {
    MachineOperand &MO = MI->getOperand(i);
    if (!MO.isReg())
      continue;
    Register Reg = MO.getReg();
    if (!Reg)
      continue;
    if (MO.isDef()) {
      if (!ModifiedRegUnits.available(Reg) || !UsedRegUnits.available(Reg)) {
        HasRegDependency = true;
        break;
      }
      DefedRegsInCopy.push_back(Reg);

      // FIXME: instead of isUse(), readsReg() would be a better fix here,
      // For example, we can ignore modifications in reg with undef. However,
      // it's not perfectly clear if skipping the internal read is safe in all
      // other targets.
    } else if (MO.isUse()) {
      if (!ModifiedRegUnits.available(Reg)) {
        HasRegDependency = true;
        break;
      }
      UsedOpsInCopy.push_back(i);
    }
  }
  return HasRegDependency;
}

bool PostRAMachineSinkingImpl::tryToSinkCopy(MachineBasicBlock &CurBB,
                                             MachineFunction &MF,
                                             const TargetRegisterInfo *TRI,
                                             const TargetInstrInfo *TII) {
  SmallPtrSet<MachineBasicBlock *, 2> SinkableBBs;
  // FIXME: For now, we sink only to a successor which has a single predecessor
  // so that we can directly sink COPY instructions to the successor without
  // adding any new block or branch instruction.
  for (MachineBasicBlock *SI : CurBB.successors())
    if (!SI->livein_empty() && SI->pred_size() == 1)
      SinkableBBs.insert(SI);

  if (SinkableBBs.empty())
    return false;

  bool Changed = false;

  // Track which registers have been modified and used between the end of the
  // block and the current instruction.
  ModifiedRegUnits.clear();
  UsedRegUnits.clear();
  SeenDbgInstrs.clear();

  for (MachineInstr &MI : llvm::make_early_inc_range(llvm::reverse(CurBB))) {
    // Track the operand index for use in Copy.
    SmallVector<unsigned, 2> UsedOpsInCopy;
    // Track the register number defed in Copy.
    SmallVector<Register, 2> DefedRegsInCopy;

    // We must sink this DBG_VALUE if its operand is sunk. To avoid searching
    // for DBG_VALUEs later, record them when they're encountered.
    if (MI.isDebugValue() && !MI.isDebugRef()) {
      SmallDenseMap<MCRegUnit, SmallVector<Register, 2>, 4> MIUnits;
      bool IsValid = true;
      for (MachineOperand &MO : MI.debug_operands()) {
        if (MO.isReg() && MO.getReg().isPhysical()) {
          // Bail if we can already tell the sink would be rejected, rather
          // than needlessly accumulating lots of DBG_VALUEs.
          if (hasRegisterDependency(&MI, UsedOpsInCopy, DefedRegsInCopy,
                                    ModifiedRegUnits, UsedRegUnits)) {
            IsValid = false;
            break;
          }

          // Record debug use of each reg unit.
          for (MCRegUnit Unit : TRI->regunits(MO.getReg()))
            MIUnits[Unit].push_back(MO.getReg());
        }
      }
      if (IsValid) {
        for (auto &RegOps : MIUnits)
          SeenDbgInstrs[RegOps.first].emplace_back(&MI,
                                                   std::move(RegOps.second));
      }
      continue;
    }

    // Don't postRASink instructions that the target prefers not to sink.
    if (!TII->shouldPostRASink(MI))
      continue;

    if (MI.isDebugOrPseudoInstr())
      continue;

    // Do not move any instruction across function call.
    if (MI.isCall())
      return false;

    if (!MI.isCopy() || !MI.getOperand(0).isRenamable()) {
      LiveRegUnits::accumulateUsedDefed(MI, ModifiedRegUnits, UsedRegUnits,
                                        TRI);
      continue;
    }

    // Don't sink the COPY if it would violate a register dependency.
    if (hasRegisterDependency(&MI, UsedOpsInCopy, DefedRegsInCopy,
                              ModifiedRegUnits, UsedRegUnits)) {
      LiveRegUnits::accumulateUsedDefed(MI, ModifiedRegUnits, UsedRegUnits,
                                        TRI);
      continue;
    }
    assert((!UsedOpsInCopy.empty() && !DefedRegsInCopy.empty()) &&
           "Unexpect SrcReg or DefReg");
    MachineBasicBlock *SuccBB =
        getSingleLiveInSuccBB(CurBB, SinkableBBs, DefedRegsInCopy, TRI);
    // Don't sink if we cannot find a single sinkable successor in which Reg
    // is live-in.
    if (!SuccBB) {
      LiveRegUnits::accumulateUsedDefed(MI, ModifiedRegUnits, UsedRegUnits,
                                        TRI);
      continue;
    }
    assert((SuccBB->pred_size() == 1 && *SuccBB->pred_begin() == &CurBB) &&
           "Unexpected predecessor");

    // Collect DBG_VALUEs that must sink with this copy. We've previously
    // recorded which reg units that DBG_VALUEs read, if this instruction
    // writes any of those units then the corresponding DBG_VALUEs must sink.
    MapVector<MachineInstr *, MIRegs::second_type> DbgValsToSinkMap;
    for (auto &MO : MI.all_defs()) {
      for (MCRegUnit Unit : TRI->regunits(MO.getReg())) {
        for (const auto &MIRegs : SeenDbgInstrs.lookup(Unit)) {
          auto &Regs = DbgValsToSinkMap[MIRegs.first];
          llvm::append_range(Regs, MIRegs.second);
        }
      }
    }
    auto DbgValsToSink = DbgValsToSinkMap.takeVector();

    LLVM_DEBUG(dbgs() << "Sink instr " << MI << "\tinto block " << *SuccBB);

    MachineBasicBlock::iterator InsertPos =
        SuccBB->SkipPHIsAndLabels(SuccBB->begin());
    if (blockPrologueInterferes(SuccBB, InsertPos, MI, TRI, TII, nullptr)) {
      LiveRegUnits::accumulateUsedDefed(MI, ModifiedRegUnits, UsedRegUnits,
                                        TRI);
      LLVM_DEBUG(dbgs() << " *** Not sinking: prologue interference\n");
      continue;
    }

    // Clear the kill flag if SrcReg is killed between MI and the end of the
    // block.
    clearKillFlags(&MI, CurBB, UsedOpsInCopy, UsedRegUnits, TRI);
    performSink(MI, *SuccBB, InsertPos, DbgValsToSink);
    updateLiveIn(&MI, SuccBB, UsedOpsInCopy, DefedRegsInCopy);

    Changed = true;
    ++NumPostRACopySink;
  }
  return Changed;
}

bool PostRAMachineSinkingImpl::run(MachineFunction &MF) {
  bool Changed = false;
  const TargetRegisterInfo *TRI = MF.getSubtarget().getRegisterInfo();
  const TargetInstrInfo *TII = MF.getSubtarget().getInstrInfo();

  ModifiedRegUnits.init(*TRI);
  UsedRegUnits.init(*TRI);
  for (auto &BB : MF)
    Changed |= tryToSinkCopy(BB, MF, TRI, TII);

  return Changed;
}

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

  return PostRAMachineSinkingImpl().run(MF);
}

PreservedAnalyses
PostRAMachineSinkingPass::run(MachineFunction &MF,
                              MachineFunctionAnalysisManager &MFAM) {
  MFPropsModifier _(*this, MF);

  if (!PostRAMachineSinkingImpl().run(MF))
    return PreservedAnalyses::all();

  PreservedAnalyses PA = getMachineFunctionPassPreservedAnalyses();
  PA.preserveSet<CFGAnalyses>();
  return PA;
}
