//===- PeepholeOptimizer.cpp - Peephole Optimizations ---------------------===//
//
// 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
//
//===----------------------------------------------------------------------===//
//
// Perform peephole optimizations on the machine code:
//
// - Optimize Extensions
//
//     Optimization of sign / zero extension instructions. It may be extended to
//     handle other instructions with similar properties.
//
//     On some targets, some instructions, e.g. X86 sign / zero extension, may
//     leave the source value in the lower part of the result. This optimization
//     will replace some uses of the pre-extension value with uses of the
//     sub-register of the results.
//
// - Optimize Comparisons
//
//     Optimization of comparison instructions. For instance, in this code:
//
//       sub r1, 1
//       cmp r1, 0
//       bz  L1
//
//     If the "sub" instruction all ready sets (or could be modified to set) the
//     same flag that the "cmp" instruction sets and that "bz" uses, then we can
//     eliminate the "cmp" instruction.
//
//     Another instance, in this code:
//
//       sub r1, r3 | sub r1, imm
//       cmp r3, r1 or cmp r1, r3 | cmp r1, imm
//       bge L1
//
//     If the branch instruction can use flag from "sub", then we can replace
//     "sub" with "subs" and eliminate the "cmp" instruction.
//
// - Optimize Loads:
//
//     Loads that can be folded into a later instruction. A load is foldable
//     if it loads to virtual registers and the virtual register defined has
//     a single use.
//
// - Optimize Copies and Bitcast (more generally, target specific copies):
//
//     Rewrite copies and bitcasts to avoid cross register bank copies
//     when possible.
//     E.g., Consider the following example, where capital and lower
//     letters denote different register file:
//     b = copy A <-- cross-bank copy
//     C = copy b <-- cross-bank copy
//   =>
//     b = copy A <-- cross-bank copy
//     C = copy A <-- same-bank copy
//
//     E.g., for bitcast:
//     b = bitcast A <-- cross-bank copy
//     C = bitcast b <-- cross-bank copy
//   =>
//     b = bitcast A <-- cross-bank copy
//     C = copy A    <-- same-bank copy
//===----------------------------------------------------------------------===//

#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/ADT/SmallSet.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/Statistic.h"
#include "llvm/CodeGen/MachineBasicBlock.h"
#include "llvm/CodeGen/MachineDominators.h"
#include "llvm/CodeGen/MachineFunction.h"
#include "llvm/CodeGen/MachineFunctionPass.h"
#include "llvm/CodeGen/MachineInstr.h"
#include "llvm/CodeGen/MachineInstrBuilder.h"
#include "llvm/CodeGen/MachineLoopInfo.h"
#include "llvm/CodeGen/MachineOperand.h"
#include "llvm/CodeGen/MachineRegisterInfo.h"
#include "llvm/CodeGen/TargetInstrInfo.h"
#include "llvm/CodeGen/TargetOpcodes.h"
#include "llvm/CodeGen/TargetRegisterInfo.h"
#include "llvm/CodeGen/TargetSubtargetInfo.h"
#include "llvm/InitializePasses.h"
#include "llvm/MC/LaneBitmask.h"
#include "llvm/MC/MCInstrDesc.h"
#include "llvm/Pass.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/raw_ostream.h"
#include <cassert>
#include <cstdint>
#include <memory>
#include <utility>

using namespace llvm;
using RegSubRegPair = TargetInstrInfo::RegSubRegPair;
using RegSubRegPairAndIdx = TargetInstrInfo::RegSubRegPairAndIdx;

#define DEBUG_TYPE "peephole-opt"

// Optimize Extensions
static cl::opt<bool>
Aggressive("aggressive-ext-opt", cl::Hidden,
           cl::desc("Aggressive extension optimization"));

static cl::opt<bool>
DisablePeephole("disable-peephole", cl::Hidden, cl::init(false),
                cl::desc("Disable the peephole optimizer"));

/// Specifiy whether or not the value tracking looks through
/// complex instructions. When this is true, the value tracker
/// bails on everything that is not a copy or a bitcast.
static cl::opt<bool>
DisableAdvCopyOpt("disable-adv-copy-opt", cl::Hidden, cl::init(false),
                  cl::desc("Disable advanced copy optimization"));

static cl::opt<bool> DisableNAPhysCopyOpt(
    "disable-non-allocatable-phys-copy-opt", cl::Hidden, cl::init(false),
    cl::desc("Disable non-allocatable physical register copy optimization"));

// Limit the number of PHI instructions to process
// in PeepholeOptimizer::getNextSource.
static cl::opt<unsigned> RewritePHILimit(
    "rewrite-phi-limit", cl::Hidden, cl::init(10),
    cl::desc("Limit the length of PHI chains to lookup"));

// Limit the length of recurrence chain when evaluating the benefit of
// commuting operands.
static cl::opt<unsigned> MaxRecurrenceChain(
    "recurrence-chain-limit", cl::Hidden, cl::init(3),
    cl::desc("Maximum length of recurrence chain when evaluating the benefit "
             "of commuting operands"));


STATISTIC(NumReuse, "Number of extension results reused");
STATISTIC(NumCmps, "Number of compares eliminated");
STATISTIC(NumImmFold, "Number of move immediate folded");
STATISTIC(NumLoadFold, "Number of loads folded");
STATISTIC(NumSelects, "Number of selects optimized");
STATISTIC(NumUncoalescableCopies, "Number of uncoalescable copies optimized");
STATISTIC(NumRewrittenCopies, "Number of copies rewritten");
STATISTIC(NumNAPhysCopies, "Number of non-allocatable physical copies removed");

namespace {

  class ValueTrackerResult;
  class RecurrenceInstr;

  class PeepholeOptimizer : public MachineFunctionPass,
                            private MachineFunction::Delegate {
    const TargetInstrInfo *TII = nullptr;
    const TargetRegisterInfo *TRI = nullptr;
    MachineRegisterInfo *MRI = nullptr;
    MachineDominatorTree *DT = nullptr; // Machine dominator tree
    MachineLoopInfo *MLI = nullptr;

  public:
    static char ID; // Pass identification

    PeepholeOptimizer() : MachineFunctionPass(ID) {
      initializePeepholeOptimizerPass(*PassRegistry::getPassRegistry());
    }

    bool runOnMachineFunction(MachineFunction &MF) override;

    void getAnalysisUsage(AnalysisUsage &AU) const override {
      AU.setPreservesCFG();
      MachineFunctionPass::getAnalysisUsage(AU);
      AU.addRequired<MachineLoopInfoWrapperPass>();
      AU.addPreserved<MachineLoopInfoWrapperPass>();
      if (Aggressive) {
        AU.addRequired<MachineDominatorTreeWrapperPass>();
        AU.addPreserved<MachineDominatorTreeWrapperPass>();
      }
    }

    MachineFunctionProperties getRequiredProperties() const override {
      return MachineFunctionProperties()
        .set(MachineFunctionProperties::Property::IsSSA);
    }

    /// Track Def -> Use info used for rewriting copies.
    using RewriteMapTy = SmallDenseMap<RegSubRegPair, ValueTrackerResult>;

    /// Sequence of instructions that formulate recurrence cycle.
    using RecurrenceCycle = SmallVector<RecurrenceInstr, 4>;

  private:
    bool optimizeCmpInstr(MachineInstr &MI);
    bool optimizeExtInstr(MachineInstr &MI, MachineBasicBlock &MBB,
                          SmallPtrSetImpl<MachineInstr*> &LocalMIs);
    bool optimizeSelect(MachineInstr &MI,
                        SmallPtrSetImpl<MachineInstr *> &LocalMIs);
    bool optimizeCondBranch(MachineInstr &MI);
    bool optimizeCoalescableCopy(MachineInstr &MI);
    bool optimizeUncoalescableCopy(MachineInstr &MI,
                                   SmallPtrSetImpl<MachineInstr *> &LocalMIs);
    bool optimizeRecurrence(MachineInstr &PHI);
    bool findNextSource(RegSubRegPair RegSubReg, RewriteMapTy &RewriteMap);
    bool isMoveImmediate(MachineInstr &MI, SmallSet<Register, 4> &ImmDefRegs,
                         DenseMap<Register, MachineInstr *> &ImmDefMIs);
    bool foldImmediate(MachineInstr &MI, SmallSet<Register, 4> &ImmDefRegs,
                       DenseMap<Register, MachineInstr *> &ImmDefMIs,
                       bool &Deleted);

    /// Finds recurrence cycles, but only ones that formulated around
    /// a def operand and a use operand that are tied. If there is a use
    /// operand commutable with the tied use operand, find recurrence cycle
    /// along that operand as well.
    bool findTargetRecurrence(Register Reg,
                              const SmallSet<Register, 2> &TargetReg,
                              RecurrenceCycle &RC);

    /// If copy instruction \p MI is a virtual register copy or a copy of a
    /// constant physical register to a virtual register, track it in the
    /// set CopySrcMIs. If this virtual register was previously seen as a
    /// copy, replace the uses of this copy with the previously seen copy's
    /// destination register.
    bool foldRedundantCopy(MachineInstr &MI);

    /// Is the register \p Reg a non-allocatable physical register?
    bool isNAPhysCopy(Register Reg);

    /// If copy instruction \p MI is a non-allocatable virtual<->physical
    /// register copy, track it in the \p NAPhysToVirtMIs map. If this
    /// non-allocatable physical register was previously copied to a virtual
    /// registered and hasn't been clobbered, the virt->phys copy can be
    /// deleted.
    bool foldRedundantNAPhysCopy(
        MachineInstr &MI, DenseMap<Register, MachineInstr *> &NAPhysToVirtMIs);

    bool isLoadFoldable(MachineInstr &MI,
                        SmallSet<Register, 16> &FoldAsLoadDefCandidates);

    /// Check whether \p MI is understood by the register coalescer
    /// but may require some rewriting.
    bool isCoalescableCopy(const MachineInstr &MI) {
      // SubregToRegs are not interesting, because they are already register
      // coalescer friendly.
      return MI.isCopy() || (!DisableAdvCopyOpt &&
                             (MI.isRegSequence() || MI.isInsertSubreg() ||
                              MI.isExtractSubreg()));
    }

    /// Check whether \p MI is a copy like instruction that is
    /// not recognized by the register coalescer.
    bool isUncoalescableCopy(const MachineInstr &MI) {
      return MI.isBitcast() ||
             (!DisableAdvCopyOpt &&
              (MI.isRegSequenceLike() || MI.isInsertSubregLike() ||
               MI.isExtractSubregLike()));
    }

    MachineInstr &rewriteSource(MachineInstr &CopyLike,
                                RegSubRegPair Def, RewriteMapTy &RewriteMap);

    // Set of copies to virtual registers keyed by source register.  Never
    // holds any physreg which requires def tracking.
    DenseMap<RegSubRegPair, MachineInstr *> CopySrcMIs;

    // MachineFunction::Delegate implementation. Used to maintain CopySrcMIs.
    void MF_HandleInsertion(MachineInstr &MI) override {
      return;
    }

    bool getCopySrc(MachineInstr &MI, RegSubRegPair &SrcPair) {
      if (!MI.isCopy())
        return false;

      Register SrcReg = MI.getOperand(1).getReg();
      unsigned SrcSubReg = MI.getOperand(1).getSubReg();
      if (!SrcReg.isVirtual() && !MRI->isConstantPhysReg(SrcReg))
        return false;

      SrcPair = RegSubRegPair(SrcReg, SrcSubReg);
      return true;
    }

    // If a COPY instruction is to be deleted or changed, we should also remove
    // it from CopySrcMIs.
    void deleteChangedCopy(MachineInstr &MI) {
      RegSubRegPair SrcPair;
      if (!getCopySrc(MI, SrcPair))
        return;

      auto It = CopySrcMIs.find(SrcPair);
      if (It != CopySrcMIs.end() && It->second == &MI)
        CopySrcMIs.erase(It);
    }

    void MF_HandleRemoval(MachineInstr &MI) override {
      deleteChangedCopy(MI);
    }

    void MF_HandleChangeDesc(MachineInstr &MI, const MCInstrDesc &TID) override
    {
      deleteChangedCopy(MI);
    }
  };

  /// Helper class to hold instructions that are inside recurrence cycles.
  /// The recurrence cycle is formulated around 1) a def operand and its
  /// tied use operand, or 2) a def operand and a use operand that is commutable
  /// with another use operand which is tied to the def operand. In the latter
  /// case, index of the tied use operand and the commutable use operand are
  /// maintained with CommutePair.
  class RecurrenceInstr {
  public:
    using IndexPair = std::pair<unsigned, unsigned>;

    RecurrenceInstr(MachineInstr *MI) : MI(MI) {}
    RecurrenceInstr(MachineInstr *MI, unsigned Idx1, unsigned Idx2)
      : MI(MI), CommutePair(std::make_pair(Idx1, Idx2)) {}

    MachineInstr *getMI() const { return MI; }
    std::optional<IndexPair> getCommutePair() const { return CommutePair; }

  private:
    MachineInstr *MI;
    std::optional<IndexPair> CommutePair;
  };

  /// Helper class to hold a reply for ValueTracker queries.
  /// Contains the returned sources for a given search and the instructions
  /// where the sources were tracked from.
  class ValueTrackerResult {
  private:
    /// Track all sources found by one ValueTracker query.
    SmallVector<RegSubRegPair, 2> RegSrcs;

    /// Instruction using the sources in 'RegSrcs'.
    const MachineInstr *Inst = nullptr;

  public:
    ValueTrackerResult() = default;

    ValueTrackerResult(Register Reg, unsigned SubReg) {
      addSource(Reg, SubReg);
    }

    bool isValid() const { return getNumSources() > 0; }

    void setInst(const MachineInstr *I) { Inst = I; }
    const MachineInstr *getInst() const { return Inst; }

    void clear() {
      RegSrcs.clear();
      Inst = nullptr;
    }

    void addSource(Register SrcReg, unsigned SrcSubReg) {
      RegSrcs.push_back(RegSubRegPair(SrcReg, SrcSubReg));
    }

    void setSource(int Idx, Register SrcReg, unsigned SrcSubReg) {
      assert(Idx < getNumSources() && "Reg pair source out of index");
      RegSrcs[Idx] = RegSubRegPair(SrcReg, SrcSubReg);
    }

    int getNumSources() const { return RegSrcs.size(); }

    RegSubRegPair getSrc(int Idx) const {
      return RegSrcs[Idx];
    }

    Register getSrcReg(int Idx) const {
      assert(Idx < getNumSources() && "Reg source out of index");
      return RegSrcs[Idx].Reg;
    }

    unsigned getSrcSubReg(int Idx) const {
      assert(Idx < getNumSources() && "SubReg source out of index");
      return RegSrcs[Idx].SubReg;
    }

    bool operator==(const ValueTrackerResult &Other) const {
      if (Other.getInst() != getInst())
        return false;

      if (Other.getNumSources() != getNumSources())
        return false;

      for (int i = 0, e = Other.getNumSources(); i != e; ++i)
        if (Other.getSrcReg(i) != getSrcReg(i) ||
            Other.getSrcSubReg(i) != getSrcSubReg(i))
          return false;
      return true;
    }
  };

  /// Helper class to track the possible sources of a value defined by
  /// a (chain of) copy related instructions.
  /// Given a definition (instruction and definition index), this class
  /// follows the use-def chain to find successive suitable sources.
  /// The given source can be used to rewrite the definition into
  /// def = COPY src.
  ///
  /// For instance, let us consider the following snippet:
  /// v0 =
  /// v2 = INSERT_SUBREG v1, v0, sub0
  /// def = COPY v2.sub0
  ///
  /// Using a ValueTracker for def = COPY v2.sub0 will give the following
  /// suitable sources:
  /// v2.sub0 and v0.
  /// Then, def can be rewritten into def = COPY v0.
  class ValueTracker {
  private:
    /// The current point into the use-def chain.
    const MachineInstr *Def = nullptr;

    /// The index of the definition in Def.
    unsigned DefIdx = 0;

    /// The sub register index of the definition.
    unsigned DefSubReg;

    /// The register where the value can be found.
    Register Reg;

    /// MachineRegisterInfo used to perform tracking.
    const MachineRegisterInfo &MRI;

    /// Optional TargetInstrInfo used to perform some complex tracking.
    const TargetInstrInfo *TII;

    /// Dispatcher to the right underlying implementation of getNextSource.
    ValueTrackerResult getNextSourceImpl();

    /// Specialized version of getNextSource for Copy instructions.
    ValueTrackerResult getNextSourceFromCopy();

    /// Specialized version of getNextSource for Bitcast instructions.
    ValueTrackerResult getNextSourceFromBitcast();

    /// Specialized version of getNextSource for RegSequence instructions.
    ValueTrackerResult getNextSourceFromRegSequence();

    /// Specialized version of getNextSource for InsertSubreg instructions.
    ValueTrackerResult getNextSourceFromInsertSubreg();

    /// Specialized version of getNextSource for ExtractSubreg instructions.
    ValueTrackerResult getNextSourceFromExtractSubreg();

    /// Specialized version of getNextSource for SubregToReg instructions.
    ValueTrackerResult getNextSourceFromSubregToReg();

    /// Specialized version of getNextSource for PHI instructions.
    ValueTrackerResult getNextSourceFromPHI();

  public:
    /// Create a ValueTracker instance for the value defined by \p Reg.
    /// \p DefSubReg represents the sub register index the value tracker will
    /// track. It does not need to match the sub register index used in the
    /// definition of \p Reg.
    /// If \p Reg is a physical register, a value tracker constructed with
    /// this constructor will not find any alternative source.
    /// Indeed, when \p Reg is a physical register that constructor does not
    /// know which definition of \p Reg it should track.
    /// Use the next constructor to track a physical register.
    ValueTracker(Register Reg, unsigned DefSubReg,
                 const MachineRegisterInfo &MRI,
                 const TargetInstrInfo *TII = nullptr)
        : DefSubReg(DefSubReg), Reg(Reg), MRI(MRI), TII(TII) {
      if (!Reg.isPhysical()) {
        Def = MRI.getVRegDef(Reg);
        DefIdx = MRI.def_begin(Reg).getOperandNo();
      }
    }

    /// Following the use-def chain, get the next available source
    /// for the tracked value.
    /// \return A ValueTrackerResult containing a set of registers
    /// and sub registers with tracked values. A ValueTrackerResult with
    /// an empty set of registers means no source was found.
    ValueTrackerResult getNextSource();
  };

} // end anonymous namespace

char PeepholeOptimizer::ID = 0;

char &llvm::PeepholeOptimizerID = PeepholeOptimizer::ID;

INITIALIZE_PASS_BEGIN(PeepholeOptimizer, DEBUG_TYPE,
                      "Peephole Optimizations", false, false)
INITIALIZE_PASS_DEPENDENCY(MachineDominatorTreeWrapperPass)
INITIALIZE_PASS_DEPENDENCY(MachineLoopInfoWrapperPass)
INITIALIZE_PASS_END(PeepholeOptimizer, DEBUG_TYPE,
                    "Peephole Optimizations", false, false)

/// If instruction is a copy-like instruction, i.e. it reads a single register
/// and writes a single register and it does not modify the source, and if the
/// source value is preserved as a sub-register of the result, then replace all
/// reachable uses of the source with the subreg of the result.
///
/// Do not generate an EXTRACT that is used only in a debug use, as this changes
/// the code. Since this code does not currently share EXTRACTs, just ignore all
/// debug uses.
bool PeepholeOptimizer::
optimizeExtInstr(MachineInstr &MI, MachineBasicBlock &MBB,
                 SmallPtrSetImpl<MachineInstr*> &LocalMIs) {
  Register SrcReg, DstReg;
  unsigned SubIdx;
  if (!TII->isCoalescableExtInstr(MI, SrcReg, DstReg, SubIdx))
    return false;

  if (DstReg.isPhysical() || SrcReg.isPhysical())
    return false;

  if (MRI->hasOneNonDBGUse(SrcReg))
    // No other uses.
    return false;

  // Ensure DstReg can get a register class that actually supports
  // sub-registers. Don't change the class until we commit.
  const TargetRegisterClass *DstRC = MRI->getRegClass(DstReg);
  DstRC = TRI->getSubClassWithSubReg(DstRC, SubIdx);
  if (!DstRC)
    return false;

  // The ext instr may be operating on a sub-register of SrcReg as well.
  // PPC::EXTSW is a 32 -> 64-bit sign extension, but it reads a 64-bit
  // register.
  // If UseSrcSubIdx is Set, SubIdx also applies to SrcReg, and only uses of
  // SrcReg:SubIdx should be replaced.
  bool UseSrcSubIdx =
      TRI->getSubClassWithSubReg(MRI->getRegClass(SrcReg), SubIdx) != nullptr;

  // The source has other uses. See if we can replace the other uses with use of
  // the result of the extension.
  SmallPtrSet<MachineBasicBlock*, 4> ReachedBBs;
  for (MachineInstr &UI : MRI->use_nodbg_instructions(DstReg))
    ReachedBBs.insert(UI.getParent());

  // Uses that are in the same BB of uses of the result of the instruction.
  SmallVector<MachineOperand*, 8> Uses;

  // Uses that the result of the instruction can reach.
  SmallVector<MachineOperand*, 8> ExtendedUses;

  bool ExtendLife = true;
  for (MachineOperand &UseMO : MRI->use_nodbg_operands(SrcReg)) {
    MachineInstr *UseMI = UseMO.getParent();
    if (UseMI == &MI)
      continue;

    if (UseMI->isPHI()) {
      ExtendLife = false;
      continue;
    }

    // Only accept uses of SrcReg:SubIdx.
    if (UseSrcSubIdx && UseMO.getSubReg() != SubIdx)
      continue;

    // It's an error to translate this:
    //
    //    %reg1025 = <sext> %reg1024
    //     ...
    //    %reg1026 = SUBREG_TO_REG 0, %reg1024, 4
    //
    // into this:
    //
    //    %reg1025 = <sext> %reg1024
    //     ...
    //    %reg1027 = COPY %reg1025:4
    //    %reg1026 = SUBREG_TO_REG 0, %reg1027, 4
    //
    // The problem here is that SUBREG_TO_REG is there to assert that an
    // implicit zext occurs. It doesn't insert a zext instruction. If we allow
    // the COPY here, it will give us the value after the <sext>, not the
    // original value of %reg1024 before <sext>.
    if (UseMI->getOpcode() == TargetOpcode::SUBREG_TO_REG)
      continue;

    MachineBasicBlock *UseMBB = UseMI->getParent();
    if (UseMBB == &MBB) {
      // Local uses that come after the extension.
      if (!LocalMIs.count(UseMI))
        Uses.push_back(&UseMO);
    } else if (ReachedBBs.count(UseMBB)) {
      // Non-local uses where the result of the extension is used. Always
      // replace these unless it's a PHI.
      Uses.push_back(&UseMO);
    } else if (Aggressive && DT->dominates(&MBB, UseMBB)) {
      // We may want to extend the live range of the extension result in order
      // to replace these uses.
      ExtendedUses.push_back(&UseMO);
    } else {
      // Both will be live out of the def MBB anyway. Don't extend live range of
      // the extension result.
      ExtendLife = false;
      break;
    }
  }

  if (ExtendLife && !ExtendedUses.empty())
    // Extend the liveness of the extension result.
    Uses.append(ExtendedUses.begin(), ExtendedUses.end());

  // Now replace all uses.
  bool Changed = false;
  if (!Uses.empty()) {
    SmallPtrSet<MachineBasicBlock*, 4> PHIBBs;

    // Look for PHI uses of the extended result, we don't want to extend the
    // liveness of a PHI input. It breaks all kinds of assumptions down
    // stream. A PHI use is expected to be the kill of its source values.
    for (MachineInstr &UI : MRI->use_nodbg_instructions(DstReg))
      if (UI.isPHI())
        PHIBBs.insert(UI.getParent());

    const TargetRegisterClass *RC = MRI->getRegClass(SrcReg);
    for (MachineOperand *UseMO : Uses) {
      MachineInstr *UseMI = UseMO->getParent();
      MachineBasicBlock *UseMBB = UseMI->getParent();
      if (PHIBBs.count(UseMBB))
        continue;

      // About to add uses of DstReg, clear DstReg's kill flags.
      if (!Changed) {
        MRI->clearKillFlags(DstReg);
        MRI->constrainRegClass(DstReg, DstRC);
      }

      // SubReg defs are illegal in machine SSA phase,
      // we should not generate SubReg defs.
      //
      // For example, for the instructions:
      //
      // %1:g8rc_and_g8rc_nox0 = EXTSW %0:g8rc
      // %3:gprc_and_gprc_nor0 = COPY %0.sub_32:g8rc
      //
      // We should generate:
      //
      // %1:g8rc_and_g8rc_nox0 = EXTSW %0:g8rc
      // %6:gprc_and_gprc_nor0 = COPY %1.sub_32:g8rc_and_g8rc_nox0
      // %3:gprc_and_gprc_nor0 = COPY %6:gprc_and_gprc_nor0
      //
      if (UseSrcSubIdx)
        RC = MRI->getRegClass(UseMI->getOperand(0).getReg());

      Register NewVR = MRI->createVirtualRegister(RC);
      BuildMI(*UseMBB, UseMI, UseMI->getDebugLoc(),
              TII->get(TargetOpcode::COPY), NewVR)
        .addReg(DstReg, 0, SubIdx);
      if (UseSrcSubIdx)
        UseMO->setSubReg(0);

      UseMO->setReg(NewVR);
      ++NumReuse;
      Changed = true;
    }
  }

  return Changed;
}

/// If the instruction is a compare and the previous instruction it's comparing
/// against already sets (or could be modified to set) the same flag as the
/// compare, then we can remove the comparison and use the flag from the
/// previous instruction.
bool PeepholeOptimizer::optimizeCmpInstr(MachineInstr &MI) {
  // If this instruction is a comparison against zero and isn't comparing a
  // physical register, we can try to optimize it.
  Register SrcReg, SrcReg2;
  int64_t CmpMask, CmpValue;
  if (!TII->analyzeCompare(MI, SrcReg, SrcReg2, CmpMask, CmpValue) ||
      SrcReg.isPhysical() || SrcReg2.isPhysical())
    return false;

  // Attempt to optimize the comparison instruction.
  LLVM_DEBUG(dbgs() << "Attempting to optimize compare: " << MI);
  if (TII->optimizeCompareInstr(MI, SrcReg, SrcReg2, CmpMask, CmpValue, MRI)) {
    LLVM_DEBUG(dbgs() << "  -> Successfully optimized compare!\n");
    ++NumCmps;
    return true;
  }

  return false;
}

/// Optimize a select instruction.
bool PeepholeOptimizer::optimizeSelect(MachineInstr &MI,
                            SmallPtrSetImpl<MachineInstr *> &LocalMIs) {
  unsigned TrueOp = 0;
  unsigned FalseOp = 0;
  bool Optimizable = false;
  SmallVector<MachineOperand, 4> Cond;
  if (TII->analyzeSelect(MI, Cond, TrueOp, FalseOp, Optimizable))
    return false;
  if (!Optimizable)
    return false;
  if (!TII->optimizeSelect(MI, LocalMIs))
    return false;
  LLVM_DEBUG(dbgs() << "Deleting select: " << MI);
  MI.eraseFromParent();
  ++NumSelects;
  return true;
}

/// Check if a simpler conditional branch can be generated.
bool PeepholeOptimizer::optimizeCondBranch(MachineInstr &MI) {
  return TII->optimizeCondBranch(MI);
}

/// Try to find the next source that share the same register file
/// for the value defined by \p Reg and \p SubReg.
/// When true is returned, the \p RewriteMap can be used by the client to
/// retrieve all Def -> Use along the way up to the next source. Any found
/// Use that is not itself a key for another entry, is the next source to
/// use. During the search for the next source, multiple sources can be found
/// given multiple incoming sources of a PHI instruction. In this case, we
/// look in each PHI source for the next source; all found next sources must
/// share the same register file as \p Reg and \p SubReg. The client should
/// then be capable to rewrite all intermediate PHIs to get the next source.
/// \return False if no alternative sources are available. True otherwise.
bool PeepholeOptimizer::findNextSource(RegSubRegPair RegSubReg,
                                       RewriteMapTy &RewriteMap) {
  // Do not try to find a new source for a physical register.
  // So far we do not have any motivating example for doing that.
  // Thus, instead of maintaining untested code, we will revisit that if
  // that changes at some point.
  Register Reg = RegSubReg.Reg;
  if (Reg.isPhysical())
    return false;
  const TargetRegisterClass *DefRC = MRI->getRegClass(Reg);

  SmallVector<RegSubRegPair, 4> SrcToLook;
  RegSubRegPair CurSrcPair = RegSubReg;
  SrcToLook.push_back(CurSrcPair);

  unsigned PHICount = 0;
  do {
    CurSrcPair = SrcToLook.pop_back_val();
    // As explained above, do not handle physical registers
    if (CurSrcPair.Reg.isPhysical())
      return false;

    ValueTracker ValTracker(CurSrcPair.Reg, CurSrcPair.SubReg, *MRI, TII);

    // Follow the chain of copies until we find a more suitable source, a phi
    // or have to abort.
    while (true) {
      ValueTrackerResult Res = ValTracker.getNextSource();
      // Abort at the end of a chain (without finding a suitable source).
      if (!Res.isValid())
        return false;

      // Insert the Def -> Use entry for the recently found source.
      ValueTrackerResult CurSrcRes = RewriteMap.lookup(CurSrcPair);
      if (CurSrcRes.isValid()) {
        assert(CurSrcRes == Res && "ValueTrackerResult found must match");
        // An existent entry with multiple sources is a PHI cycle we must avoid.
        // Otherwise it's an entry with a valid next source we already found.
        if (CurSrcRes.getNumSources() > 1) {
          LLVM_DEBUG(dbgs()
                     << "findNextSource: found PHI cycle, aborting...\n");
          return false;
        }
        break;
      }
      RewriteMap.insert(std::make_pair(CurSrcPair, Res));

      // ValueTrackerResult usually have one source unless it's the result from
      // a PHI instruction. Add the found PHI edges to be looked up further.
      unsigned NumSrcs = Res.getNumSources();
      if (NumSrcs > 1) {
        PHICount++;
        if (PHICount >= RewritePHILimit) {
          LLVM_DEBUG(dbgs() << "findNextSource: PHI limit reached\n");
          return false;
        }

        for (unsigned i = 0; i < NumSrcs; ++i)
          SrcToLook.push_back(Res.getSrc(i));
        break;
      }

      CurSrcPair = Res.getSrc(0);
      // Do not extend the live-ranges of physical registers as they add
      // constraints to the register allocator. Moreover, if we want to extend
      // the live-range of a physical register, unlike SSA virtual register,
      // we will have to check that they aren't redefine before the related use.
      if (CurSrcPair.Reg.isPhysical())
        return false;

      // Keep following the chain if the value isn't any better yet.
      const TargetRegisterClass *SrcRC = MRI->getRegClass(CurSrcPair.Reg);
      if (!TRI->shouldRewriteCopySrc(DefRC, RegSubReg.SubReg, SrcRC,
                                     CurSrcPair.SubReg))
        continue;

      // We currently cannot deal with subreg operands on PHI instructions
      // (see insertPHI()).
      if (PHICount > 0 && CurSrcPair.SubReg != 0)
        continue;

      // We found a suitable source, and are done with this chain.
      break;
    }
  } while (!SrcToLook.empty());

  // If we did not find a more suitable source, there is nothing to optimize.
  return CurSrcPair.Reg != Reg;
}

/// Insert a PHI instruction with incoming edges \p SrcRegs that are
/// guaranteed to have the same register class. This is necessary whenever we
/// successfully traverse a PHI instruction and find suitable sources coming
/// from its edges. By inserting a new PHI, we provide a rewritten PHI def
/// suitable to be used in a new COPY instruction.
static MachineInstr &
insertPHI(MachineRegisterInfo &MRI, const TargetInstrInfo &TII,
          const SmallVectorImpl<RegSubRegPair> &SrcRegs,
          MachineInstr &OrigPHI) {
  assert(!SrcRegs.empty() && "No sources to create a PHI instruction?");

  const TargetRegisterClass *NewRC = MRI.getRegClass(SrcRegs[0].Reg);
  // NewRC is only correct if no subregisters are involved. findNextSource()
  // should have rejected those cases already.
  assert(SrcRegs[0].SubReg == 0 && "should not have subreg operand");
  Register NewVR = MRI.createVirtualRegister(NewRC);
  MachineBasicBlock *MBB = OrigPHI.getParent();
  MachineInstrBuilder MIB = BuildMI(*MBB, &OrigPHI, OrigPHI.getDebugLoc(),
                                    TII.get(TargetOpcode::PHI), NewVR);

  unsigned MBBOpIdx = 2;
  for (const RegSubRegPair &RegPair : SrcRegs) {
    MIB.addReg(RegPair.Reg, 0, RegPair.SubReg);
    MIB.addMBB(OrigPHI.getOperand(MBBOpIdx).getMBB());
    // Since we're extended the lifetime of RegPair.Reg, clear the
    // kill flags to account for that and make RegPair.Reg reaches
    // the new PHI.
    MRI.clearKillFlags(RegPair.Reg);
    MBBOpIdx += 2;
  }

  return *MIB;
}

namespace {

/// Interface to query instructions amenable to copy rewriting.
class Rewriter {
protected:
  MachineInstr &CopyLike;
  unsigned CurrentSrcIdx = 0;   ///< The index of the source being rewritten.
public:
  Rewriter(MachineInstr &CopyLike) : CopyLike(CopyLike) {}
  virtual ~Rewriter() = default;

  /// Get the next rewritable source (SrcReg, SrcSubReg) and
  /// the related value that it affects (DstReg, DstSubReg).
  /// A source is considered rewritable if its register class and the
  /// register class of the related DstReg may not be register
  /// coalescer friendly. In other words, given a copy-like instruction
  /// not all the arguments may be returned at rewritable source, since
  /// some arguments are none to be register coalescer friendly.
  ///
  /// Each call of this method moves the current source to the next
  /// rewritable source.
  /// For instance, let CopyLike be the instruction to rewrite.
  /// CopyLike has one definition and one source:
  /// dst.dstSubIdx = CopyLike src.srcSubIdx.
  ///
  /// The first call will give the first rewritable source, i.e.,
  /// the only source this instruction has:
  /// (SrcReg, SrcSubReg) = (src, srcSubIdx).
  /// This source defines the whole definition, i.e.,
  /// (DstReg, DstSubReg) = (dst, dstSubIdx).
  ///
  /// The second and subsequent calls will return false, as there is only one
  /// rewritable source.
  ///
  /// \return True if a rewritable source has been found, false otherwise.
  /// The output arguments are valid if and only if true is returned.
  virtual bool getNextRewritableSource(RegSubRegPair &Src,
                                       RegSubRegPair &Dst) = 0;

  /// Rewrite the current source with \p NewReg and \p NewSubReg if possible.
  /// \return True if the rewriting was possible, false otherwise.
  virtual bool RewriteCurrentSource(Register NewReg, unsigned NewSubReg) = 0;
};

/// Rewriter for COPY instructions.
class CopyRewriter : public Rewriter {
public:
  CopyRewriter(MachineInstr &MI) : Rewriter(MI) {
    assert(MI.isCopy() && "Expected copy instruction");
  }
  virtual ~CopyRewriter() = default;

  bool getNextRewritableSource(RegSubRegPair &Src,
                               RegSubRegPair &Dst) override {
    // CurrentSrcIdx > 0 means this function has already been called.
    if (CurrentSrcIdx > 0)
      return false;
    // This is the first call to getNextRewritableSource.
    // Move the CurrentSrcIdx to remember that we made that call.
    CurrentSrcIdx = 1;
    // The rewritable source is the argument.
    const MachineOperand &MOSrc = CopyLike.getOperand(1);
    Src = RegSubRegPair(MOSrc.getReg(), MOSrc.getSubReg());
    // What we track are the alternative sources of the definition.
    const MachineOperand &MODef = CopyLike.getOperand(0);
    Dst = RegSubRegPair(MODef.getReg(), MODef.getSubReg());
    return true;
  }

  bool RewriteCurrentSource(Register NewReg, unsigned NewSubReg) override {
    if (CurrentSrcIdx != 1)
      return false;
    MachineOperand &MOSrc = CopyLike.getOperand(CurrentSrcIdx);
    MOSrc.setReg(NewReg);
    MOSrc.setSubReg(NewSubReg);
    return true;
  }
};

/// Helper class to rewrite uncoalescable copy like instructions
/// into new COPY (coalescable friendly) instructions.
class UncoalescableRewriter : public Rewriter {
  unsigned NumDefs;  ///< Number of defs in the bitcast.

public:
  UncoalescableRewriter(MachineInstr &MI) : Rewriter(MI) {
    NumDefs = MI.getDesc().getNumDefs();
  }

  /// \see See Rewriter::getNextRewritableSource()
  /// All such sources need to be considered rewritable in order to
  /// rewrite a uncoalescable copy-like instruction. This method return
  /// each definition that must be checked if rewritable.
  bool getNextRewritableSource(RegSubRegPair &Src,
                               RegSubRegPair &Dst) override {
    // Find the next non-dead definition and continue from there.
    if (CurrentSrcIdx == NumDefs)
      return false;

    while (CopyLike.getOperand(CurrentSrcIdx).isDead()) {
      ++CurrentSrcIdx;
      if (CurrentSrcIdx == NumDefs)
        return false;
    }

    // What we track are the alternative sources of the definition.
    Src = RegSubRegPair(0, 0);
    const MachineOperand &MODef = CopyLike.getOperand(CurrentSrcIdx);
    Dst = RegSubRegPair(MODef.getReg(), MODef.getSubReg());

    CurrentSrcIdx++;
    return true;
  }

  bool RewriteCurrentSource(Register NewReg, unsigned NewSubReg) override {
    return false;
  }
};

/// Specialized rewriter for INSERT_SUBREG instruction.
class InsertSubregRewriter : public Rewriter {
public:
  InsertSubregRewriter(MachineInstr &MI) : Rewriter(MI) {
    assert(MI.isInsertSubreg() && "Invalid instruction");
  }

  /// \see See Rewriter::getNextRewritableSource()
  /// Here CopyLike has the following form:
  /// dst = INSERT_SUBREG Src1, Src2.src2SubIdx, subIdx.
  /// Src1 has the same register class has dst, hence, there is
  /// nothing to rewrite.
  /// Src2.src2SubIdx, may not be register coalescer friendly.
  /// Therefore, the first call to this method returns:
  /// (SrcReg, SrcSubReg) = (Src2, src2SubIdx).
  /// (DstReg, DstSubReg) = (dst, subIdx).
  ///
  /// Subsequence calls will return false.
  bool getNextRewritableSource(RegSubRegPair &Src,
                               RegSubRegPair &Dst) override {
    // If we already get the only source we can rewrite, return false.
    if (CurrentSrcIdx == 2)
      return false;
    // We are looking at v2 = INSERT_SUBREG v0, v1, sub0.
    CurrentSrcIdx = 2;
    const MachineOperand &MOInsertedReg = CopyLike.getOperand(2);
    Src = RegSubRegPair(MOInsertedReg.getReg(), MOInsertedReg.getSubReg());
    const MachineOperand &MODef = CopyLike.getOperand(0);

    // We want to track something that is compatible with the
    // partial definition.
    if (MODef.getSubReg())
      // Bail if we have to compose sub-register indices.
      return false;
    Dst = RegSubRegPair(MODef.getReg(),
                        (unsigned)CopyLike.getOperand(3).getImm());
    return true;
  }

  bool RewriteCurrentSource(Register NewReg, unsigned NewSubReg) override {
    if (CurrentSrcIdx != 2)
      return false;
    // We are rewriting the inserted reg.
    MachineOperand &MO = CopyLike.getOperand(CurrentSrcIdx);
    MO.setReg(NewReg);
    MO.setSubReg(NewSubReg);
    return true;
  }
};

/// Specialized rewriter for EXTRACT_SUBREG instruction.
class ExtractSubregRewriter : public Rewriter {
  const TargetInstrInfo &TII;

public:
  ExtractSubregRewriter(MachineInstr &MI, const TargetInstrInfo &TII)
      : Rewriter(MI), TII(TII) {
    assert(MI.isExtractSubreg() && "Invalid instruction");
  }

  /// \see Rewriter::getNextRewritableSource()
  /// Here CopyLike has the following form:
  /// dst.dstSubIdx = EXTRACT_SUBREG Src, subIdx.
  /// There is only one rewritable source: Src.subIdx,
  /// which defines dst.dstSubIdx.
  bool getNextRewritableSource(RegSubRegPair &Src,
                               RegSubRegPair &Dst) override {
    // If we already get the only source we can rewrite, return false.
    if (CurrentSrcIdx == 1)
      return false;
    // We are looking at v1 = EXTRACT_SUBREG v0, sub0.
    CurrentSrcIdx = 1;
    const MachineOperand &MOExtractedReg = CopyLike.getOperand(1);
    // If we have to compose sub-register indices, bail out.
    if (MOExtractedReg.getSubReg())
      return false;

    Src = RegSubRegPair(MOExtractedReg.getReg(),
                        CopyLike.getOperand(2).getImm());

    // We want to track something that is compatible with the definition.
    const MachineOperand &MODef = CopyLike.getOperand(0);
    Dst = RegSubRegPair(MODef.getReg(), MODef.getSubReg());
    return true;
  }

  bool RewriteCurrentSource(Register NewReg, unsigned NewSubReg) override {
    // The only source we can rewrite is the input register.
    if (CurrentSrcIdx != 1)
      return false;

    CopyLike.getOperand(CurrentSrcIdx).setReg(NewReg);

    // If we find a source that does not require to extract something,
    // rewrite the operation with a copy.
    if (!NewSubReg) {
      // Move the current index to an invalid position.
      // We do not want another call to this method to be able
      // to do any change.
      CurrentSrcIdx = -1;
      // Rewrite the operation as a COPY.
      // Get rid of the sub-register index.
      CopyLike.removeOperand(2);
      // Morph the operation into a COPY.
      CopyLike.setDesc(TII.get(TargetOpcode::COPY));
      return true;
    }
    CopyLike.getOperand(CurrentSrcIdx + 1).setImm(NewSubReg);
    return true;
  }
};

/// Specialized rewriter for REG_SEQUENCE instruction.
class RegSequenceRewriter : public Rewriter {
public:
  RegSequenceRewriter(MachineInstr &MI) : Rewriter(MI) {
    assert(MI.isRegSequence() && "Invalid instruction");
  }

  /// \see Rewriter::getNextRewritableSource()
  /// Here CopyLike has the following form:
  /// dst = REG_SEQUENCE Src1.src1SubIdx, subIdx1, Src2.src2SubIdx, subIdx2.
  /// Each call will return a different source, walking all the available
  /// source.
  ///
  /// The first call returns:
  /// (SrcReg, SrcSubReg) = (Src1, src1SubIdx).
  /// (DstReg, DstSubReg) = (dst, subIdx1).
  ///
  /// The second call returns:
  /// (SrcReg, SrcSubReg) = (Src2, src2SubIdx).
  /// (DstReg, DstSubReg) = (dst, subIdx2).
  ///
  /// And so on, until all the sources have been traversed, then
  /// it returns false.
  bool getNextRewritableSource(RegSubRegPair &Src,
                               RegSubRegPair &Dst) override {
    // We are looking at v0 = REG_SEQUENCE v1, sub1, v2, sub2, etc.

    // If this is the first call, move to the first argument.
    if (CurrentSrcIdx == 0) {
      CurrentSrcIdx = 1;
    } else {
      // Otherwise, move to the next argument and check that it is valid.
      CurrentSrcIdx += 2;
      if (CurrentSrcIdx >= CopyLike.getNumOperands())
        return false;
    }
    const MachineOperand &MOInsertedReg = CopyLike.getOperand(CurrentSrcIdx);
    Src.Reg = MOInsertedReg.getReg();
    // If we have to compose sub-register indices, bail out.
    if ((Src.SubReg = MOInsertedReg.getSubReg()))
      return false;

    // We want to track something that is compatible with the related
    // partial definition.
    Dst.SubReg = CopyLike.getOperand(CurrentSrcIdx + 1).getImm();

    const MachineOperand &MODef = CopyLike.getOperand(0);
    Dst.Reg = MODef.getReg();
    // If we have to compose sub-registers, bail.
    return MODef.getSubReg() == 0;
  }

  bool RewriteCurrentSource(Register NewReg, unsigned NewSubReg) override {
    // We cannot rewrite out of bound operands.
    // Moreover, rewritable sources are at odd positions.
    if ((CurrentSrcIdx & 1) != 1 || CurrentSrcIdx > CopyLike.getNumOperands())
      return false;

    MachineOperand &MO = CopyLike.getOperand(CurrentSrcIdx);
    MO.setReg(NewReg);
    MO.setSubReg(NewSubReg);
    return true;
  }
};

} // end anonymous namespace

/// Get the appropriated Rewriter for \p MI.
/// \return A pointer to a dynamically allocated Rewriter or nullptr if no
/// rewriter works for \p MI.
static Rewriter *getCopyRewriter(MachineInstr &MI, const TargetInstrInfo &TII) {
  // Handle uncoalescable copy-like instructions.
  if (MI.isBitcast() || MI.isRegSequenceLike() || MI.isInsertSubregLike() ||
      MI.isExtractSubregLike())
    return new UncoalescableRewriter(MI);

  switch (MI.getOpcode()) {
  default:
    return nullptr;
  case TargetOpcode::COPY:
    return new CopyRewriter(MI);
  case TargetOpcode::INSERT_SUBREG:
    return new InsertSubregRewriter(MI);
  case TargetOpcode::EXTRACT_SUBREG:
    return new ExtractSubregRewriter(MI, TII);
  case TargetOpcode::REG_SEQUENCE:
    return new RegSequenceRewriter(MI);
  }
}

/// Given a \p Def.Reg and Def.SubReg  pair, use \p RewriteMap to find
/// the new source to use for rewrite. If \p HandleMultipleSources is true and
/// multiple sources for a given \p Def are found along the way, we found a
/// PHI instructions that needs to be rewritten.
/// TODO: HandleMultipleSources should be removed once we test PHI handling
/// with coalescable copies.
static RegSubRegPair
getNewSource(MachineRegisterInfo *MRI, const TargetInstrInfo *TII,
             RegSubRegPair Def,
             const PeepholeOptimizer::RewriteMapTy &RewriteMap,
             bool HandleMultipleSources = true) {
  RegSubRegPair LookupSrc(Def.Reg, Def.SubReg);
  while (true) {
    ValueTrackerResult Res = RewriteMap.lookup(LookupSrc);
    // If there are no entries on the map, LookupSrc is the new source.
    if (!Res.isValid())
      return LookupSrc;

    // There's only one source for this definition, keep searching...
    unsigned NumSrcs = Res.getNumSources();
    if (NumSrcs == 1) {
      LookupSrc.Reg = Res.getSrcReg(0);
      LookupSrc.SubReg = Res.getSrcSubReg(0);
      continue;
    }

    // TODO: Remove once multiple srcs w/ coalescable copies are supported.
    if (!HandleMultipleSources)
      break;

    // Multiple sources, recurse into each source to find a new source
    // for it. Then, rewrite the PHI accordingly to its new edges.
    SmallVector<RegSubRegPair, 4> NewPHISrcs;
    for (unsigned i = 0; i < NumSrcs; ++i) {
      RegSubRegPair PHISrc(Res.getSrcReg(i), Res.getSrcSubReg(i));
      NewPHISrcs.push_back(
          getNewSource(MRI, TII, PHISrc, RewriteMap, HandleMultipleSources));
    }

    // Build the new PHI node and return its def register as the new source.
    MachineInstr &OrigPHI = const_cast<MachineInstr &>(*Res.getInst());
    MachineInstr &NewPHI = insertPHI(*MRI, *TII, NewPHISrcs, OrigPHI);
    LLVM_DEBUG(dbgs() << "-- getNewSource\n");
    LLVM_DEBUG(dbgs() << "   Replacing: " << OrigPHI);
    LLVM_DEBUG(dbgs() << "        With: " << NewPHI);
    const MachineOperand &MODef = NewPHI.getOperand(0);
    return RegSubRegPair(MODef.getReg(), MODef.getSubReg());
  }

  return RegSubRegPair(0, 0);
}

/// Optimize generic copy instructions to avoid cross register bank copy.
/// The optimization looks through a chain of copies and tries to find a source
/// that has a compatible register class.
/// Two register classes are considered to be compatible if they share the same
/// register bank.
/// New copies issued by this optimization are register allocator
/// friendly. This optimization does not remove any copy as it may
/// overconstrain the register allocator, but replaces some operands
/// when possible.
/// \pre isCoalescableCopy(*MI) is true.
/// \return True, when \p MI has been rewritten. False otherwise.
bool PeepholeOptimizer::optimizeCoalescableCopy(MachineInstr &MI) {
  assert(isCoalescableCopy(MI) && "Invalid argument");
  assert(MI.getDesc().getNumDefs() == 1 &&
         "Coalescer can understand multiple defs?!");
  const MachineOperand &MODef = MI.getOperand(0);
  // Do not rewrite physical definitions.
  if (MODef.getReg().isPhysical())
    return false;

  bool Changed = false;
  // Get the right rewriter for the current copy.
  std::unique_ptr<Rewriter> CpyRewriter(getCopyRewriter(MI, *TII));
  // If none exists, bail out.
  if (!CpyRewriter)
    return false;
  // Rewrite each rewritable source.
  RegSubRegPair Src;
  RegSubRegPair TrackPair;
  while (CpyRewriter->getNextRewritableSource(Src, TrackPair)) {
    // Keep track of PHI nodes and its incoming edges when looking for sources.
    RewriteMapTy RewriteMap;
    // Try to find a more suitable source. If we failed to do so, or get the
    // actual source, move to the next source.
    if (!findNextSource(TrackPair, RewriteMap))
      continue;

    // Get the new source to rewrite. TODO: Only enable handling of multiple
    // sources (PHIs) once we have a motivating example and testcases for it.
    RegSubRegPair NewSrc = getNewSource(MRI, TII, TrackPair, RewriteMap,
                                        /*HandleMultipleSources=*/false);
    if (Src.Reg == NewSrc.Reg || NewSrc.Reg == 0)
      continue;

    // Rewrite source.
    if (CpyRewriter->RewriteCurrentSource(NewSrc.Reg, NewSrc.SubReg)) {
      // We may have extended the live-range of NewSrc, account for that.
      MRI->clearKillFlags(NewSrc.Reg);
      Changed = true;
    }
  }
  // TODO: We could have a clean-up method to tidy the instruction.
  // E.g., v0 = INSERT_SUBREG v1, v1.sub0, sub0
  // => v0 = COPY v1
  // Currently we haven't seen motivating example for that and we
  // want to avoid untested code.
  NumRewrittenCopies += Changed;
  return Changed;
}

/// Rewrite the source found through \p Def, by using the \p RewriteMap
/// and create a new COPY instruction. More info about RewriteMap in
/// PeepholeOptimizer::findNextSource. Right now this is only used to handle
/// Uncoalescable copies, since they are copy like instructions that aren't
/// recognized by the register allocator.
MachineInstr &
PeepholeOptimizer::rewriteSource(MachineInstr &CopyLike,
                                 RegSubRegPair Def, RewriteMapTy &RewriteMap) {
  assert(!Def.Reg.isPhysical() && "We do not rewrite physical registers");

  // Find the new source to use in the COPY rewrite.
  RegSubRegPair NewSrc = getNewSource(MRI, TII, Def, RewriteMap);

  // Insert the COPY.
  const TargetRegisterClass *DefRC = MRI->getRegClass(Def.Reg);
  Register NewVReg = MRI->createVirtualRegister(DefRC);

  MachineInstr *NewCopy =
      BuildMI(*CopyLike.getParent(), &CopyLike, CopyLike.getDebugLoc(),
              TII->get(TargetOpcode::COPY), NewVReg)
          .addReg(NewSrc.Reg, 0, NewSrc.SubReg);

  if (Def.SubReg) {
    NewCopy->getOperand(0).setSubReg(Def.SubReg);
    NewCopy->getOperand(0).setIsUndef();
  }

  LLVM_DEBUG(dbgs() << "-- RewriteSource\n");
  LLVM_DEBUG(dbgs() << "   Replacing: " << CopyLike);
  LLVM_DEBUG(dbgs() << "        With: " << *NewCopy);
  MRI->replaceRegWith(Def.Reg, NewVReg);
  MRI->clearKillFlags(NewVReg);

  // We extended the lifetime of NewSrc.Reg, clear the kill flags to
  // account for that.
  MRI->clearKillFlags(NewSrc.Reg);

  return *NewCopy;
}

/// Optimize copy-like instructions to create
/// register coalescer friendly instruction.
/// The optimization tries to kill-off the \p MI by looking
/// through a chain of copies to find a source that has a compatible
/// register class.
/// If such a source is found, it replace \p MI by a generic COPY
/// operation.
/// \pre isUncoalescableCopy(*MI) is true.
/// \return True, when \p MI has been optimized. In that case, \p MI has
/// been removed from its parent.
/// All COPY instructions created, are inserted in \p LocalMIs.
bool PeepholeOptimizer::optimizeUncoalescableCopy(
    MachineInstr &MI, SmallPtrSetImpl<MachineInstr *> &LocalMIs) {
  assert(isUncoalescableCopy(MI) && "Invalid argument");
  UncoalescableRewriter CpyRewriter(MI);

  // Rewrite each rewritable source by generating new COPYs. This works
  // differently from optimizeCoalescableCopy since it first makes sure that all
  // definitions can be rewritten.
  RewriteMapTy RewriteMap;
  RegSubRegPair Src;
  RegSubRegPair Def;
  SmallVector<RegSubRegPair, 4> RewritePairs;
  while (CpyRewriter.getNextRewritableSource(Src, Def)) {
    // If a physical register is here, this is probably for a good reason.
    // Do not rewrite that.
    if (Def.Reg.isPhysical())
      return false;

    // If we do not know how to rewrite this definition, there is no point
    // in trying to kill this instruction.
    if (!findNextSource(Def, RewriteMap))
      return false;

    RewritePairs.push_back(Def);
  }

  // The change is possible for all defs, do it.
  for (const RegSubRegPair &Def : RewritePairs) {
    // Rewrite the "copy" in a way the register coalescer understands.
    MachineInstr &NewCopy = rewriteSource(MI, Def, RewriteMap);
    LocalMIs.insert(&NewCopy);
  }

  // MI is now dead.
  LLVM_DEBUG(dbgs() << "Deleting uncoalescable copy: " << MI);
  MI.eraseFromParent();
  ++NumUncoalescableCopies;
  return true;
}

/// Check whether MI is a candidate for folding into a later instruction.
/// We only fold loads to virtual registers and the virtual register defined
/// has a single user.
bool PeepholeOptimizer::isLoadFoldable(
    MachineInstr &MI, SmallSet<Register, 16> &FoldAsLoadDefCandidates) {
  if (!MI.canFoldAsLoad() || !MI.mayLoad())
    return false;
  const MCInstrDesc &MCID = MI.getDesc();
  if (MCID.getNumDefs() != 1)
    return false;

  Register Reg = MI.getOperand(0).getReg();
  // To reduce compilation time, we check MRI->hasOneNonDBGUser when inserting
  // loads. It should be checked when processing uses of the load, since
  // uses can be removed during peephole.
  if (Reg.isVirtual() && !MI.getOperand(0).getSubReg() &&
      MRI->hasOneNonDBGUser(Reg)) {
    FoldAsLoadDefCandidates.insert(Reg);
    return true;
  }
  return false;
}

bool PeepholeOptimizer::isMoveImmediate(
    MachineInstr &MI, SmallSet<Register, 4> &ImmDefRegs,
    DenseMap<Register, MachineInstr *> &ImmDefMIs) {
  const MCInstrDesc &MCID = MI.getDesc();
  if (MCID.getNumDefs() != 1 || !MI.getOperand(0).isReg())
    return false;
  Register Reg = MI.getOperand(0).getReg();
  if (!Reg.isVirtual())
    return false;

  int64_t ImmVal;
  if (!MI.isMoveImmediate() && !TII->getConstValDefinedInReg(MI, Reg, ImmVal))
    return false;

  ImmDefMIs.insert(std::make_pair(Reg, &MI));
  ImmDefRegs.insert(Reg);
  return true;
}

/// Try folding register operands that are defined by move immediate
/// instructions, i.e. a trivial constant folding optimization, if
/// and only if the def and use are in the same BB.
bool PeepholeOptimizer::foldImmediate(
    MachineInstr &MI, SmallSet<Register, 4> &ImmDefRegs,
    DenseMap<Register, MachineInstr *> &ImmDefMIs, bool &Deleted) {
  Deleted = false;
  for (unsigned i = 0, e = MI.getDesc().getNumOperands(); i != e; ++i) {
    MachineOperand &MO = MI.getOperand(i);
    if (!MO.isReg() || MO.isDef())
      continue;
    Register Reg = MO.getReg();
    if (!Reg.isVirtual())
      continue;
    if (ImmDefRegs.count(Reg) == 0)
      continue;
    DenseMap<Register, MachineInstr *>::iterator II = ImmDefMIs.find(Reg);
    assert(II != ImmDefMIs.end() && "couldn't find immediate definition");
    if (TII->foldImmediate(MI, *II->second, Reg, MRI)) {
      ++NumImmFold;
      // foldImmediate can delete ImmDefMI if MI was its only user. If ImmDefMI
      // is not deleted, and we happened to get a same MI, we can delete MI and
      // replace its users.
      if (MRI->getVRegDef(Reg) &&
          MI.isIdenticalTo(*II->second, MachineInstr::IgnoreVRegDefs)) {
        Register DstReg = MI.getOperand(0).getReg();
        if (DstReg.isVirtual() &&
            MRI->getRegClass(DstReg) == MRI->getRegClass(Reg)) {
          MRI->replaceRegWith(DstReg, Reg);
          MI.eraseFromParent();
          Deleted = true;
        }
      }
      return true;
    }
  }
  return false;
}

// FIXME: This is very simple and misses some cases which should be handled when
// motivating examples are found.
//
// The copy rewriting logic should look at uses as well as defs and be able to
// eliminate copies across blocks.
//
// Later copies that are subregister extracts will also not be eliminated since
// only the first copy is considered.
//
// e.g.
// %1 = COPY %0
// %2 = COPY %0:sub1
//
// Should replace %2 uses with %1:sub1
bool PeepholeOptimizer::foldRedundantCopy(MachineInstr &MI) {
  assert(MI.isCopy() && "expected a COPY machine instruction");

  RegSubRegPair SrcPair;
  if (!getCopySrc(MI, SrcPair))
    return false;

  Register DstReg = MI.getOperand(0).getReg();
  if (!DstReg.isVirtual())
    return false;

  if (CopySrcMIs.insert(std::make_pair(SrcPair, &MI)).second) {
    // First copy of this reg seen.
    return false;
  }

  MachineInstr *PrevCopy = CopySrcMIs.find(SrcPair)->second;

  assert(SrcPair.SubReg == PrevCopy->getOperand(1).getSubReg() &&
         "Unexpected mismatching subreg!");

  Register PrevDstReg = PrevCopy->getOperand(0).getReg();

  // Only replace if the copy register class is the same.
  //
  // TODO: If we have multiple copies to different register classes, we may want
  // to track multiple copies of the same source register.
  if (MRI->getRegClass(DstReg) != MRI->getRegClass(PrevDstReg))
    return false;

  MRI->replaceRegWith(DstReg, PrevDstReg);

  // Lifetime of the previous copy has been extended.
  MRI->clearKillFlags(PrevDstReg);
  return true;
}

bool PeepholeOptimizer::isNAPhysCopy(Register Reg) {
  return Reg.isPhysical() && !MRI->isAllocatable(Reg);
}

bool PeepholeOptimizer::foldRedundantNAPhysCopy(
    MachineInstr &MI, DenseMap<Register, MachineInstr *> &NAPhysToVirtMIs) {
  assert(MI.isCopy() && "expected a COPY machine instruction");

  if (DisableNAPhysCopyOpt)
    return false;

  Register DstReg = MI.getOperand(0).getReg();
  Register SrcReg = MI.getOperand(1).getReg();
  if (isNAPhysCopy(SrcReg) && DstReg.isVirtual()) {
    // %vreg = COPY $physreg
    // Avoid using a datastructure which can track multiple live non-allocatable
    // phys->virt copies since LLVM doesn't seem to do this.
    NAPhysToVirtMIs.insert({SrcReg, &MI});
    return false;
  }

  if (!(SrcReg.isVirtual() && isNAPhysCopy(DstReg)))
    return false;

  // $physreg = COPY %vreg
  auto PrevCopy = NAPhysToVirtMIs.find(DstReg);
  if (PrevCopy == NAPhysToVirtMIs.end()) {
    // We can't remove the copy: there was an intervening clobber of the
    // non-allocatable physical register after the copy to virtual.
    LLVM_DEBUG(dbgs() << "NAPhysCopy: intervening clobber forbids erasing "
                      << MI);
    return false;
  }

  Register PrevDstReg = PrevCopy->second->getOperand(0).getReg();
  if (PrevDstReg == SrcReg) {
    // Remove the virt->phys copy: we saw the virtual register definition, and
    // the non-allocatable physical register's state hasn't changed since then.
    LLVM_DEBUG(dbgs() << "NAPhysCopy: erasing " << MI);
    ++NumNAPhysCopies;
    return true;
  }

  // Potential missed optimization opportunity: we saw a different virtual
  // register get a copy of the non-allocatable physical register, and we only
  // track one such copy. Avoid getting confused by this new non-allocatable
  // physical register definition, and remove it from the tracked copies.
  LLVM_DEBUG(dbgs() << "NAPhysCopy: missed opportunity " << MI);
  NAPhysToVirtMIs.erase(PrevCopy);
  return false;
}

/// \bried Returns true if \p MO is a virtual register operand.
static bool isVirtualRegisterOperand(MachineOperand &MO) {
  return MO.isReg() && MO.getReg().isVirtual();
}

bool PeepholeOptimizer::findTargetRecurrence(
    Register Reg, const SmallSet<Register, 2> &TargetRegs,
    RecurrenceCycle &RC) {
  // Recurrence found if Reg is in TargetRegs.
  if (TargetRegs.count(Reg))
    return true;

  // TODO: Curerntly, we only allow the last instruction of the recurrence
  // cycle (the instruction that feeds the PHI instruction) to have more than
  // one uses to guarantee that commuting operands does not tie registers
  // with overlapping live range. Once we have actual live range info of
  // each register, this constraint can be relaxed.
  if (!MRI->hasOneNonDBGUse(Reg))
    return false;

  // Give up if the reccurrence chain length is longer than the limit.
  if (RC.size() >= MaxRecurrenceChain)
    return false;

  MachineInstr &MI = *(MRI->use_instr_nodbg_begin(Reg));
  unsigned Idx = MI.findRegisterUseOperandIdx(Reg, /*TRI=*/nullptr);

  // Only interested in recurrences whose instructions have only one def, which
  // is a virtual register.
  if (MI.getDesc().getNumDefs() != 1)
    return false;

  MachineOperand &DefOp = MI.getOperand(0);
  if (!isVirtualRegisterOperand(DefOp))
    return false;

  // Check if def operand of MI is tied to any use operand. We are only
  // interested in the case that all the instructions in the recurrence chain
  // have there def operand tied with one of the use operand.
  unsigned TiedUseIdx;
  if (!MI.isRegTiedToUseOperand(0, &TiedUseIdx))
    return false;

  if (Idx == TiedUseIdx) {
    RC.push_back(RecurrenceInstr(&MI));
    return findTargetRecurrence(DefOp.getReg(), TargetRegs, RC);
  } else {
    // If Idx is not TiedUseIdx, check if Idx is commutable with TiedUseIdx.
    unsigned CommIdx = TargetInstrInfo::CommuteAnyOperandIndex;
    if (TII->findCommutedOpIndices(MI, Idx, CommIdx) && CommIdx == TiedUseIdx) {
      RC.push_back(RecurrenceInstr(&MI, Idx, CommIdx));
      return findTargetRecurrence(DefOp.getReg(), TargetRegs, RC);
    }
  }

  return false;
}

/// Phi instructions will eventually be lowered to copy instructions.
/// If phi is in a loop header, a recurrence may formulated around the source
/// and destination of the phi. For such case commuting operands of the
/// instructions in the recurrence may enable coalescing of the copy instruction
/// generated from the phi. For example, if there is a recurrence of
///
/// LoopHeader:
///   %1 = phi(%0, %100)
/// LoopLatch:
///   %0<def, tied1> = ADD %2<def, tied0>, %1
///
/// , the fact that %0 and %2 are in the same tied operands set makes
/// the coalescing of copy instruction generated from the phi in
/// LoopHeader(i.e. %1 = COPY %0) impossible, because %1 and
/// %2 have overlapping live range. This introduces additional move
/// instruction to the final assembly. However, if we commute %2 and
/// %1 of ADD instruction, the redundant move instruction can be
/// avoided.
bool PeepholeOptimizer::optimizeRecurrence(MachineInstr &PHI) {
  SmallSet<Register, 2> TargetRegs;
  for (unsigned Idx = 1; Idx < PHI.getNumOperands(); Idx += 2) {
    MachineOperand &MO = PHI.getOperand(Idx);
    assert(isVirtualRegisterOperand(MO) && "Invalid PHI instruction");
    TargetRegs.insert(MO.getReg());
  }

  bool Changed = false;
  RecurrenceCycle RC;
  if (findTargetRecurrence(PHI.getOperand(0).getReg(), TargetRegs, RC)) {
    // Commutes operands of instructions in RC if necessary so that the copy to
    // be generated from PHI can be coalesced.
    LLVM_DEBUG(dbgs() << "Optimize recurrence chain from " << PHI);
    for (auto &RI : RC) {
      LLVM_DEBUG(dbgs() << "\tInst: " << *(RI.getMI()));
      auto CP = RI.getCommutePair();
      if (CP) {
        Changed = true;
        TII->commuteInstruction(*(RI.getMI()), false, (*CP).first,
                                (*CP).second);
        LLVM_DEBUG(dbgs() << "\t\tCommuted: " << *(RI.getMI()));
      }
    }
  }

  return Changed;
}

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

  LLVM_DEBUG(dbgs() << "********** PEEPHOLE OPTIMIZER **********\n");
  LLVM_DEBUG(dbgs() << "********** Function: " << MF.getName() << '\n');

  if (DisablePeephole)
    return false;

  TII = MF.getSubtarget().getInstrInfo();
  TRI = MF.getSubtarget().getRegisterInfo();
  MRI = &MF.getRegInfo();
  DT = Aggressive ? &getAnalysis<MachineDominatorTreeWrapperPass>().getDomTree()
                  : nullptr;
  MLI = &getAnalysis<MachineLoopInfoWrapperPass>().getLI();
  MF.setDelegate(this);

  bool Changed = false;

  for (MachineBasicBlock &MBB : MF) {
    bool SeenMoveImm = false;

    // During this forward scan, at some point it needs to answer the question
    // "given a pointer to an MI in the current BB, is it located before or
    // after the current instruction".
    // To perform this, the following set keeps track of the MIs already seen
    // during the scan, if a MI is not in the set, it is assumed to be located
    // after. Newly created MIs have to be inserted in the set as well.
    SmallPtrSet<MachineInstr*, 16> LocalMIs;
    SmallSet<Register, 4> ImmDefRegs;
    DenseMap<Register, MachineInstr *> ImmDefMIs;
    SmallSet<Register, 16> FoldAsLoadDefCandidates;

    // Track when a non-allocatable physical register is copied to a virtual
    // register so that useless moves can be removed.
    //
    // $physreg is the map index; MI is the last valid `%vreg = COPY $physreg`
    // without any intervening re-definition of $physreg.
    DenseMap<Register, MachineInstr *> NAPhysToVirtMIs;

    CopySrcMIs.clear();

    bool IsLoopHeader = MLI->isLoopHeader(&MBB);

    for (MachineBasicBlock::iterator MII = MBB.begin(), MIE = MBB.end();
         MII != MIE; ) {
      MachineInstr *MI = &*MII;
      // We may be erasing MI below, increment MII now.
      ++MII;
      LocalMIs.insert(MI);

      // Skip debug instructions. They should not affect this peephole
      // optimization.
      if (MI->isDebugInstr())
        continue;

      if (MI->isPosition())
        continue;

      if (IsLoopHeader && MI->isPHI()) {
        if (optimizeRecurrence(*MI)) {
          Changed = true;
          continue;
        }
      }

      if (!MI->isCopy()) {
        for (const MachineOperand &MO : MI->operands()) {
          // Visit all operands: definitions can be implicit or explicit.
          if (MO.isReg()) {
            Register Reg = MO.getReg();
            if (MO.isDef() && isNAPhysCopy(Reg)) {
              const auto &Def = NAPhysToVirtMIs.find(Reg);
              if (Def != NAPhysToVirtMIs.end()) {
                // A new definition of the non-allocatable physical register
                // invalidates previous copies.
                LLVM_DEBUG(dbgs()
                           << "NAPhysCopy: invalidating because of " << *MI);
                NAPhysToVirtMIs.erase(Def);
              }
            }
          } else if (MO.isRegMask()) {
            const uint32_t *RegMask = MO.getRegMask();
            for (auto &RegMI : NAPhysToVirtMIs) {
              Register Def = RegMI.first;
              if (MachineOperand::clobbersPhysReg(RegMask, Def)) {
                LLVM_DEBUG(dbgs()
                           << "NAPhysCopy: invalidating because of " << *MI);
                NAPhysToVirtMIs.erase(Def);
              }
            }
          }
        }
      }

      if (MI->isImplicitDef() || MI->isKill())
        continue;

      if (MI->isInlineAsm() || MI->hasUnmodeledSideEffects()) {
        // Blow away all non-allocatable physical registers knowledge since we
        // don't know what's correct anymore.
        //
        // FIXME: handle explicit asm clobbers.
        LLVM_DEBUG(dbgs() << "NAPhysCopy: blowing away all info due to "
                          << *MI);
        NAPhysToVirtMIs.clear();
      }

      if ((isUncoalescableCopy(*MI) &&
           optimizeUncoalescableCopy(*MI, LocalMIs)) ||
          (MI->isCompare() && optimizeCmpInstr(*MI)) ||
          (MI->isSelect() && optimizeSelect(*MI, LocalMIs))) {
        // MI is deleted.
        LocalMIs.erase(MI);
        Changed = true;
        continue;
      }

      if (MI->isConditionalBranch() && optimizeCondBranch(*MI)) {
        Changed = true;
        continue;
      }

      if (isCoalescableCopy(*MI) && optimizeCoalescableCopy(*MI)) {
        // MI is just rewritten.
        Changed = true;
        continue;
      }

      if (MI->isCopy() && (foldRedundantCopy(*MI) ||
                           foldRedundantNAPhysCopy(*MI, NAPhysToVirtMIs))) {
        LocalMIs.erase(MI);
        LLVM_DEBUG(dbgs() << "Deleting redundant copy: " << *MI << "\n");
        MI->eraseFromParent();
        Changed = true;
        continue;
      }

      if (isMoveImmediate(*MI, ImmDefRegs, ImmDefMIs)) {
        SeenMoveImm = true;
      } else {
        Changed |= optimizeExtInstr(*MI, MBB, LocalMIs);
        // optimizeExtInstr might have created new instructions after MI
        // and before the already incremented MII. Adjust MII so that the
        // next iteration sees the new instructions.
        MII = MI;
        ++MII;
        if (SeenMoveImm) {
          bool Deleted;
          Changed |= foldImmediate(*MI, ImmDefRegs, ImmDefMIs, Deleted);
          if (Deleted) {
            LocalMIs.erase(MI);
            continue;
          }
        }
      }

      // Check whether MI is a load candidate for folding into a later
      // instruction. If MI is not a candidate, check whether we can fold an
      // earlier load into MI.
      if (!isLoadFoldable(*MI, FoldAsLoadDefCandidates) &&
          !FoldAsLoadDefCandidates.empty()) {

        // We visit each operand even after successfully folding a previous
        // one.  This allows us to fold multiple loads into a single
        // instruction.  We do assume that optimizeLoadInstr doesn't insert
        // foldable uses earlier in the argument list.  Since we don't restart
        // iteration, we'd miss such cases.
        const MCInstrDesc &MIDesc = MI->getDesc();
        for (unsigned i = MIDesc.getNumDefs(); i != MI->getNumOperands();
             ++i) {
          const MachineOperand &MOp = MI->getOperand(i);
          if (!MOp.isReg())
            continue;
          Register FoldAsLoadDefReg = MOp.getReg();
          if (FoldAsLoadDefCandidates.count(FoldAsLoadDefReg)) {
            // We need to fold load after optimizeCmpInstr, since
            // optimizeCmpInstr can enable folding by converting SUB to CMP.
            // Save FoldAsLoadDefReg because optimizeLoadInstr() resets it and
            // we need it for markUsesInDebugValueAsUndef().
            Register FoldedReg = FoldAsLoadDefReg;
            MachineInstr *DefMI = nullptr;
            if (MachineInstr *FoldMI =
                    TII->optimizeLoadInstr(*MI, MRI, FoldAsLoadDefReg, DefMI)) {
              // Update LocalMIs since we replaced MI with FoldMI and deleted
              // DefMI.
              LLVM_DEBUG(dbgs() << "Replacing: " << *MI);
              LLVM_DEBUG(dbgs() << "     With: " << *FoldMI);
              LocalMIs.erase(MI);
              LocalMIs.erase(DefMI);
              LocalMIs.insert(FoldMI);
              // Update the call site info.
              if (MI->shouldUpdateCallSiteInfo())
                MI->getMF()->moveCallSiteInfo(MI, FoldMI);
              MI->eraseFromParent();
              DefMI->eraseFromParent();
              MRI->markUsesInDebugValueAsUndef(FoldedReg);
              FoldAsLoadDefCandidates.erase(FoldedReg);
              ++NumLoadFold;

              // MI is replaced with FoldMI so we can continue trying to fold
              Changed = true;
              MI = FoldMI;
            }
          }
        }
      }

      // If we run into an instruction we can't fold across, discard
      // the load candidates.  Note: We might be able to fold *into* this
      // instruction, so this needs to be after the folding logic.
      if (MI->isLoadFoldBarrier()) {
        LLVM_DEBUG(dbgs() << "Encountered load fold barrier on " << *MI);
        FoldAsLoadDefCandidates.clear();
      }
    }
  }

  MF.resetDelegate(this);
  return Changed;
}

ValueTrackerResult ValueTracker::getNextSourceFromCopy() {
  assert(Def->isCopy() && "Invalid definition");
  // Copy instruction are supposed to be: Def = Src.
  // If someone breaks this assumption, bad things will happen everywhere.
  // There may be implicit uses preventing the copy to be moved across
  // some target specific register definitions
  assert(Def->getNumOperands() - Def->getNumImplicitOperands() == 2 &&
         "Invalid number of operands");
  assert(!Def->hasImplicitDef() && "Only implicit uses are allowed");

  if (Def->getOperand(DefIdx).getSubReg() != DefSubReg)
    // If we look for a different subreg, it means we want a subreg of src.
    // Bails as we do not support composing subregs yet.
    return ValueTrackerResult();
  // Otherwise, we want the whole source.
  const MachineOperand &Src = Def->getOperand(1);
  if (Src.isUndef())
    return ValueTrackerResult();
  return ValueTrackerResult(Src.getReg(), Src.getSubReg());
}

ValueTrackerResult ValueTracker::getNextSourceFromBitcast() {
  assert(Def->isBitcast() && "Invalid definition");

  // Bail if there are effects that a plain copy will not expose.
  if (Def->mayRaiseFPException() || Def->hasUnmodeledSideEffects())
    return ValueTrackerResult();

  // Bitcasts with more than one def are not supported.
  if (Def->getDesc().getNumDefs() != 1)
    return ValueTrackerResult();
  const MachineOperand DefOp = Def->getOperand(DefIdx);
  if (DefOp.getSubReg() != DefSubReg)
    // If we look for a different subreg, it means we want a subreg of the src.
    // Bails as we do not support composing subregs yet.
    return ValueTrackerResult();

  unsigned SrcIdx = Def->getNumOperands();
  for (unsigned OpIdx = DefIdx + 1, EndOpIdx = SrcIdx; OpIdx != EndOpIdx;
       ++OpIdx) {
    const MachineOperand &MO = Def->getOperand(OpIdx);
    if (!MO.isReg() || !MO.getReg())
      continue;
    // Ignore dead implicit defs.
    if (MO.isImplicit() && MO.isDead())
      continue;
    assert(!MO.isDef() && "We should have skipped all the definitions by now");
    if (SrcIdx != EndOpIdx)
      // Multiple sources?
      return ValueTrackerResult();
    SrcIdx = OpIdx;
  }

  // In some rare case, Def has no input, SrcIdx is out of bound,
  // getOperand(SrcIdx) will fail below.
  if (SrcIdx >= Def->getNumOperands())
    return ValueTrackerResult();

  // Stop when any user of the bitcast is a SUBREG_TO_REG, replacing with a COPY
  // will break the assumed guarantees for the upper bits.
  for (const MachineInstr &UseMI : MRI.use_nodbg_instructions(DefOp.getReg())) {
    if (UseMI.isSubregToReg())
      return ValueTrackerResult();
  }

  const MachineOperand &Src = Def->getOperand(SrcIdx);
  if (Src.isUndef())
    return ValueTrackerResult();
  return ValueTrackerResult(Src.getReg(), Src.getSubReg());
}

ValueTrackerResult ValueTracker::getNextSourceFromRegSequence() {
  assert((Def->isRegSequence() || Def->isRegSequenceLike()) &&
         "Invalid definition");

  if (Def->getOperand(DefIdx).getSubReg())
    // If we are composing subregs, bail out.
    // The case we are checking is Def.<subreg> = REG_SEQUENCE.
    // This should almost never happen as the SSA property is tracked at
    // the register level (as opposed to the subreg level).
    // I.e.,
    // Def.sub0 =
    // Def.sub1 =
    // is a valid SSA representation for Def.sub0 and Def.sub1, but not for
    // Def. Thus, it must not be generated.
    // However, some code could theoretically generates a single
    // Def.sub0 (i.e, not defining the other subregs) and we would
    // have this case.
    // If we can ascertain (or force) that this never happens, we could
    // turn that into an assertion.
    return ValueTrackerResult();

  if (!TII)
    // We could handle the REG_SEQUENCE here, but we do not want to
    // duplicate the code from the generic TII.
    return ValueTrackerResult();

  SmallVector<RegSubRegPairAndIdx, 8> RegSeqInputRegs;
  if (!TII->getRegSequenceInputs(*Def, DefIdx, RegSeqInputRegs))
    return ValueTrackerResult();

  // We are looking at:
  // Def = REG_SEQUENCE v0, sub0, v1, sub1, ...
  // Check if one of the operand defines the subreg we are interested in.
  for (const RegSubRegPairAndIdx &RegSeqInput : RegSeqInputRegs) {
    if (RegSeqInput.SubIdx == DefSubReg)
      return ValueTrackerResult(RegSeqInput.Reg, RegSeqInput.SubReg);
  }

  // If the subreg we are tracking is super-defined by another subreg,
  // we could follow this value. However, this would require to compose
  // the subreg and we do not do that for now.
  return ValueTrackerResult();
}

ValueTrackerResult ValueTracker::getNextSourceFromInsertSubreg() {
  assert((Def->isInsertSubreg() || Def->isInsertSubregLike()) &&
         "Invalid definition");

  if (Def->getOperand(DefIdx).getSubReg())
    // If we are composing subreg, bail out.
    // Same remark as getNextSourceFromRegSequence.
    // I.e., this may be turned into an assert.
    return ValueTrackerResult();

  if (!TII)
    // We could handle the REG_SEQUENCE here, but we do not want to
    // duplicate the code from the generic TII.
    return ValueTrackerResult();

  RegSubRegPair BaseReg;
  RegSubRegPairAndIdx InsertedReg;
  if (!TII->getInsertSubregInputs(*Def, DefIdx, BaseReg, InsertedReg))
    return ValueTrackerResult();

  // We are looking at:
  // Def = INSERT_SUBREG v0, v1, sub1
  // There are two cases:
  // 1. DefSubReg == sub1, get v1.
  // 2. DefSubReg != sub1, the value may be available through v0.

  // #1 Check if the inserted register matches the required sub index.
  if (InsertedReg.SubIdx == DefSubReg) {
    return ValueTrackerResult(InsertedReg.Reg, InsertedReg.SubReg);
  }
  // #2 Otherwise, if the sub register we are looking for is not partial
  // defined by the inserted element, we can look through the main
  // register (v0).
  const MachineOperand &MODef = Def->getOperand(DefIdx);
  // If the result register (Def) and the base register (v0) do not
  // have the same register class or if we have to compose
  // subregisters, bail out.
  if (MRI.getRegClass(MODef.getReg()) != MRI.getRegClass(BaseReg.Reg) ||
      BaseReg.SubReg)
    return ValueTrackerResult();

  // Get the TRI and check if the inserted sub-register overlaps with the
  // sub-register we are tracking.
  const TargetRegisterInfo *TRI = MRI.getTargetRegisterInfo();
  if (!TRI ||
      !(TRI->getSubRegIndexLaneMask(DefSubReg) &
        TRI->getSubRegIndexLaneMask(InsertedReg.SubIdx)).none())
    return ValueTrackerResult();
  // At this point, the value is available in v0 via the same subreg
  // we used for Def.
  return ValueTrackerResult(BaseReg.Reg, DefSubReg);
}

ValueTrackerResult ValueTracker::getNextSourceFromExtractSubreg() {
  assert((Def->isExtractSubreg() ||
          Def->isExtractSubregLike()) && "Invalid definition");
  // We are looking at:
  // Def = EXTRACT_SUBREG v0, sub0

  // Bail if we have to compose sub registers.
  // Indeed, if DefSubReg != 0, we would have to compose it with sub0.
  if (DefSubReg)
    return ValueTrackerResult();

  if (!TII)
    // We could handle the EXTRACT_SUBREG here, but we do not want to
    // duplicate the code from the generic TII.
    return ValueTrackerResult();

  RegSubRegPairAndIdx ExtractSubregInputReg;
  if (!TII->getExtractSubregInputs(*Def, DefIdx, ExtractSubregInputReg))
    return ValueTrackerResult();

  // Bail if we have to compose sub registers.
  // Likewise, if v0.subreg != 0, we would have to compose v0.subreg with sub0.
  if (ExtractSubregInputReg.SubReg)
    return ValueTrackerResult();
  // Otherwise, the value is available in the v0.sub0.
  return ValueTrackerResult(ExtractSubregInputReg.Reg,
                            ExtractSubregInputReg.SubIdx);
}

ValueTrackerResult ValueTracker::getNextSourceFromSubregToReg() {
  assert(Def->isSubregToReg() && "Invalid definition");
  // We are looking at:
  // Def = SUBREG_TO_REG Imm, v0, sub0

  // Bail if we have to compose sub registers.
  // If DefSubReg != sub0, we would have to check that all the bits
  // we track are included in sub0 and if yes, we would have to
  // determine the right subreg in v0.
  if (DefSubReg != Def->getOperand(3).getImm())
    return ValueTrackerResult();
  // Bail if we have to compose sub registers.
  // Likewise, if v0.subreg != 0, we would have to compose it with sub0.
  if (Def->getOperand(2).getSubReg())
    return ValueTrackerResult();

  return ValueTrackerResult(Def->getOperand(2).getReg(),
                            Def->getOperand(3).getImm());
}

/// Explore each PHI incoming operand and return its sources.
ValueTrackerResult ValueTracker::getNextSourceFromPHI() {
  assert(Def->isPHI() && "Invalid definition");
  ValueTrackerResult Res;

  // If we look for a different subreg, bail as we do not support composing
  // subregs yet.
  if (Def->getOperand(0).getSubReg() != DefSubReg)
    return ValueTrackerResult();

  // Return all register sources for PHI instructions.
  for (unsigned i = 1, e = Def->getNumOperands(); i < e; i += 2) {
    const MachineOperand &MO = Def->getOperand(i);
    assert(MO.isReg() && "Invalid PHI instruction");
    // We have no code to deal with undef operands. They shouldn't happen in
    // normal programs anyway.
    if (MO.isUndef())
      return ValueTrackerResult();
    Res.addSource(MO.getReg(), MO.getSubReg());
  }

  return Res;
}

ValueTrackerResult ValueTracker::getNextSourceImpl() {
  assert(Def && "This method needs a valid definition");

  assert(((Def->getOperand(DefIdx).isDef() &&
           (DefIdx < Def->getDesc().getNumDefs() ||
            Def->getDesc().isVariadic())) ||
          Def->getOperand(DefIdx).isImplicit()) &&
         "Invalid DefIdx");
  if (Def->isCopy())
    return getNextSourceFromCopy();
  if (Def->isBitcast())
    return getNextSourceFromBitcast();
  // All the remaining cases involve "complex" instructions.
  // Bail if we did not ask for the advanced tracking.
  if (DisableAdvCopyOpt)
    return ValueTrackerResult();
  if (Def->isRegSequence() || Def->isRegSequenceLike())
    return getNextSourceFromRegSequence();
  if (Def->isInsertSubreg() || Def->isInsertSubregLike())
    return getNextSourceFromInsertSubreg();
  if (Def->isExtractSubreg() || Def->isExtractSubregLike())
    return getNextSourceFromExtractSubreg();
  if (Def->isSubregToReg())
    return getNextSourceFromSubregToReg();
  if (Def->isPHI())
    return getNextSourceFromPHI();
  return ValueTrackerResult();
}

ValueTrackerResult ValueTracker::getNextSource() {
  // If we reach a point where we cannot move up in the use-def chain,
  // there is nothing we can get.
  if (!Def)
    return ValueTrackerResult();

  ValueTrackerResult Res = getNextSourceImpl();
  if (Res.isValid()) {
    // Update definition, definition index, and subregister for the
    // next call of getNextSource.
    // Update the current register.
    bool OneRegSrc = Res.getNumSources() == 1;
    if (OneRegSrc)
      Reg = Res.getSrcReg(0);
    // Update the result before moving up in the use-def chain
    // with the instruction containing the last found sources.
    Res.setInst(Def);

    // If we can still move up in the use-def chain, move to the next
    // definition.
    if (!Reg.isPhysical() && OneRegSrc) {
      MachineRegisterInfo::def_iterator DI = MRI.def_begin(Reg);
      if (DI != MRI.def_end()) {
        Def = DI->getParent();
        DefIdx = DI.getOperandNo();
        DefSubReg = Res.getSrcSubReg(0);
      } else {
        Def = nullptr;
      }
      return Res;
    }
  }
  // If we end up here, this means we will not be able to find another source
  // for the next iteration. Make sure any new call to getNextSource bails out
  // early by cutting the use-def chain.
  Def = nullptr;
  return Res;
}
