//===- 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/CodeGen/PeepholeOptimizer.h"
#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/MachinePassManager.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;

/// Interface to query instructions amenable to copy rewriting.
class Rewriter {
protected:
  MachineInstr &CopyLike;
  int 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 {
    if (++CurrentSrcIdx > 1)
      return false;

    // The rewritable source is the argument.
    const MachineOperand &MOSrc = CopyLike.getOperand(CurrentSrcIdx);
    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 {
    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 {
  int 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");
    CurrentSrcIdx = -1;
  }

  /// \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.
    CurrentSrcIdx += 2;
    if (static_cast<unsigned>(CurrentSrcIdx) >= CopyLike.getNumOperands())
      return false;

    const MachineOperand &MOInsertedReg = CopyLike.getOperand(CurrentSrcIdx);
    Src.Reg = MOInsertedReg.getReg();
    Src.SubReg = MOInsertedReg.getSubReg();

    // 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();
    assert(MODef.getSubReg() == 0 && "cannot have subregister def in SSA");
    return true;
  }

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

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

public:
  PeepholeOptimizer(MachineDominatorTree *DT, MachineLoopInfo *MLI)
      : DT(DT), MLI(MLI) {}

  bool run(MachineFunction &MF);
  /// 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 optimizeCoalescableCopyImpl(Rewriter &&CpyRewriter);
  bool optimizeCoalescableCopy(MachineInstr &MI);
  bool optimizeUncoalescableCopy(MachineInstr &MI,
                                 SmallPtrSetImpl<MachineInstr *> &LocalMIs);
  bool optimizeRecurrence(MachineInstr &PHI);
  bool findNextSource(const TargetRegisterClass *DefRC, unsigned DefSubReg,
                      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.
  static 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.
  static 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);
  }
};

class PeepholeOptimizerLegacy : public MachineFunctionPass {
public:
  static char ID; // Pass identification

  PeepholeOptimizerLegacy() : MachineFunctionPass(ID) {
    initializePeepholeOptimizerLegacyPass(*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);
  }
};

/// 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 PeepholeOptimizerLegacy::ID = 0;

char &llvm::PeepholeOptimizerLegacyID = PeepholeOptimizerLegacy::ID;

INITIALIZE_PASS_BEGIN(PeepholeOptimizerLegacy, DEBUG_TYPE,
                      "Peephole Optimizations", false, false)
INITIALIZE_PASS_DEPENDENCY(MachineDominatorTreeWrapperPass)
INITIALIZE_PASS_DEPENDENCY(MachineLoopInfoWrapperPass)
INITIALIZE_PASS_END(PeepholeOptimizerLegacy, 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 a better source value that shares the same register file to
/// replace \p RegSubReg in an instruction like
/// `DefRC.DefSubReg = COPY RegSubReg`
///
/// 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(const TargetRegisterClass *DefRC,
                                       unsigned DefSubReg,
                                       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;
  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.
      auto [InsertPt, WasInserted] = RewriteMap.try_emplace(CurSrcPair, Res);

      if (!WasInserted) {
        const ValueTrackerResult &CurSrcRes = InsertPt->second;

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

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

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

bool PeepholeOptimizer::optimizeCoalescableCopyImpl(Rewriter &&CpyRewriter) {
  bool Changed = false;
  // Get the right rewriter for the current copy.
  // Rewrite each rewritable source.
  RegSubRegPair Dst;
  RegSubRegPair TrackPair;
  while (CpyRewriter.getNextRewritableSource(TrackPair, Dst)) {
    if (Dst.Reg.isPhysical()) {
      // 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.
      continue;
    }

    const TargetRegisterClass *DefRC = MRI->getRegClass(Dst.Reg);

    // 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(DefRC, Dst.SubReg, 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);
    assert(TrackPair.Reg != NewSrc.Reg &&
           "should not rewrite source to original value");
    if (!NewSrc.Reg)
      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;
}

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

  switch (MI.getOpcode()) {
  case TargetOpcode::COPY:
    return optimizeCoalescableCopyImpl(CopyRewriter(MI));
  case TargetOpcode::INSERT_SUBREG:
    return optimizeCoalescableCopyImpl(InsertSubregRewriter(MI));
  case TargetOpcode::EXTRACT_SUBREG:
    return optimizeCoalescableCopyImpl(ExtractSubregRewriter(MI, *TII));
  case TargetOpcode::REG_SEQUENCE:
    return optimizeCoalescableCopyImpl(RegSequenceRewriter(MI));
  default:
    // Handle uncoalescable copy-like instructions.
    if (MI.isBitcast() || MI.isRegSequenceLike() || MI.isInsertSubregLike() ||
        MI.isExtractSubregLike())
      return optimizeCoalescableCopyImpl(UncoalescableRewriter(MI));
    return false;
  }
}

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

    // FIXME: Uncoalescable copies are treated differently by
    // UncoalescableRewriter, and this probably should not share
    // API. getNextRewritableSource really finds rewritable defs.
    const TargetRegisterClass *DefRC = MRI->getRegClass(Def.Reg);

    // If we do not know how to rewrite this definition, there is no point
    // in trying to kill this instruction.
    if (!findNextSource(DefRC, Def.SubReg, 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;
}

PreservedAnalyses
PeepholeOptimizerPass::run(MachineFunction &MF,
                           MachineFunctionAnalysisManager &MFAM) {
  MFPropsModifier _(*this, MF);
  auto *DT =
      Aggressive ? &MFAM.getResult<MachineDominatorTreeAnalysis>(MF) : nullptr;
  auto *MLI = &MFAM.getResult<MachineLoopAnalysis>(MF);
  PeepholeOptimizer Impl(DT, MLI);
  bool Changed = Impl.run(MF);
  if (!Changed)
    return PreservedAnalyses::all();

  auto PA = getMachineFunctionPassPreservedAnalyses();
  PA.preserve<MachineDominatorTreeAnalysis>();
  PA.preserve<MachineLoopAnalysis>();
  PA.preserveSet<CFGAnalyses>();
  return PA;
}

bool PeepholeOptimizerLegacy::runOnMachineFunction(MachineFunction &MF) {
  if (skipFunction(MF.getFunction()))
    return false;
  auto *DT = Aggressive
                 ? &getAnalysis<MachineDominatorTreeWrapperPass>().getDomTree()
                 : nullptr;
  auto *MLI = &getAnalysis<MachineLoopInfoWrapperPass>().getLI();
  PeepholeOptimizer Impl(DT, MLI);
  return Impl.run(MF);
}

bool PeepholeOptimizer::run(MachineFunction &MF) {

  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();
  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 info.
              if (MI->shouldUpdateAdditionalCallInfo())
                MI->getMF()->moveAdditionalCallInfo(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");
  assert(!Def->getOperand(DefIdx).getSubReg() && "no subregister defs in SSA");

  // 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();

  assert(!Def->getOperand(DefIdx).getSubReg() && "no subregister defs in SSA");

  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();

  const MachineOperand &DefOp = Def->getOperand(DefIdx);

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

  assert(!Def->getOperand(DefIdx).getSubReg() && "illegal subregister def");

  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 operands exactly defines the subreg we are interested
  // in.
  for (const RegSubRegPairAndIdx &RegSeqInput : RegSeqInputRegs) {
    if (RegSeqInput.SubIdx == DefSubReg)
      return ValueTrackerResult(RegSeqInput.Reg, RegSeqInput.SubReg);
  }

  const TargetRegisterInfo *TRI = MRI.getTargetRegisterInfo();

  // If we did not find an exact match, see if we can do a composition to
  // extract a sub-subregister.
  for (const RegSubRegPairAndIdx &RegSeqInput : RegSeqInputRegs) {
    LaneBitmask DefMask = TRI->getSubRegIndexLaneMask(DefSubReg);
    LaneBitmask ThisOpRegMask = TRI->getSubRegIndexLaneMask(RegSeqInput.SubIdx);

    // Check that this extract reads a subset of this single reg_sequence input.
    //
    // FIXME: We should be able to filter this in terms of the indexes directly
    // without checking the lanemasks.
    if ((DefMask & ThisOpRegMask) != DefMask)
      continue;

    unsigned ReverseDefCompose =
        TRI->reverseComposeSubRegIndices(RegSeqInput.SubIdx, DefSubReg);
    if (!ReverseDefCompose)
      continue;

    unsigned ComposedDefInSrcReg1 =
        TRI->composeSubRegIndices(RegSeqInput.SubReg, ReverseDefCompose);

    // TODO: We should be able to defer checking if the result register class
    // supports the index to continue looking for a rewritable source.
    //
    // TODO: Should we modify the register class to support the index?
    const TargetRegisterClass *SrcRC = MRI.getRegClass(RegSeqInput.Reg);
    const TargetRegisterClass *SrcWithSubRC =
        TRI->getSubClassWithSubReg(SrcRC, ComposedDefInSrcReg1);
    if (SrcRC != SrcWithSubRC)
      return ValueTrackerResult();

    return ValueTrackerResult(RegSeqInput.Reg, ComposedDefInSrcReg1);
  }

  // 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");
  assert(!Def->getOperand(DefIdx).getSubReg() && "no subreg defs in SSA");

  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->getSubRegIndexLaneMask(DefSubReg) &
       TRI->getSubRegIndexLaneMask(InsertedReg.SubIdx))
          .any())
    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();

  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;

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