//===- ARMLoadStoreOptimizer.cpp - ARM load / store opt. pass -------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
/// \file This file contains a pass that performs load / store related peephole
/// optimizations. This pass should be run after register allocation.
//
//===----------------------------------------------------------------------===//

#include "ARM.h"
#include "ARMBaseInstrInfo.h"
#include "ARMBaseRegisterInfo.h"
#include "ARMISelLowering.h"
#include "ARMMachineFunctionInfo.h"
#include "ARMSubtarget.h"
#include "MCTargetDesc/ARMAddressingModes.h"
#include "MCTargetDesc/ARMBaseInfo.h"
#include "Utils/ARMBaseInfo.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/DenseSet.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SetVector.h"
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/ADT/SmallSet.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/Statistic.h"
#include "llvm/ADT/iterator_range.h"
#include "llvm/Analysis/AliasAnalysis.h"
#include "llvm/CodeGen/LiveRegUnits.h"
#include "llvm/CodeGen/MachineBasicBlock.h"
#include "llvm/CodeGen/MachineDominators.h"
#include "llvm/CodeGen/MachineFrameInfo.h"
#include "llvm/CodeGen/MachineFunction.h"
#include "llvm/CodeGen/MachineFunctionPass.h"
#include "llvm/CodeGen/MachineInstr.h"
#include "llvm/CodeGen/MachineInstrBuilder.h"
#include "llvm/CodeGen/MachineMemOperand.h"
#include "llvm/CodeGen/MachineOperand.h"
#include "llvm/CodeGen/MachineRegisterInfo.h"
#include "llvm/CodeGen/RegisterClassInfo.h"
#include "llvm/CodeGen/TargetFrameLowering.h"
#include "llvm/CodeGen/TargetInstrInfo.h"
#include "llvm/CodeGen/TargetLowering.h"
#include "llvm/CodeGen/TargetRegisterInfo.h"
#include "llvm/CodeGen/TargetSubtargetInfo.h"
#include "llvm/IR/DataLayout.h"
#include "llvm/IR/DebugLoc.h"
#include "llvm/IR/Function.h"
#include "llvm/IR/Type.h"
#include "llvm/InitializePasses.h"
#include "llvm/MC/MCInstrDesc.h"
#include "llvm/Pass.h"
#include "llvm/Support/Allocator.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/raw_ostream.h"
#include <cassert>
#include <cstddef>
#include <cstdlib>
#include <iterator>
#include <limits>
#include <utility>

using namespace llvm;

#define DEBUG_TYPE "arm-ldst-opt"

STATISTIC(NumLDMGened , "Number of ldm instructions generated");
STATISTIC(NumSTMGened , "Number of stm instructions generated");
STATISTIC(NumVLDMGened, "Number of vldm instructions generated");
STATISTIC(NumVSTMGened, "Number of vstm instructions generated");
STATISTIC(NumLdStMoved, "Number of load / store instructions moved");
STATISTIC(NumLDRDFormed,"Number of ldrd created before allocation");
STATISTIC(NumSTRDFormed,"Number of strd created before allocation");
STATISTIC(NumLDRD2LDM,  "Number of ldrd instructions turned back into ldm");
STATISTIC(NumSTRD2STM,  "Number of strd instructions turned back into stm");
STATISTIC(NumLDRD2LDR,  "Number of ldrd instructions turned back into ldr's");
STATISTIC(NumSTRD2STR,  "Number of strd instructions turned back into str's");

/// This switch disables formation of double/multi instructions that could
/// potentially lead to (new) alignment traps even with CCR.UNALIGN_TRP
/// disabled. This can be used to create libraries that are robust even when
/// users provoke undefined behaviour by supplying misaligned pointers.
/// \see mayCombineMisaligned()
static cl::opt<bool>
AssumeMisalignedLoadStores("arm-assume-misaligned-load-store", cl::Hidden,
    cl::init(false), cl::desc("Be more conservative in ARM load/store opt"));

#define ARM_LOAD_STORE_OPT_NAME "ARM load / store optimization pass"

namespace {

/// Post- register allocation pass the combine load / store instructions to
/// form ldm / stm instructions.
struct ARMLoadStoreOpt {
  const MachineFunction *MF;
  const TargetInstrInfo *TII;
  const TargetRegisterInfo *TRI;
  const ARMSubtarget *STI;
  const TargetLowering *TL;
  ARMFunctionInfo *AFI;
  LiveRegUnits LiveRegs;
  const RegisterClassInfo *RCI = nullptr;
  MachineBasicBlock::const_iterator LiveRegPos;
  bool LiveRegsValid;
  bool isThumb1, isThumb2;

  bool runOnMachineFunction(MachineFunction &Fn,
                            const RegisterClassInfo &RegClassInfo);

private:
  /// A set of load/store MachineInstrs with same base register sorted by
  /// offset.
  struct MemOpQueueEntry {
    MachineInstr *MI;
    int Offset;        ///< Load/Store offset.
    unsigned Position; ///< Position as counted from end of basic block.

    MemOpQueueEntry(MachineInstr &MI, int Offset, unsigned Position)
        : MI(&MI), Offset(Offset), Position(Position) {}
  };
  using MemOpQueue = SmallVector<MemOpQueueEntry, 8>;

  /// A set of MachineInstrs that fulfill (nearly all) conditions to get
  /// merged into a LDM/STM.
  struct MergeCandidate {
    /// List of instructions ordered by load/store offset.
    SmallVector<MachineInstr *, 4> Instrs;

    /// Index in Instrs of the instruction being latest in the schedule.
    unsigned LatestMIIdx;

    /// Index in Instrs of the instruction being earliest in the schedule.
    unsigned EarliestMIIdx;

    /// Index into the basic block where the merged instruction will be
    /// inserted. (See MemOpQueueEntry.Position)
    unsigned InsertPos;

    /// Whether the instructions can be merged into a ldm/stm instruction.
    bool CanMergeToLSMulti;

    /// Whether the instructions can be merged into a ldrd/strd instruction.
    bool CanMergeToLSDouble;
  };
  SpecificBumpPtrAllocator<MergeCandidate> Allocator;
  SmallVector<const MergeCandidate *, 4> Candidates;
  SmallVector<MachineInstr *, 4> MergeBaseCandidates;

  MachineBasicBlock::iterator eraseInstr(MachineBasicBlock::iterator MI);

  void moveLiveRegsBefore(const MachineBasicBlock &MBB,
                          MachineBasicBlock::const_iterator Before);
  unsigned findFreeReg(const TargetRegisterClass &RegClass);
  void UpdateBaseRegUses(MachineBasicBlock &MBB,
                         MachineBasicBlock::iterator MBBI, const DebugLoc &DL,
                         unsigned Base, unsigned WordOffset,
                         ARMCC::CondCodes Pred, unsigned PredReg);
  MachineInstr *CreateLoadStoreMulti(MachineBasicBlock &MBB,
                                     MachineBasicBlock::iterator InsertBefore,
                                     int Offset, unsigned Base, bool BaseKill,
                                     unsigned Opcode, ARMCC::CondCodes Pred,
                                     unsigned PredReg, const DebugLoc &DL,
                                     ArrayRef<std::pair<unsigned, bool>> Regs,
                                     ArrayRef<MachineInstr *> Instrs);
  MachineInstr *CreateLoadStoreDouble(MachineBasicBlock &MBB,
                                      MachineBasicBlock::iterator InsertBefore,
                                      int Offset, unsigned Base, bool BaseKill,
                                      unsigned Opcode, ARMCC::CondCodes Pred,
                                      unsigned PredReg, const DebugLoc &DL,
                                      ArrayRef<std::pair<unsigned, bool>> Regs,
                                      ArrayRef<MachineInstr *> Instrs) const;
  void FormCandidates(const MemOpQueue &MemOps);
  MachineInstr *MergeOpsUpdate(const MergeCandidate &Cand);
  bool FixInvalidRegPairOp(MachineBasicBlock &MBB,
                           MachineBasicBlock::iterator &MBBI);
  bool MergeBaseUpdateLoadStore(MachineInstr *MI);
  bool MergeBaseUpdateLSMultiple(MachineInstr *MI);
  bool MergeBaseUpdateLSDouble(MachineInstr &MI);
  bool LoadStoreMultipleOpti(MachineBasicBlock &MBB);
  bool MergeReturnIntoLDM(MachineBasicBlock &MBB);
  bool CombineMovBx(MachineBasicBlock &MBB);
};

struct ARMLoadStoreOptLegacy : public MachineFunctionPass {
  static char ID;

  ARMLoadStoreOptLegacy() : MachineFunctionPass(ID) {}

  bool runOnMachineFunction(MachineFunction &Fn) override;

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

  StringRef getPassName() const override { return ARM_LOAD_STORE_OPT_NAME; }

  void getAnalysisUsage(AnalysisUsage &AU) const override {
    AU.addRequired<MachineRegisterClassInfoWrapperPass>();
    AU.addPreserved<MachineRegisterClassInfoWrapperPass>();
    MachineFunctionPass::getAnalysisUsage(AU);
  }
};

char ARMLoadStoreOptLegacy::ID = 0;

} // end anonymous namespace

INITIALIZE_PASS_BEGIN(ARMLoadStoreOptLegacy, "arm-ldst-opt",
                      ARM_LOAD_STORE_OPT_NAME, false, false)
INITIALIZE_PASS_DEPENDENCY(MachineRegisterClassInfoWrapperPass)
INITIALIZE_PASS_END(ARMLoadStoreOptLegacy, "arm-ldst-opt",
                    ARM_LOAD_STORE_OPT_NAME, false, false)

static bool definesCPSR(const MachineInstr &MI) {
  for (const auto &MO : MI.operands()) {
    if (!MO.isReg())
      continue;
    if (MO.isDef() && MO.getReg() == ARM::CPSR && !MO.isDead())
      // If the instruction has live CPSR def, then it's not safe to fold it
      // into load / store.
      return true;
  }

  return false;
}

static int getMemoryOpOffset(const MachineInstr &MI) {
  unsigned Opcode = MI.getOpcode();
  bool isAM3 = Opcode == ARM::LDRD || Opcode == ARM::STRD;
  unsigned NumOperands = MI.getDesc().getNumOperands();
  unsigned OffField = MI.getOperand(NumOperands - 3).getImm();

  if (Opcode == ARM::t2LDRi12 || Opcode == ARM::t2LDRi8 ||
      Opcode == ARM::t2STRi12 || Opcode == ARM::t2STRi8 ||
      Opcode == ARM::t2LDRDi8 || Opcode == ARM::t2STRDi8 ||
      Opcode == ARM::LDRi12   || Opcode == ARM::STRi12)
    return OffField;

  // Thumb1 immediate offsets are scaled by 4
  if (Opcode == ARM::tLDRi || Opcode == ARM::tSTRi ||
      Opcode == ARM::tLDRspi || Opcode == ARM::tSTRspi)
    return OffField * 4;

  int Offset = isAM3 ? ARM_AM::getAM3Offset(OffField)
    : ARM_AM::getAM5Offset(OffField) * 4;
  ARM_AM::AddrOpc Op = isAM3 ? ARM_AM::getAM3Op(OffField)
    : ARM_AM::getAM5Op(OffField);

  if (Op == ARM_AM::sub)
    return -Offset;

  return Offset;
}

static const MachineOperand &getLoadStoreBaseOp(const MachineInstr &MI) {
  return MI.getOperand(1);
}

static const MachineOperand &getLoadStoreRegOp(const MachineInstr &MI) {
  return MI.getOperand(0);
}

static int getLoadStoreMultipleOpcode(unsigned Opcode, ARM_AM::AMSubMode Mode) {
  switch (Opcode) {
  default: llvm_unreachable("Unhandled opcode!");
  case ARM::LDRi12:
    ++NumLDMGened;
    switch (Mode) {
    default: llvm_unreachable("Unhandled submode!");
    case ARM_AM::ia: return ARM::LDMIA;
    case ARM_AM::da: return ARM::LDMDA;
    case ARM_AM::db: return ARM::LDMDB;
    case ARM_AM::ib: return ARM::LDMIB;
    }
  case ARM::STRi12:
    ++NumSTMGened;
    switch (Mode) {
    default: llvm_unreachable("Unhandled submode!");
    case ARM_AM::ia: return ARM::STMIA;
    case ARM_AM::da: return ARM::STMDA;
    case ARM_AM::db: return ARM::STMDB;
    case ARM_AM::ib: return ARM::STMIB;
    }
  case ARM::tLDRi:
  case ARM::tLDRspi:
    // tLDMIA is writeback-only - unless the base register is in the input
    // reglist.
    ++NumLDMGened;
    switch (Mode) {
    default: llvm_unreachable("Unhandled submode!");
    case ARM_AM::ia: return ARM::tLDMIA;
    }
  case ARM::tSTRi:
  case ARM::tSTRspi:
    // There is no non-writeback tSTMIA either.
    ++NumSTMGened;
    switch (Mode) {
    default: llvm_unreachable("Unhandled submode!");
    case ARM_AM::ia: return ARM::tSTMIA_UPD;
    }
  case ARM::t2LDRi8:
  case ARM::t2LDRi12:
    ++NumLDMGened;
    switch (Mode) {
    default: llvm_unreachable("Unhandled submode!");
    case ARM_AM::ia: return ARM::t2LDMIA;
    case ARM_AM::db: return ARM::t2LDMDB;
    }
  case ARM::t2STRi8:
  case ARM::t2STRi12:
    ++NumSTMGened;
    switch (Mode) {
    default: llvm_unreachable("Unhandled submode!");
    case ARM_AM::ia: return ARM::t2STMIA;
    case ARM_AM::db: return ARM::t2STMDB;
    }
  case ARM::VLDRS:
    ++NumVLDMGened;
    switch (Mode) {
    default: llvm_unreachable("Unhandled submode!");
    case ARM_AM::ia: return ARM::VLDMSIA;
    case ARM_AM::db: return 0; // Only VLDMSDB_UPD exists.
    }
  case ARM::VSTRS:
    ++NumVSTMGened;
    switch (Mode) {
    default: llvm_unreachable("Unhandled submode!");
    case ARM_AM::ia: return ARM::VSTMSIA;
    case ARM_AM::db: return 0; // Only VSTMSDB_UPD exists.
    }
  case ARM::VLDRD:
    ++NumVLDMGened;
    switch (Mode) {
    default: llvm_unreachable("Unhandled submode!");
    case ARM_AM::ia: return ARM::VLDMDIA;
    case ARM_AM::db: return 0; // Only VLDMDDB_UPD exists.
    }
  case ARM::VSTRD:
    ++NumVSTMGened;
    switch (Mode) {
    default: llvm_unreachable("Unhandled submode!");
    case ARM_AM::ia: return ARM::VSTMDIA;
    case ARM_AM::db: return 0; // Only VSTMDDB_UPD exists.
    }
  }
}

static ARM_AM::AMSubMode getLoadStoreMultipleSubMode(unsigned Opcode) {
  switch (Opcode) {
  default: llvm_unreachable("Unhandled opcode!");
  case ARM::LDMIA_RET:
  case ARM::LDMIA:
  case ARM::LDMIA_UPD:
  case ARM::STMIA:
  case ARM::STMIA_UPD:
  case ARM::tLDMIA:
  case ARM::tLDMIA_UPD:
  case ARM::tSTMIA_UPD:
  case ARM::t2LDMIA_RET:
  case ARM::t2LDMIA:
  case ARM::t2LDMIA_UPD:
  case ARM::t2STMIA:
  case ARM::t2STMIA_UPD:
  case ARM::VLDMSIA:
  case ARM::VLDMSIA_UPD:
  case ARM::VSTMSIA:
  case ARM::VSTMSIA_UPD:
  case ARM::VLDMDIA:
  case ARM::VLDMDIA_UPD:
  case ARM::VSTMDIA:
  case ARM::VSTMDIA_UPD:
    return ARM_AM::ia;

  case ARM::LDMDA:
  case ARM::LDMDA_UPD:
  case ARM::STMDA:
  case ARM::STMDA_UPD:
    return ARM_AM::da;

  case ARM::LDMDB:
  case ARM::LDMDB_UPD:
  case ARM::STMDB:
  case ARM::STMDB_UPD:
  case ARM::t2LDMDB:
  case ARM::t2LDMDB_UPD:
  case ARM::t2STMDB:
  case ARM::t2STMDB_UPD:
  case ARM::VLDMSDB_UPD:
  case ARM::VSTMSDB_UPD:
  case ARM::VLDMDDB_UPD:
  case ARM::VSTMDDB_UPD:
    return ARM_AM::db;

  case ARM::LDMIB:
  case ARM::LDMIB_UPD:
  case ARM::STMIB:
  case ARM::STMIB_UPD:
    return ARM_AM::ib;
  }
}

static bool isT1i32Load(unsigned Opc) {
  return Opc == ARM::tLDRi || Opc == ARM::tLDRspi;
}

static bool isT2i32Load(unsigned Opc) {
  return Opc == ARM::t2LDRi12 || Opc == ARM::t2LDRi8;
}

static bool isi32Load(unsigned Opc) {
  return Opc == ARM::LDRi12 || isT1i32Load(Opc) || isT2i32Load(Opc) ;
}

static bool isT1i32Store(unsigned Opc) {
  return Opc == ARM::tSTRi || Opc == ARM::tSTRspi;
}

static bool isT2i32Store(unsigned Opc) {
  return Opc == ARM::t2STRi12 || Opc == ARM::t2STRi8;
}

static bool isi32Store(unsigned Opc) {
  return Opc == ARM::STRi12 || isT1i32Store(Opc) || isT2i32Store(Opc);
}

static bool isLoadSingle(unsigned Opc) {
  return isi32Load(Opc) || Opc == ARM::VLDRS || Opc == ARM::VLDRD;
}

static unsigned getImmScale(unsigned Opc) {
  switch (Opc) {
  default: llvm_unreachable("Unhandled opcode!");
  case ARM::tLDRi:
  case ARM::tSTRi:
  case ARM::tLDRspi:
  case ARM::tSTRspi:
    return 1;
  case ARM::tLDRHi:
  case ARM::tSTRHi:
    return 2;
  case ARM::tLDRBi:
  case ARM::tSTRBi:
    return 4;
  }
}

static unsigned getLSMultipleTransferSize(const MachineInstr *MI) {
  switch (MI->getOpcode()) {
  default: return 0;
  case ARM::LDRi12:
  case ARM::STRi12:
  case ARM::tLDRi:
  case ARM::tSTRi:
  case ARM::tLDRspi:
  case ARM::tSTRspi:
  case ARM::t2LDRi8:
  case ARM::t2LDRi12:
  case ARM::t2STRi8:
  case ARM::t2STRi12:
  case ARM::VLDRS:
  case ARM::VSTRS:
    return 4;
  case ARM::VLDRD:
  case ARM::VSTRD:
    return 8;
  case ARM::LDMIA:
  case ARM::LDMDA:
  case ARM::LDMDB:
  case ARM::LDMIB:
  case ARM::STMIA:
  case ARM::STMDA:
  case ARM::STMDB:
  case ARM::STMIB:
  case ARM::tLDMIA:
  case ARM::tLDMIA_UPD:
  case ARM::tSTMIA_UPD:
  case ARM::t2LDMIA:
  case ARM::t2LDMDB:
  case ARM::t2STMIA:
  case ARM::t2STMDB:
  case ARM::VLDMSIA:
  case ARM::VSTMSIA:
    return (MI->getNumOperands() - MI->getDesc().getNumOperands() + 1) * 4;
  case ARM::VLDMDIA:
  case ARM::VSTMDIA:
    return (MI->getNumOperands() - MI->getDesc().getNumOperands() + 1) * 8;
  }
}

/// Update future uses of the base register with the offset introduced
/// due to writeback. This function only works on Thumb1.
void ARMLoadStoreOpt::UpdateBaseRegUses(MachineBasicBlock &MBB,
                                        MachineBasicBlock::iterator MBBI,
                                        const DebugLoc &DL, unsigned Base,
                                        unsigned WordOffset,
                                        ARMCC::CondCodes Pred,
                                        unsigned PredReg) {
  assert(isThumb1 && "Can only update base register uses for Thumb1!");
  // Start updating any instructions with immediate offsets. Insert a SUB before
  // the first non-updateable instruction (if any).
  for (; MBBI != MBB.end(); ++MBBI) {
    bool InsertSub = false;
    unsigned Opc = MBBI->getOpcode();

    if (MBBI->readsRegister(Base, /*TRI=*/nullptr)) {
      int Offset;
      bool IsLoad =
        Opc == ARM::tLDRi || Opc == ARM::tLDRHi || Opc == ARM::tLDRBi;
      bool IsStore =
        Opc == ARM::tSTRi || Opc == ARM::tSTRHi || Opc == ARM::tSTRBi;

      if (IsLoad || IsStore) {
        // Loads and stores with immediate offsets can be updated, but only if
        // the new offset isn't negative.
        // The MachineOperand containing the offset immediate is the last one
        // before predicates.
        MachineOperand &MO =
          MBBI->getOperand(MBBI->getDesc().getNumOperands() - 3);
        // The offsets are scaled by 1, 2 or 4 depending on the Opcode.
        Offset = MO.getImm() - WordOffset * getImmScale(Opc);

        // If storing the base register, it needs to be reset first.
        Register InstrSrcReg = getLoadStoreRegOp(*MBBI).getReg();

        if (Offset >= 0 && !(IsStore && InstrSrcReg == Base))
          MO.setImm(Offset);
        else
          InsertSub = true;
      } else if ((Opc == ARM::tSUBi8 || Opc == ARM::tADDi8) &&
                 !definesCPSR(*MBBI)) {
        // SUBS/ADDS using this register, with a dead def of the CPSR.
        // Merge it with the update; if the merged offset is too large,
        // insert a new sub instead.
        MachineOperand &MO =
          MBBI->getOperand(MBBI->getDesc().getNumOperands() - 3);
        Offset = (Opc == ARM::tSUBi8) ?
          MO.getImm() + WordOffset * 4 :
          MO.getImm() - WordOffset * 4 ;
        if (Offset >= 0 && TL->isLegalAddImmediate(Offset)) {
          // FIXME: Swap ADDS<->SUBS if Offset < 0, erase instruction if
          // Offset == 0.
          MO.setImm(Offset);
          // The base register has now been reset, so exit early.
          return;
        } else {
          InsertSub = true;
        }
      } else {
        // Can't update the instruction.
        InsertSub = true;
      }
    } else if (definesCPSR(*MBBI) || MBBI->isCall() || MBBI->isBranch()) {
      // Since SUBS sets the condition flags, we can't place the base reset
      // after an instruction that has a live CPSR def.
      // The base register might also contain an argument for a function call.
      InsertSub = true;
    }

    if (InsertSub) {
      // An instruction above couldn't be updated, so insert a sub.
      BuildMI(MBB, MBBI, DL, TII->get(ARM::tSUBi8), Base)
          .add(t1CondCodeOp(true))
          .addReg(Base)
          .addImm(WordOffset * 4)
          .addImm(Pred)
          .addReg(PredReg);
      return;
    }

    if (MBBI->killsRegister(Base, /*TRI=*/nullptr) ||
        MBBI->definesRegister(Base, /*TRI=*/nullptr))
      // Register got killed. Stop updating.
      return;
  }

  // End of block was reached.
  if (!MBB.succ_empty()) {
    // FIXME: Because of a bug, live registers are sometimes missing from
    // the successor blocks' live-in sets. This means we can't trust that
    // information and *always* have to reset at the end of a block.
    // See PR21029.
    if (MBBI != MBB.end()) --MBBI;
    BuildMI(MBB, MBBI, DL, TII->get(ARM::tSUBi8), Base)
        .add(t1CondCodeOp(true))
        .addReg(Base)
        .addImm(WordOffset * 4)
        .addImm(Pred)
        .addReg(PredReg);
  }
}

MachineBasicBlock::iterator
ARMLoadStoreOpt::eraseInstr(MachineBasicBlock::iterator MI) {
  if (LiveRegsValid && LiveRegPos == MI)
    LiveRegsValid = false;
  return MI->eraseFromParent();
}

/// Return the first register of class \p RegClass that is not in \p Regs.
unsigned ARMLoadStoreOpt::findFreeReg(const TargetRegisterClass &RegClass) {
  for (unsigned Reg : RCI->getOrder(&RegClass))
    if (LiveRegs.available(Reg))
      return Reg;
  return 0;
}

/// Compute live registers just before instruction \p Before (in normal schedule
/// direction). Computes backwards so multiple queries in the same block must
/// come in reverse order.
void ARMLoadStoreOpt::moveLiveRegsBefore(const MachineBasicBlock &MBB,
    MachineBasicBlock::const_iterator Before) {
  // Initialize if we never queried in this block.
  if (!LiveRegsValid) {
    LiveRegs.init(*TRI);
    LiveRegs.addLiveOuts(MBB);
    LiveRegPos = MBB.end();
    LiveRegsValid = true;
  }
  // Move backward just before the "Before" position.
  while (LiveRegPos != Before) {
    --LiveRegPos;
    if (!LiveRegPos->isDebugInstr())
      LiveRegs.stepBackward(*LiveRegPos);
  }
}

static bool ContainsReg(ArrayRef<std::pair<unsigned, bool>> Regs,
                        unsigned Reg) {
  for (const std::pair<unsigned, bool> &R : Regs)
    if (R.first == Reg)
      return true;
  return false;
}

/// Create and insert a LDM or STM with Base as base register and registers in
/// Regs as the register operands that would be loaded / stored.  It returns
/// true if the transformation is done.
MachineInstr *ARMLoadStoreOpt::CreateLoadStoreMulti(
    MachineBasicBlock &MBB, MachineBasicBlock::iterator InsertBefore,
    int Offset, unsigned Base, bool BaseKill, unsigned Opcode,
    ARMCC::CondCodes Pred, unsigned PredReg, const DebugLoc &DL,
    ArrayRef<std::pair<unsigned, bool>> Regs,
    ArrayRef<MachineInstr*> Instrs) {
  unsigned NumRegs = Regs.size();
  assert(NumRegs > 1);

  // For Thumb1 targets, it might be necessary to clobber the CPSR to merge.
  // Compute liveness information for that register to make the decision.
  bool SafeToClobberCPSR = !isThumb1 ||
    (MBB.computeRegisterLiveness(TRI, ARM::CPSR, InsertBefore, 20) ==
     MachineBasicBlock::LQR_Dead);

  bool Writeback = isThumb1; // Thumb1 LDM/STM have base reg writeback.

  // Exception: If the base register is in the input reglist, Thumb1 LDM is
  // non-writeback.
  // It's also not possible to merge an STR of the base register in Thumb1.
  if (isThumb1 && ContainsReg(Regs, Base)) {
    assert(Base != ARM::SP && "Thumb1 does not allow SP in register list");
    if (Opcode == ARM::tLDRi)
      Writeback = false;
    else if (Opcode == ARM::tSTRi)
      return nullptr;
  }

  ARM_AM::AMSubMode Mode = ARM_AM::ia;
  // VFP and Thumb2 do not support IB or DA modes. Thumb1 only supports IA.
  bool isNotVFP = isi32Load(Opcode) || isi32Store(Opcode);
  bool haveIBAndDA = isNotVFP && !isThumb2 && !isThumb1;

  if (Offset == 4 && haveIBAndDA) {
    Mode = ARM_AM::ib;
  } else if (Offset == -4 * (int)NumRegs + 4 && haveIBAndDA) {
    Mode = ARM_AM::da;
  } else if (Offset == -4 * (int)NumRegs && isNotVFP && !isThumb1) {
    // VLDM/VSTM do not support DB mode without also updating the base reg.
    Mode = ARM_AM::db;
  } else if (Offset != 0 || Opcode == ARM::tLDRspi || Opcode == ARM::tSTRspi) {
    // Check if this is a supported opcode before inserting instructions to
    // calculate a new base register.
    if (!getLoadStoreMultipleOpcode(Opcode, Mode)) return nullptr;

    // If starting offset isn't zero, insert a MI to materialize a new base.
    // But only do so if it is cost effective, i.e. merging more than two
    // loads / stores.
    if (NumRegs <= 2)
      return nullptr;

    // On Thumb1, it's not worth materializing a new base register without
    // clobbering the CPSR (i.e. not using ADDS/SUBS).
    if (!SafeToClobberCPSR)
      return nullptr;

    unsigned NewBase;
    if (isi32Load(Opcode)) {
      // If it is a load, then just use one of the destination registers
      // as the new base. Will no longer be writeback in Thumb1.
      NewBase = Regs[NumRegs-1].first;
      Writeback = false;
    } else {
      // Find a free register that we can use as scratch register.
      moveLiveRegsBefore(MBB, InsertBefore);
      // The merged instruction does not exist yet but will use several Regs if
      // it is a Store.
      if (!isLoadSingle(Opcode))
        for (const std::pair<unsigned, bool> &R : Regs)
          LiveRegs.addReg(R.first);

      NewBase = findFreeReg(isThumb1 ? ARM::tGPRRegClass : ARM::GPRRegClass);
      if (NewBase == 0)
        return nullptr;
    }

    int BaseOpc = isThumb2 ? (BaseKill && Base == ARM::SP ? ARM::t2ADDspImm
                                                          : ARM::t2ADDri)
                           : (isThumb1 && Base == ARM::SP)
                                 ? ARM::tADDrSPi
                                 : (isThumb1 && Offset < 8)
                                       ? ARM::tADDi3
                                       : isThumb1 ? ARM::tADDi8 : ARM::ADDri;

    if (Offset < 0) {
      // FIXME: There are no Thumb1 load/store instructions with negative
      // offsets. So the Base != ARM::SP might be unnecessary.
      Offset = -Offset;
      BaseOpc = isThumb2 ? (BaseKill && Base == ARM::SP ? ARM::t2SUBspImm
                                                        : ARM::t2SUBri)
                         : (isThumb1 && Offset < 8 && Base != ARM::SP)
                               ? ARM::tSUBi3
                               : isThumb1 ? ARM::tSUBi8 : ARM::SUBri;
    }

    if (!TL->isLegalAddImmediate(Offset))
      // FIXME: Try add with register operand?
      return nullptr; // Probably not worth it then.

    // We can only append a kill flag to the add/sub input if the value is not
    // used in the register list of the stm as well.
    bool KillOldBase = BaseKill &&
      (!isi32Store(Opcode) || !ContainsReg(Regs, Base));

    if (isThumb1) {
      // Thumb1: depending on immediate size, use either
      //   ADDS NewBase, Base, #imm3
      // or
      //   MOV  NewBase, Base
      //   ADDS NewBase, #imm8.
      if (Base != NewBase &&
          (BaseOpc == ARM::tADDi8 || BaseOpc == ARM::tSUBi8)) {
        // Need to insert a MOV to the new base first.
        if (isARMLowRegister(NewBase) && isARMLowRegister(Base) &&
            !STI->hasV6Ops()) {
          // thumbv4t doesn't have lo->lo copies, and we can't predicate tMOVSr
          if (Pred != ARMCC::AL)
            return nullptr;
          BuildMI(MBB, InsertBefore, DL, TII->get(ARM::tMOVSr), NewBase)
            .addReg(Base, getKillRegState(KillOldBase));
        } else
          BuildMI(MBB, InsertBefore, DL, TII->get(ARM::tMOVr), NewBase)
              .addReg(Base, getKillRegState(KillOldBase))
              .add(predOps(Pred, PredReg));

        // The following ADDS/SUBS becomes an update.
        Base = NewBase;
        KillOldBase = true;
      }
      if (BaseOpc == ARM::tADDrSPi) {
        assert(Offset % 4 == 0 && "tADDrSPi offset is scaled by 4");
        BuildMI(MBB, InsertBefore, DL, TII->get(BaseOpc), NewBase)
            .addReg(Base, getKillRegState(KillOldBase))
            .addImm(Offset / 4)
            .add(predOps(Pred, PredReg));
      } else
        BuildMI(MBB, InsertBefore, DL, TII->get(BaseOpc), NewBase)
            .add(t1CondCodeOp(true))
            .addReg(Base, getKillRegState(KillOldBase))
            .addImm(Offset)
            .add(predOps(Pred, PredReg));
    } else {
      BuildMI(MBB, InsertBefore, DL, TII->get(BaseOpc), NewBase)
          .addReg(Base, getKillRegState(KillOldBase))
          .addImm(Offset)
          .add(predOps(Pred, PredReg))
          .add(condCodeOp());
    }
    Base = NewBase;
    BaseKill = true; // New base is always killed straight away.
  }

  bool isDef = isLoadSingle(Opcode);

  // Get LS multiple opcode. Note that for Thumb1 this might be an opcode with
  // base register writeback.
  Opcode = getLoadStoreMultipleOpcode(Opcode, Mode);
  if (!Opcode)
    return nullptr;

  // Check if a Thumb1 LDM/STM merge is safe. This is the case if:
  // - There is no writeback (LDM of base register),
  // - the base register is killed by the merged instruction,
  // - or it's safe to overwrite the condition flags, i.e. to insert a SUBS
  //   to reset the base register.
  // Otherwise, don't merge.
  // It's safe to return here since the code to materialize a new base register
  // above is also conditional on SafeToClobberCPSR.
  if (isThumb1 && !SafeToClobberCPSR && Writeback && !BaseKill)
    return nullptr;

  MachineInstrBuilder MIB;

  if (Writeback) {
    assert(isThumb1 && "expected Writeback only inThumb1");
    if (Opcode == ARM::tLDMIA) {
      assert(!(ContainsReg(Regs, Base)) && "Thumb1 can't LDM ! with Base in Regs");
      // Update tLDMIA with writeback if necessary.
      Opcode = ARM::tLDMIA_UPD;
    }

    MIB = BuildMI(MBB, InsertBefore, DL, TII->get(Opcode));

    // Thumb1: we might need to set base writeback when building the MI.
    MIB.addReg(Base, getDefRegState(true))
       .addReg(Base, getKillRegState(BaseKill));

    // The base isn't dead after a merged instruction with writeback.
    // Insert a sub instruction after the newly formed instruction to reset.
    if (!BaseKill)
      UpdateBaseRegUses(MBB, InsertBefore, DL, Base, NumRegs, Pred, PredReg);
  } else {
    // No writeback, simply build the MachineInstr.
    MIB = BuildMI(MBB, InsertBefore, DL, TII->get(Opcode));
    MIB.addReg(Base, getKillRegState(BaseKill));
  }

  MIB.addImm(Pred).addReg(PredReg);

  for (const std::pair<unsigned, bool> &R : Regs)
    MIB.addReg(R.first, getDefRegState(isDef) | getKillRegState(R.second));

  MIB.cloneMergedMemRefs(Instrs);

  return MIB.getInstr();
}

MachineInstr *ARMLoadStoreOpt::CreateLoadStoreDouble(
    MachineBasicBlock &MBB, MachineBasicBlock::iterator InsertBefore,
    int Offset, unsigned Base, bool BaseKill, unsigned Opcode,
    ARMCC::CondCodes Pred, unsigned PredReg, const DebugLoc &DL,
    ArrayRef<std::pair<unsigned, bool>> Regs,
    ArrayRef<MachineInstr*> Instrs) const {
  bool IsLoad = isi32Load(Opcode);
  assert((IsLoad || isi32Store(Opcode)) && "Must have integer load or store");
  unsigned LoadStoreOpcode = IsLoad ? ARM::t2LDRDi8 : ARM::t2STRDi8;

  assert(Regs.size() == 2);
  MachineInstrBuilder MIB = BuildMI(MBB, InsertBefore, DL,
                                    TII->get(LoadStoreOpcode));
  if (IsLoad) {
    MIB.addReg(Regs[0].first, RegState::Define)
       .addReg(Regs[1].first, RegState::Define);
  } else {
    MIB.addReg(Regs[0].first, getKillRegState(Regs[0].second))
       .addReg(Regs[1].first, getKillRegState(Regs[1].second));
  }
  MIB.addReg(Base).addImm(Offset).addImm(Pred).addReg(PredReg);
  MIB.cloneMergedMemRefs(Instrs);
  return MIB.getInstr();
}

/// Call MergeOps and update MemOps and merges accordingly on success.
MachineInstr *ARMLoadStoreOpt::MergeOpsUpdate(const MergeCandidate &Cand) {
  const MachineInstr *First = Cand.Instrs.front();
  unsigned Opcode = First->getOpcode();
  bool IsLoad = isLoadSingle(Opcode);
  SmallVector<std::pair<unsigned, bool>, 8> Regs;
  SmallVector<unsigned, 4> ImpDefs;
  DenseSet<unsigned> KilledRegs;
  DenseSet<unsigned> UsedRegs;
  // Determine list of registers and list of implicit super-register defs.
  for (const MachineInstr *MI : Cand.Instrs) {
    const MachineOperand &MO = getLoadStoreRegOp(*MI);
    Register Reg = MO.getReg();
    bool IsKill = MO.isKill();
    if (IsKill)
      KilledRegs.insert(Reg);
    Regs.push_back(std::make_pair(Reg, IsKill));
    UsedRegs.insert(Reg);

    if (IsLoad) {
      // Collect any implicit defs of super-registers, after merging we can't
      // be sure anymore that we properly preserved these live ranges and must
      // removed these implicit operands.
      for (const MachineOperand &MO : MI->implicit_operands()) {
        if (!MO.isReg() || !MO.isDef() || MO.isDead())
          continue;
        assert(MO.isImplicit());
        Register DefReg = MO.getReg();

        if (is_contained(ImpDefs, DefReg))
          continue;
        // We can ignore cases where the super-reg is read and written.
        if (MI->readsRegister(DefReg, /*TRI=*/nullptr))
          continue;
        ImpDefs.push_back(DefReg);
      }
    }
  }

  // Attempt the merge.
  using iterator = MachineBasicBlock::iterator;

  MachineInstr *LatestMI = Cand.Instrs[Cand.LatestMIIdx];
  iterator InsertBefore = std::next(iterator(LatestMI));
  MachineBasicBlock &MBB = *LatestMI->getParent();
  unsigned Offset = getMemoryOpOffset(*First);
  Register Base = getLoadStoreBaseOp(*First).getReg();
  bool BaseKill = LatestMI->killsRegister(Base, /*TRI=*/nullptr);
  Register PredReg;
  ARMCC::CondCodes Pred = getInstrPredicate(*First, PredReg);
  DebugLoc DL = First->getDebugLoc();
  MachineInstr *Merged = nullptr;
  if (Cand.CanMergeToLSDouble)
    Merged = CreateLoadStoreDouble(MBB, InsertBefore, Offset, Base, BaseKill,
                                   Opcode, Pred, PredReg, DL, Regs,
                                   Cand.Instrs);
  if (!Merged && Cand.CanMergeToLSMulti)
    Merged = CreateLoadStoreMulti(MBB, InsertBefore, Offset, Base, BaseKill,
                                  Opcode, Pred, PredReg, DL, Regs, Cand.Instrs);
  if (!Merged)
    return nullptr;

  // Determine earliest instruction that will get removed. We then keep an
  // iterator just above it so the following erases don't invalidated it.
  iterator EarliestI(Cand.Instrs[Cand.EarliestMIIdx]);
  bool EarliestAtBegin = false;
  if (EarliestI == MBB.begin()) {
    EarliestAtBegin = true;
  } else {
    EarliestI = std::prev(EarliestI);
  }

  // Remove instructions which have been merged.
  for (MachineInstr *MI : Cand.Instrs)
    eraseInstr(MI);

  // Determine range between the earliest removed instruction and the new one.
  if (EarliestAtBegin)
    EarliestI = MBB.begin();
  else
    EarliestI = std::next(EarliestI);
  auto FixupRange = make_range(EarliestI, iterator(Merged));

  if (isLoadSingle(Opcode)) {
    // If the previous loads defined a super-reg, then we have to mark earlier
    // operands undef; Replicate the super-reg def on the merged instruction.
    for (MachineInstr &MI : FixupRange) {
      for (unsigned &ImpDefReg : ImpDefs) {
        for (MachineOperand &MO : MI.implicit_operands()) {
          if (!MO.isReg() || MO.getReg() != ImpDefReg)
            continue;
          if (MO.readsReg())
            MO.setIsUndef();
          else if (MO.isDef())
            ImpDefReg = 0;
        }
      }
    }

    MachineInstrBuilder MIB(*Merged->getParent()->getParent(), Merged);
    for (unsigned ImpDef : ImpDefs)
      MIB.addReg(ImpDef, RegState::ImplicitDefine);
  } else {
    // Remove kill flags: We are possibly storing the values later now.
    assert(isi32Store(Opcode) || Opcode == ARM::VSTRS || Opcode == ARM::VSTRD);
    for (MachineInstr &MI : FixupRange) {
      for (MachineOperand &MO : MI.uses()) {
        if (!MO.isReg() || !MO.isKill())
          continue;
        if (UsedRegs.count(MO.getReg()))
          MO.setIsKill(false);
      }
    }
    assert(ImpDefs.empty());
  }

  return Merged;
}

static bool isValidLSDoubleOffset(int Offset) {
  unsigned Value = abs(Offset);
  // t2LDRDi8/t2STRDi8 supports an 8 bit immediate which is internally
  // multiplied by 4.
  return (Value % 4) == 0 && Value < 1024;
}

/// Return true for loads/stores that can be combined to a double/multi
/// operation without increasing the requirements for alignment.
static bool mayCombineMisaligned(const TargetSubtargetInfo &STI,
                                 const MachineInstr &MI) {
  // vldr/vstr trap on misaligned pointers anyway, forming vldm makes no
  // difference.
  unsigned Opcode = MI.getOpcode();
  if (!isi32Load(Opcode) && !isi32Store(Opcode))
    return true;

  // Stack pointer alignment is out of the programmers control so we can trust
  // SP-relative loads/stores.
  if (getLoadStoreBaseOp(MI).getReg() == ARM::SP &&
      STI.getFrameLowering()->getTransientStackAlign() >= Align(4))
    return true;
  return false;
}

/// Find candidates for load/store multiple merge in list of MemOpQueueEntries.
void ARMLoadStoreOpt::FormCandidates(const MemOpQueue &MemOps) {
  const MachineInstr *FirstMI = MemOps[0].MI;
  unsigned Opcode = FirstMI->getOpcode();
  bool isNotVFP = isi32Load(Opcode) || isi32Store(Opcode);
  unsigned Size = getLSMultipleTransferSize(FirstMI);

  unsigned SIndex = 0;
  unsigned EIndex = MemOps.size();
  do {
    // Look at the first instruction.
    const MachineInstr *MI = MemOps[SIndex].MI;
    int Offset = MemOps[SIndex].Offset;
    const MachineOperand &PMO = getLoadStoreRegOp(*MI);
    Register PReg = PMO.getReg();
    unsigned PRegNum = PMO.isUndef() ? std::numeric_limits<unsigned>::max()
                                     : TRI->getEncodingValue(PReg);
    unsigned Latest = SIndex;
    unsigned Earliest = SIndex;
    unsigned Count = 1;
    bool CanMergeToLSDouble =
      STI->isThumb2() && isNotVFP && isValidLSDoubleOffset(Offset);
    // ARM errata 602117: LDRD with base in list may result in incorrect base
    // register when interrupted or faulted.
    if (STI->isCortexM3() && isi32Load(Opcode) &&
        PReg == getLoadStoreBaseOp(*MI).getReg())
      CanMergeToLSDouble = false;

    bool CanMergeToLSMulti = true;
    // On swift vldm/vstm starting with an odd register number as that needs
    // more uops than single vldrs.
    if (STI->hasSlowOddRegister() && !isNotVFP && (PRegNum % 2) == 1)
      CanMergeToLSMulti = false;

    // LDRD/STRD do not allow SP/PC. LDM/STM do not support it or have it
    // deprecated; LDM to PC is fine but cannot happen here.
    if (PReg == ARM::SP || PReg == ARM::PC)
      CanMergeToLSMulti = CanMergeToLSDouble = false;

    // Should we be conservative?
    if (AssumeMisalignedLoadStores && !mayCombineMisaligned(*STI, *MI))
      CanMergeToLSMulti = CanMergeToLSDouble = false;

    // vldm / vstm limit are 32 for S variants, 16 for D variants.
    unsigned Limit;
    switch (Opcode) {
    default:
      Limit = UINT_MAX;
      break;
    case ARM::VLDRD:
    case ARM::VSTRD:
      Limit = 16;
      break;
    }

    // Merge following instructions where possible.
    for (unsigned I = SIndex+1; I < EIndex; ++I, ++Count) {
      int NewOffset = MemOps[I].Offset;
      if (NewOffset != Offset + (int)Size)
        break;
      const MachineOperand &MO = getLoadStoreRegOp(*MemOps[I].MI);
      Register Reg = MO.getReg();
      if (Reg == ARM::SP || Reg == ARM::PC)
        break;
      if (Count == Limit)
        break;

      // See if the current load/store may be part of a multi load/store.
      unsigned RegNum = MO.isUndef() ? std::numeric_limits<unsigned>::max()
                                     : TRI->getEncodingValue(Reg);
      bool PartOfLSMulti = CanMergeToLSMulti;
      if (PartOfLSMulti) {
        // Register numbers must be in ascending order.
        if (RegNum <= PRegNum)
          PartOfLSMulti = false;
        // For VFP / NEON load/store multiples, the registers must be
        // consecutive and within the limit on the number of registers per
        // instruction.
        else if (!isNotVFP && RegNum != PRegNum+1)
          PartOfLSMulti = false;
      }
      // See if the current load/store may be part of a double load/store.
      bool PartOfLSDouble = CanMergeToLSDouble && Count <= 1;

      if (!PartOfLSMulti && !PartOfLSDouble)
        break;
      CanMergeToLSMulti &= PartOfLSMulti;
      CanMergeToLSDouble &= PartOfLSDouble;
      // Track MemOp with latest and earliest position (Positions are
      // counted in reverse).
      unsigned Position = MemOps[I].Position;
      if (Position < MemOps[Latest].Position)
        Latest = I;
      else if (Position > MemOps[Earliest].Position)
        Earliest = I;
      // Prepare for next MemOp.
      Offset += Size;
      PRegNum = RegNum;
    }

    // Form a candidate from the Ops collected so far.
    MergeCandidate *Candidate = new(Allocator.Allocate()) MergeCandidate;
    for (unsigned C = SIndex, CE = SIndex + Count; C < CE; ++C)
      Candidate->Instrs.push_back(MemOps[C].MI);
    Candidate->LatestMIIdx = Latest - SIndex;
    Candidate->EarliestMIIdx = Earliest - SIndex;
    Candidate->InsertPos = MemOps[Latest].Position;
    if (Count == 1)
      CanMergeToLSMulti = CanMergeToLSDouble = false;
    Candidate->CanMergeToLSMulti = CanMergeToLSMulti;
    Candidate->CanMergeToLSDouble = CanMergeToLSDouble;
    Candidates.push_back(Candidate);
    // Continue after the chain.
    SIndex += Count;
  } while (SIndex < EIndex);
}

static unsigned getUpdatingLSMultipleOpcode(unsigned Opc,
                                            ARM_AM::AMSubMode Mode) {
  switch (Opc) {
  default: llvm_unreachable("Unhandled opcode!");
  case ARM::LDMIA:
  case ARM::LDMDA:
  case ARM::LDMDB:
  case ARM::LDMIB:
    switch (Mode) {
    default: llvm_unreachable("Unhandled submode!");
    case ARM_AM::ia: return ARM::LDMIA_UPD;
    case ARM_AM::ib: return ARM::LDMIB_UPD;
    case ARM_AM::da: return ARM::LDMDA_UPD;
    case ARM_AM::db: return ARM::LDMDB_UPD;
    }
  case ARM::STMIA:
  case ARM::STMDA:
  case ARM::STMDB:
  case ARM::STMIB:
    switch (Mode) {
    default: llvm_unreachable("Unhandled submode!");
    case ARM_AM::ia: return ARM::STMIA_UPD;
    case ARM_AM::ib: return ARM::STMIB_UPD;
    case ARM_AM::da: return ARM::STMDA_UPD;
    case ARM_AM::db: return ARM::STMDB_UPD;
    }
  case ARM::t2LDMIA:
  case ARM::t2LDMDB:
    switch (Mode) {
    default: llvm_unreachable("Unhandled submode!");
    case ARM_AM::ia: return ARM::t2LDMIA_UPD;
    case ARM_AM::db: return ARM::t2LDMDB_UPD;
    }
  case ARM::t2STMIA:
  case ARM::t2STMDB:
    switch (Mode) {
    default: llvm_unreachable("Unhandled submode!");
    case ARM_AM::ia: return ARM::t2STMIA_UPD;
    case ARM_AM::db: return ARM::t2STMDB_UPD;
    }
  case ARM::VLDMSIA:
    switch (Mode) {
    default: llvm_unreachable("Unhandled submode!");
    case ARM_AM::ia: return ARM::VLDMSIA_UPD;
    case ARM_AM::db: return ARM::VLDMSDB_UPD;
    }
  case ARM::VLDMDIA:
    switch (Mode) {
    default: llvm_unreachable("Unhandled submode!");
    case ARM_AM::ia: return ARM::VLDMDIA_UPD;
    case ARM_AM::db: return ARM::VLDMDDB_UPD;
    }
  case ARM::VSTMSIA:
    switch (Mode) {
    default: llvm_unreachable("Unhandled submode!");
    case ARM_AM::ia: return ARM::VSTMSIA_UPD;
    case ARM_AM::db: return ARM::VSTMSDB_UPD;
    }
  case ARM::VSTMDIA:
    switch (Mode) {
    default: llvm_unreachable("Unhandled submode!");
    case ARM_AM::ia: return ARM::VSTMDIA_UPD;
    case ARM_AM::db: return ARM::VSTMDDB_UPD;
    }
  }
}

/// Check if the given instruction increments or decrements a register and
/// return the amount it is incremented/decremented. Returns 0 if the CPSR flags
/// generated by the instruction are possibly read as well.
static int isIncrementOrDecrement(const MachineInstr &MI, Register Reg,
                                  ARMCC::CondCodes Pred, Register PredReg) {
  bool CheckCPSRDef;
  int Scale;
  switch (MI.getOpcode()) {
  case ARM::tADDi8:  Scale =  4; CheckCPSRDef = true; break;
  case ARM::tSUBi8:  Scale = -4; CheckCPSRDef = true; break;
  case ARM::t2SUBri:
  case ARM::t2SUBspImm:
  case ARM::SUBri:   Scale = -1; CheckCPSRDef = true; break;
  case ARM::t2ADDri:
  case ARM::t2ADDspImm:
  case ARM::ADDri:   Scale =  1; CheckCPSRDef = true; break;
  case ARM::tADDspi: Scale =  4; CheckCPSRDef = false; break;
  case ARM::tSUBspi: Scale = -4; CheckCPSRDef = false; break;
  default: return 0;
  }

  Register MIPredReg;
  if (MI.getOperand(0).getReg() != Reg ||
      MI.getOperand(1).getReg() != Reg ||
      getInstrPredicate(MI, MIPredReg) != Pred ||
      MIPredReg != PredReg)
    return 0;

  if (CheckCPSRDef && definesCPSR(MI))
    return 0;
  return MI.getOperand(2).getImm() * Scale;
}

/// Searches for an increment or decrement of \p Reg before \p MBBI.
static MachineBasicBlock::iterator
findIncDecBefore(MachineBasicBlock::iterator MBBI, Register Reg,
                 ARMCC::CondCodes Pred, Register PredReg, int &Offset) {
  Offset = 0;
  MachineBasicBlock &MBB = *MBBI->getParent();
  MachineBasicBlock::iterator BeginMBBI = MBB.begin();
  MachineBasicBlock::iterator EndMBBI = MBB.end();
  if (MBBI == BeginMBBI)
    return EndMBBI;

  // Skip debug values.
  MachineBasicBlock::iterator PrevMBBI = std::prev(MBBI);
  while (PrevMBBI->isDebugInstr() && PrevMBBI != BeginMBBI)
    --PrevMBBI;

  Offset = isIncrementOrDecrement(*PrevMBBI, Reg, Pred, PredReg);
  return Offset == 0 ? EndMBBI : PrevMBBI;
}

/// Searches for a increment or decrement of \p Reg after \p MBBI.
static MachineBasicBlock::iterator
findIncDecAfter(MachineBasicBlock::iterator MBBI, Register Reg,
                ARMCC::CondCodes Pred, Register PredReg, int &Offset,
                const TargetRegisterInfo *TRI) {
  Offset = 0;
  MachineBasicBlock &MBB = *MBBI->getParent();
  MachineBasicBlock::iterator EndMBBI = MBB.end();
  MachineBasicBlock::iterator NextMBBI = std::next(MBBI);
  while (NextMBBI != EndMBBI) {
    // Skip debug values.
    while (NextMBBI != EndMBBI && NextMBBI->isDebugInstr())
      ++NextMBBI;
    if (NextMBBI == EndMBBI)
      return EndMBBI;

    unsigned Off = isIncrementOrDecrement(*NextMBBI, Reg, Pred, PredReg);
    if (Off) {
      Offset = Off;
      return NextMBBI;
    }

    // SP can only be combined if it is the next instruction after the original
    // MBBI, otherwise we may be incrementing the stack pointer (invalidating
    // anything below the new pointer) when its frame elements are still in
    // use. Other registers can attempt to look further, until a different use
    // or def of the register is found.
    if (Reg == ARM::SP || NextMBBI->readsRegister(Reg, TRI) ||
        NextMBBI->definesRegister(Reg, TRI))
      return EndMBBI;

    ++NextMBBI;
  }
  return EndMBBI;
}

/// Fold proceeding/trailing inc/dec of base register into the
/// LDM/STM/VLDM{D|S}/VSTM{D|S} op when possible:
///
/// stmia rn, <ra, rb, rc>
/// rn := rn + 4 * 3;
/// =>
/// stmia rn!, <ra, rb, rc>
///
/// rn := rn - 4 * 3;
/// ldmia rn, <ra, rb, rc>
/// =>
/// ldmdb rn!, <ra, rb, rc>
bool ARMLoadStoreOpt::MergeBaseUpdateLSMultiple(MachineInstr *MI) {
  // Thumb1 is already using updating loads/stores.
  if (isThumb1) return false;
  LLVM_DEBUG(dbgs() << "Attempting to merge update of: " << *MI);

  const MachineOperand &BaseOP = MI->getOperand(0);
  Register Base = BaseOP.getReg();
  bool BaseKill = BaseOP.isKill();
  Register PredReg;
  ARMCC::CondCodes Pred = getInstrPredicate(*MI, PredReg);
  unsigned Opcode = MI->getOpcode();
  DebugLoc DL = MI->getDebugLoc();

  // Can't use an updating ld/st if the base register is also a dest
  // register. e.g. ldmdb r0!, {r0, r1, r2}. The behavior is undefined.
  for (const MachineOperand &MO : llvm::drop_begin(MI->operands(), 2))
    if (MO.getReg() == Base)
      return false;

  int Bytes = getLSMultipleTransferSize(MI);
  MachineBasicBlock &MBB = *MI->getParent();
  MachineBasicBlock::iterator MBBI(MI);
  int Offset;
  MachineBasicBlock::iterator MergeInstr
    = findIncDecBefore(MBBI, Base, Pred, PredReg, Offset);
  ARM_AM::AMSubMode Mode = getLoadStoreMultipleSubMode(Opcode);
  if (Mode == ARM_AM::ia && Offset == -Bytes) {
    Mode = ARM_AM::db;
  } else if (Mode == ARM_AM::ib && Offset == -Bytes) {
    Mode = ARM_AM::da;
  } else {
    MergeInstr = findIncDecAfter(MBBI, Base, Pred, PredReg, Offset, TRI);
    if (((Mode != ARM_AM::ia && Mode != ARM_AM::ib) || Offset != Bytes) &&
        ((Mode != ARM_AM::da && Mode != ARM_AM::db) || Offset != -Bytes)) {

      // We couldn't find an inc/dec to merge. But if the base is dead, we
      // can still change to a writeback form as that will save us 2 bytes
      // of code size. It can create WAW hazards though, so only do it if
      // we're minimizing code size.
      if (!STI->hasMinSize() || !BaseKill)
        return false;

      bool HighRegsUsed = false;
      for (const MachineOperand &MO : llvm::drop_begin(MI->operands(), 2))
        if (MO.getReg() >= ARM::R8) {
          HighRegsUsed = true;
          break;
        }

      if (!HighRegsUsed)
        MergeInstr = MBB.end();
      else
        return false;
    }
  }
  if (MergeInstr != MBB.end()) {
    LLVM_DEBUG(dbgs() << "  Erasing old increment: " << *MergeInstr);
    eraseInstr(MergeInstr);
  }

  unsigned NewOpc = getUpdatingLSMultipleOpcode(Opcode, Mode);
  MachineInstrBuilder MIB = BuildMI(MBB, MBBI, DL, TII->get(NewOpc))
    .addReg(Base, getDefRegState(true)) // WB base register
    .addReg(Base, getKillRegState(BaseKill))
    .addImm(Pred).addReg(PredReg);

  // Transfer the rest of operands.
  for (const MachineOperand &MO : llvm::drop_begin(MI->operands(), 3))
    MIB.add(MO);

  // Transfer memoperands.
  MIB.setMemRefs(MI->memoperands());

  LLVM_DEBUG(dbgs() << "  Added new load/store: " << *MIB);
  eraseInstr(MBBI);
  return true;
}

static unsigned getPreIndexedLoadStoreOpcode(unsigned Opc,
                                             ARM_AM::AddrOpc Mode) {
  switch (Opc) {
  case ARM::LDRi12:
    return ARM::LDR_PRE_IMM;
  case ARM::STRi12:
    return ARM::STR_PRE_IMM;
  case ARM::VLDRS:
    return Mode == ARM_AM::add ? ARM::VLDMSIA_UPD : ARM::VLDMSDB_UPD;
  case ARM::VLDRD:
    return Mode == ARM_AM::add ? ARM::VLDMDIA_UPD : ARM::VLDMDDB_UPD;
  case ARM::VSTRS:
    return Mode == ARM_AM::add ? ARM::VSTMSIA_UPD : ARM::VSTMSDB_UPD;
  case ARM::VSTRD:
    return Mode == ARM_AM::add ? ARM::VSTMDIA_UPD : ARM::VSTMDDB_UPD;
  case ARM::t2LDRi8:
  case ARM::t2LDRi12:
    return ARM::t2LDR_PRE;
  case ARM::t2STRi8:
  case ARM::t2STRi12:
    return ARM::t2STR_PRE;
  default: llvm_unreachable("Unhandled opcode!");
  }
}

static unsigned getPostIndexedLoadStoreOpcode(unsigned Opc,
                                              ARM_AM::AddrOpc Mode) {
  switch (Opc) {
  case ARM::LDRi12:
    return ARM::LDR_POST_IMM;
  case ARM::STRi12:
    return ARM::STR_POST_IMM;
  case ARM::VLDRS:
    return Mode == ARM_AM::add ? ARM::VLDMSIA_UPD : ARM::VLDMSDB_UPD;
  case ARM::VLDRD:
    return Mode == ARM_AM::add ? ARM::VLDMDIA_UPD : ARM::VLDMDDB_UPD;
  case ARM::VSTRS:
    return Mode == ARM_AM::add ? ARM::VSTMSIA_UPD : ARM::VSTMSDB_UPD;
  case ARM::VSTRD:
    return Mode == ARM_AM::add ? ARM::VSTMDIA_UPD : ARM::VSTMDDB_UPD;
  case ARM::t2LDRi8:
  case ARM::t2LDRi12:
    return ARM::t2LDR_POST;
  case ARM::t2LDRBi8:
  case ARM::t2LDRBi12:
    return ARM::t2LDRB_POST;
  case ARM::t2LDRSBi8:
  case ARM::t2LDRSBi12:
    return ARM::t2LDRSB_POST;
  case ARM::t2LDRHi8:
  case ARM::t2LDRHi12:
    return ARM::t2LDRH_POST;
  case ARM::t2LDRSHi8:
  case ARM::t2LDRSHi12:
    return ARM::t2LDRSH_POST;
  case ARM::t2STRi8:
  case ARM::t2STRi12:
    return ARM::t2STR_POST;
  case ARM::t2STRBi8:
  case ARM::t2STRBi12:
    return ARM::t2STRB_POST;
  case ARM::t2STRHi8:
  case ARM::t2STRHi12:
    return ARM::t2STRH_POST;

  case ARM::MVE_VLDRBS16:
    return ARM::MVE_VLDRBS16_post;
  case ARM::MVE_VLDRBS32:
    return ARM::MVE_VLDRBS32_post;
  case ARM::MVE_VLDRBU16:
    return ARM::MVE_VLDRBU16_post;
  case ARM::MVE_VLDRBU32:
    return ARM::MVE_VLDRBU32_post;
  case ARM::MVE_VLDRHS32:
    return ARM::MVE_VLDRHS32_post;
  case ARM::MVE_VLDRHU32:
    return ARM::MVE_VLDRHU32_post;
  case ARM::MVE_VLDRBU8:
    return ARM::MVE_VLDRBU8_post;
  case ARM::MVE_VLDRHU16:
    return ARM::MVE_VLDRHU16_post;
  case ARM::MVE_VLDRWU32:
    return ARM::MVE_VLDRWU32_post;
  case ARM::MVE_VSTRB16:
    return ARM::MVE_VSTRB16_post;
  case ARM::MVE_VSTRB32:
    return ARM::MVE_VSTRB32_post;
  case ARM::MVE_VSTRH32:
    return ARM::MVE_VSTRH32_post;
  case ARM::MVE_VSTRBU8:
    return ARM::MVE_VSTRBU8_post;
  case ARM::MVE_VSTRHU16:
    return ARM::MVE_VSTRHU16_post;
  case ARM::MVE_VSTRWU32:
    return ARM::MVE_VSTRWU32_post;

  default: llvm_unreachable("Unhandled opcode!");
  }
}

/// Fold proceeding/trailing inc/dec of base register into the
/// LDR/STR/FLD{D|S}/FST{D|S} op when possible:
bool ARMLoadStoreOpt::MergeBaseUpdateLoadStore(MachineInstr *MI) {
  // Thumb1 doesn't have updating LDR/STR.
  // FIXME: Use LDM/STM with single register instead.
  if (isThumb1) return false;
  LLVM_DEBUG(dbgs() << "Attempting to merge update of: " << *MI);

  Register Base = getLoadStoreBaseOp(*MI).getReg();
  bool BaseKill = getLoadStoreBaseOp(*MI).isKill();
  unsigned Opcode = MI->getOpcode();
  DebugLoc DL = MI->getDebugLoc();
  bool isAM5 = (Opcode == ARM::VLDRD || Opcode == ARM::VLDRS ||
                Opcode == ARM::VSTRD || Opcode == ARM::VSTRS);
  bool isAM2 = (Opcode == ARM::LDRi12 || Opcode == ARM::STRi12);
  if (isi32Load(Opcode) || isi32Store(Opcode))
    if (MI->getOperand(2).getImm() != 0)
      return false;
  if (isAM5 && ARM_AM::getAM5Offset(MI->getOperand(2).getImm()) != 0)
    return false;

  // Can't do the merge if the destination register is the same as the would-be
  // writeback register.
  if (MI->getOperand(0).getReg() == Base)
    return false;

  Register PredReg;
  ARMCC::CondCodes Pred = getInstrPredicate(*MI, PredReg);
  int Bytes = getLSMultipleTransferSize(MI);
  MachineBasicBlock &MBB = *MI->getParent();
  MachineBasicBlock::iterator MBBI(MI);
  int Offset;
  MachineBasicBlock::iterator MergeInstr
    = findIncDecBefore(MBBI, Base, Pred, PredReg, Offset);
  unsigned NewOpc;
  if (!isAM5 && Offset == Bytes) {
    NewOpc = getPreIndexedLoadStoreOpcode(Opcode, ARM_AM::add);
  } else if (Offset == -Bytes) {
    NewOpc = getPreIndexedLoadStoreOpcode(Opcode, ARM_AM::sub);
  } else {
    MergeInstr = findIncDecAfter(MBBI, Base, Pred, PredReg, Offset, TRI);
    if (MergeInstr == MBB.end())
      return false;

    NewOpc = getPostIndexedLoadStoreOpcode(Opcode, ARM_AM::add);
    if ((isAM5 && Offset != Bytes) ||
        (!isAM5 && !isLegalAddressImm(NewOpc, Offset, TII))) {
      NewOpc = getPostIndexedLoadStoreOpcode(Opcode, ARM_AM::sub);
      if (isAM5 || !isLegalAddressImm(NewOpc, Offset, TII))
        return false;
    }
  }
  LLVM_DEBUG(dbgs() << "  Erasing old increment: " << *MergeInstr);
  eraseInstr(MergeInstr);

  ARM_AM::AddrOpc AddSub = Offset < 0 ? ARM_AM::sub : ARM_AM::add;

  bool isLd = isLoadSingle(Opcode);
  if (isAM5) {
    // VLDM[SD]_UPD, VSTM[SD]_UPD
    // (There are no base-updating versions of VLDR/VSTR instructions, but the
    // updating load/store-multiple instructions can be used with only one
    // register.)
    MachineOperand &MO = MI->getOperand(0);
    auto MIB = BuildMI(MBB, MBBI, DL, TII->get(NewOpc))
                   .addReg(Base, getDefRegState(true)) // WB base register
                   .addReg(Base, getKillRegState(isLd ? BaseKill : false))
                   .addImm(Pred)
                   .addReg(PredReg)
                   .addReg(MO.getReg(), (isLd ? getDefRegState(true)
                                              : getKillRegState(MO.isKill())))
                   .cloneMemRefs(*MI);
    (void)MIB;
    LLVM_DEBUG(dbgs() << "  Added new instruction: " << *MIB);
  } else if (isLd) {
    if (isAM2) {
      // LDR_PRE, LDR_POST
      if (NewOpc == ARM::LDR_PRE_IMM || NewOpc == ARM::LDRB_PRE_IMM) {
        auto MIB =
            BuildMI(MBB, MBBI, DL, TII->get(NewOpc), MI->getOperand(0).getReg())
                .addReg(Base, RegState::Define)
                .addReg(Base)
                .addImm(Offset)
                .addImm(Pred)
                .addReg(PredReg)
                .cloneMemRefs(*MI);
        (void)MIB;
        LLVM_DEBUG(dbgs() << "  Added new instruction: " << *MIB);
      } else {
        int Imm = ARM_AM::getAM2Opc(AddSub, abs(Offset), ARM_AM::no_shift);
        auto MIB =
            BuildMI(MBB, MBBI, DL, TII->get(NewOpc), MI->getOperand(0).getReg())
                .addReg(Base, RegState::Define)
                .addReg(Base)
                .addReg(0)
                .addImm(Imm)
                .add(predOps(Pred, PredReg))
                .cloneMemRefs(*MI);
        (void)MIB;
        LLVM_DEBUG(dbgs() << "  Added new instruction: " << *MIB);
      }
    } else {
      // t2LDR_PRE, t2LDR_POST
      auto MIB =
          BuildMI(MBB, MBBI, DL, TII->get(NewOpc), MI->getOperand(0).getReg())
              .addReg(Base, RegState::Define)
              .addReg(Base)
              .addImm(Offset)
              .add(predOps(Pred, PredReg))
              .cloneMemRefs(*MI);
      (void)MIB;
      LLVM_DEBUG(dbgs() << "  Added new instruction: " << *MIB);
    }
  } else {
    MachineOperand &MO = MI->getOperand(0);
    // FIXME: post-indexed stores use am2offset_imm, which still encodes
    // the vestigial zero-reg offset register. When that's fixed, this clause
    // can be removed entirely.
    if (isAM2 && NewOpc == ARM::STR_POST_IMM) {
      int Imm = ARM_AM::getAM2Opc(AddSub, abs(Offset), ARM_AM::no_shift);
      // STR_PRE, STR_POST
      auto MIB = BuildMI(MBB, MBBI, DL, TII->get(NewOpc), Base)
                     .addReg(MO.getReg(), getKillRegState(MO.isKill()))
                     .addReg(Base)
                     .addReg(0)
                     .addImm(Imm)
                     .add(predOps(Pred, PredReg))
                     .cloneMemRefs(*MI);
      (void)MIB;
      LLVM_DEBUG(dbgs() << "  Added new instruction: " << *MIB);
    } else {
      // t2STR_PRE, t2STR_POST
      auto MIB = BuildMI(MBB, MBBI, DL, TII->get(NewOpc), Base)
                     .addReg(MO.getReg(), getKillRegState(MO.isKill()))
                     .addReg(Base)
                     .addImm(Offset)
                     .add(predOps(Pred, PredReg))
                     .cloneMemRefs(*MI);
      (void)MIB;
      LLVM_DEBUG(dbgs() << "  Added new instruction: " << *MIB);
    }
  }
  eraseInstr(MBBI);

  return true;
}

bool ARMLoadStoreOpt::MergeBaseUpdateLSDouble(MachineInstr &MI) {
  unsigned Opcode = MI.getOpcode();
  assert((Opcode == ARM::t2LDRDi8 || Opcode == ARM::t2STRDi8) &&
         "Must have t2STRDi8 or t2LDRDi8");
  if (MI.getOperand(3).getImm() != 0)
    return false;
  LLVM_DEBUG(dbgs() << "Attempting to merge update of: " << MI);

  // Behaviour for writeback is undefined if base register is the same as one
  // of the others.
  const MachineOperand &BaseOp = MI.getOperand(2);
  Register Base = BaseOp.getReg();
  const MachineOperand &Reg0Op = MI.getOperand(0);
  const MachineOperand &Reg1Op = MI.getOperand(1);
  if (Reg0Op.getReg() == Base || Reg1Op.getReg() == Base)
    return false;

  Register PredReg;
  ARMCC::CondCodes Pred = getInstrPredicate(MI, PredReg);
  MachineBasicBlock::iterator MBBI(MI);
  MachineBasicBlock &MBB = *MI.getParent();
  int Offset;
  MachineBasicBlock::iterator MergeInstr = findIncDecBefore(MBBI, Base, Pred,
                                                            PredReg, Offset);
  unsigned NewOpc;
  if (Offset == 8 || Offset == -8) {
    NewOpc = Opcode == ARM::t2LDRDi8 ? ARM::t2LDRD_PRE : ARM::t2STRD_PRE;
  } else {
    MergeInstr = findIncDecAfter(MBBI, Base, Pred, PredReg, Offset, TRI);
    if (MergeInstr == MBB.end())
      return false;
    NewOpc = Opcode == ARM::t2LDRDi8 ? ARM::t2LDRD_POST : ARM::t2STRD_POST;
    if (!isLegalAddressImm(NewOpc, Offset, TII))
      return false;
  }
  LLVM_DEBUG(dbgs() << "  Erasing old increment: " << *MergeInstr);
  eraseInstr(MergeInstr);

  DebugLoc DL = MI.getDebugLoc();
  MachineInstrBuilder MIB = BuildMI(MBB, MBBI, DL, TII->get(NewOpc));
  if (NewOpc == ARM::t2LDRD_PRE || NewOpc == ARM::t2LDRD_POST) {
    MIB.add(Reg0Op).add(Reg1Op).addReg(BaseOp.getReg(), RegState::Define);
  } else {
    assert(NewOpc == ARM::t2STRD_PRE || NewOpc == ARM::t2STRD_POST);
    MIB.addReg(BaseOp.getReg(), RegState::Define).add(Reg0Op).add(Reg1Op);
  }
  MIB.addReg(BaseOp.getReg(), RegState::Kill)
     .addImm(Offset).addImm(Pred).addReg(PredReg);
  assert(TII->get(Opcode).getNumOperands() == 6 &&
         TII->get(NewOpc).getNumOperands() == 7 &&
         "Unexpected number of operands in Opcode specification.");

  // Transfer implicit operands.
  for (const MachineOperand &MO : MI.implicit_operands())
    MIB.add(MO);
  MIB.cloneMemRefs(MI);

  LLVM_DEBUG(dbgs() << "  Added new load/store: " << *MIB);
  eraseInstr(MBBI);
  return true;
}

/// Returns true if instruction is a memory operation that this pass is capable
/// of operating on.
static bool isMemoryOp(const MachineInstr &MI) {
  unsigned Opcode = MI.getOpcode();
  switch (Opcode) {
  case ARM::VLDRS:
  case ARM::VSTRS:
  case ARM::VLDRD:
  case ARM::VSTRD:
  case ARM::LDRi12:
  case ARM::STRi12:
  case ARM::tLDRi:
  case ARM::tSTRi:
  case ARM::tLDRspi:
  case ARM::tSTRspi:
  case ARM::t2LDRi8:
  case ARM::t2LDRi12:
  case ARM::t2STRi8:
  case ARM::t2STRi12:
    break;
  default:
    return false;
  }
  if (!MI.getOperand(1).isReg())
    return false;

  // When no memory operands are present, conservatively assume unaligned,
  // volatile, unfoldable.
  if (!MI.hasOneMemOperand())
    return false;

  const MachineMemOperand &MMO = **MI.memoperands_begin();

  // Don't touch volatile memory accesses - we may be changing their order.
  // TODO: We could allow unordered and monotonic atomics here, but we need to
  // make sure the resulting ldm/stm is correctly marked as atomic.
  if (MMO.isVolatile() || MMO.isAtomic())
    return false;

  // Unaligned ldr/str is emulated by some kernels, but unaligned ldm/stm is
  // not.
  if (MMO.getAlign() < Align(4))
    return false;

  // str <undef> could probably be eliminated entirely, but for now we just want
  // to avoid making a mess of it.
  // FIXME: Use str <undef> as a wildcard to enable better stm folding.
  if (MI.getOperand(0).isReg() && MI.getOperand(0).isUndef())
    return false;

  // Likewise don't mess with references to undefined addresses.
  if (MI.getOperand(1).isUndef())
    return false;

  return true;
}

static void InsertLDR_STR(MachineBasicBlock &MBB,
                          MachineBasicBlock::iterator &MBBI, int Offset,
                          bool isDef, unsigned NewOpc, unsigned Reg,
                          bool RegDeadKill, bool RegUndef, unsigned BaseReg,
                          bool BaseKill, bool BaseUndef, ARMCC::CondCodes Pred,
                          unsigned PredReg, const TargetInstrInfo *TII,
                          MachineInstr *MI) {
  if (isDef) {
    MachineInstrBuilder MIB = BuildMI(MBB, MBBI, MBBI->getDebugLoc(),
                                      TII->get(NewOpc))
      .addReg(Reg, getDefRegState(true) | getDeadRegState(RegDeadKill))
      .addReg(BaseReg, getKillRegState(BaseKill)|getUndefRegState(BaseUndef));
    MIB.addImm(Offset).addImm(Pred).addReg(PredReg);
    // FIXME: This is overly conservative; the new instruction accesses 4
    // bytes, not 8.
    MIB.cloneMemRefs(*MI);
  } else {
    MachineInstrBuilder MIB = BuildMI(MBB, MBBI, MBBI->getDebugLoc(),
                                      TII->get(NewOpc))
      .addReg(Reg, getKillRegState(RegDeadKill) | getUndefRegState(RegUndef))
      .addReg(BaseReg, getKillRegState(BaseKill)|getUndefRegState(BaseUndef));
    MIB.addImm(Offset).addImm(Pred).addReg(PredReg);
    // FIXME: This is overly conservative; the new instruction accesses 4
    // bytes, not 8.
    MIB.cloneMemRefs(*MI);
  }
}

bool ARMLoadStoreOpt::FixInvalidRegPairOp(MachineBasicBlock &MBB,
                                          MachineBasicBlock::iterator &MBBI) {
  MachineInstr *MI = &*MBBI;
  unsigned Opcode = MI->getOpcode();
  // FIXME: Code/comments below check Opcode == t2STRDi8, but this check returns
  // if we see this opcode.
  if (Opcode != ARM::LDRD && Opcode != ARM::STRD && Opcode != ARM::t2LDRDi8)
    return false;

  const MachineOperand &BaseOp = MI->getOperand(2);
  Register BaseReg = BaseOp.getReg();
  Register EvenReg = MI->getOperand(0).getReg();
  Register OddReg = MI->getOperand(1).getReg();
  unsigned EvenRegNum = TRI->getDwarfRegNum(EvenReg, false);
  unsigned OddRegNum  = TRI->getDwarfRegNum(OddReg, false);

  // ARM errata 602117: LDRD with base in list may result in incorrect base
  // register when interrupted or faulted.
  bool Errata602117 = EvenReg == BaseReg &&
    (Opcode == ARM::LDRD || Opcode == ARM::t2LDRDi8) && STI->isCortexM3();
  // ARM LDRD/STRD needs consecutive registers.
  bool NonConsecutiveRegs = (Opcode == ARM::LDRD || Opcode == ARM::STRD) &&
    (EvenRegNum % 2 != 0 || EvenRegNum + 1 != OddRegNum);

  if (!Errata602117 && !NonConsecutiveRegs)
    return false;

  bool isT2 = Opcode == ARM::t2LDRDi8 || Opcode == ARM::t2STRDi8;
  bool isLd = Opcode == ARM::LDRD || Opcode == ARM::t2LDRDi8;
  bool EvenDeadKill = isLd ?
    MI->getOperand(0).isDead() : MI->getOperand(0).isKill();
  bool EvenUndef = MI->getOperand(0).isUndef();
  bool OddDeadKill  = isLd ?
    MI->getOperand(1).isDead() : MI->getOperand(1).isKill();
  bool OddUndef = MI->getOperand(1).isUndef();
  bool BaseKill = BaseOp.isKill();
  bool BaseUndef = BaseOp.isUndef();
  assert((isT2 || !MI->getOperand(3).getReg().isValid()) &&
         "register offset not handled below");
  int OffImm = getMemoryOpOffset(*MI);
  Register PredReg;
  ARMCC::CondCodes Pred = getInstrPredicate(*MI, PredReg);

  if (OddRegNum > EvenRegNum && OffImm == 0) {
    // Ascending register numbers and no offset. It's safe to change it to a
    // ldm or stm.
    unsigned NewOpc = (isLd)
      ? (isT2 ? ARM::t2LDMIA : ARM::LDMIA)
      : (isT2 ? ARM::t2STMIA : ARM::STMIA);
    if (isLd) {
      BuildMI(MBB, MBBI, MBBI->getDebugLoc(), TII->get(NewOpc))
          .add(BaseOp)
          .addImm(Pred)
          .addReg(PredReg)
          .addReg(EvenReg, getDefRegState(isLd) | getDeadRegState(EvenDeadKill))
          .addReg(OddReg, getDefRegState(isLd) | getDeadRegState(OddDeadKill))
          .cloneMemRefs(*MI);
      ++NumLDRD2LDM;
    } else {
      BuildMI(MBB, MBBI, MBBI->getDebugLoc(), TII->get(NewOpc))
          .add(BaseOp)
          .addImm(Pred)
          .addReg(PredReg)
          .addReg(EvenReg,
                  getKillRegState(EvenDeadKill) | getUndefRegState(EvenUndef))
          .addReg(OddReg,
                  getKillRegState(OddDeadKill) | getUndefRegState(OddUndef))
          .cloneMemRefs(*MI);
      ++NumSTRD2STM;
    }
  } else {
    // Split into two instructions.
    unsigned NewOpc = (isLd)
      ? (isT2 ? (OffImm < 0 ? ARM::t2LDRi8 : ARM::t2LDRi12) : ARM::LDRi12)
      : (isT2 ? (OffImm < 0 ? ARM::t2STRi8 : ARM::t2STRi12) : ARM::STRi12);
    // Be extra careful for thumb2. t2LDRi8 can't reference a zero offset,
    // so adjust and use t2LDRi12 here for that.
    unsigned NewOpc2 = (isLd)
      ? (isT2 ? (OffImm+4 < 0 ? ARM::t2LDRi8 : ARM::t2LDRi12) : ARM::LDRi12)
      : (isT2 ? (OffImm+4 < 0 ? ARM::t2STRi8 : ARM::t2STRi12) : ARM::STRi12);
    // If this is a load, make sure the first load does not clobber the base
    // register before the second load reads it.
    if (isLd && TRI->regsOverlap(EvenReg, BaseReg)) {
      assert(!TRI->regsOverlap(OddReg, BaseReg));
      InsertLDR_STR(MBB, MBBI, OffImm + 4, isLd, NewOpc2, OddReg, OddDeadKill,
                    false, BaseReg, false, BaseUndef, Pred, PredReg, TII, MI);
      InsertLDR_STR(MBB, MBBI, OffImm, isLd, NewOpc, EvenReg, EvenDeadKill,
                    false, BaseReg, BaseKill, BaseUndef, Pred, PredReg, TII,
                    MI);
    } else {
      if (OddReg == EvenReg && EvenDeadKill) {
        // If the two source operands are the same, the kill marker is
        // probably on the first one. e.g.
        // t2STRDi8 killed %r5, %r5, killed %r9, 0, 14, %reg0
        EvenDeadKill = false;
        OddDeadKill = true;
      }
      // Never kill the base register in the first instruction.
      if (EvenReg == BaseReg)
        EvenDeadKill = false;
      InsertLDR_STR(MBB, MBBI, OffImm, isLd, NewOpc, EvenReg, EvenDeadKill,
                    EvenUndef, BaseReg, false, BaseUndef, Pred, PredReg, TII,
                    MI);
      InsertLDR_STR(MBB, MBBI, OffImm + 4, isLd, NewOpc2, OddReg, OddDeadKill,
                    OddUndef, BaseReg, BaseKill, BaseUndef, Pred, PredReg, TII,
                    MI);
    }
    if (isLd)
      ++NumLDRD2LDR;
    else
      ++NumSTRD2STR;
  }

  MBBI = eraseInstr(MBBI);
  return true;
}

/// An optimization pass to turn multiple LDR / STR ops of the same base and
/// incrementing offset into LDM / STM ops.
bool ARMLoadStoreOpt::LoadStoreMultipleOpti(MachineBasicBlock &MBB) {
  MemOpQueue MemOps;
  unsigned CurrBase = 0;
  unsigned CurrOpc = ~0u;
  ARMCC::CondCodes CurrPred = ARMCC::AL;
  unsigned Position = 0;
  assert(Candidates.size() == 0);
  assert(MergeBaseCandidates.size() == 0);
  LiveRegsValid = false;

  for (MachineBasicBlock::iterator I = MBB.end(), MBBI; I != MBB.begin();
       I = MBBI) {
    // The instruction in front of the iterator is the one we look at.
    MBBI = std::prev(I);
    if (FixInvalidRegPairOp(MBB, MBBI))
      continue;
    ++Position;

    if (isMemoryOp(*MBBI)) {
      unsigned Opcode = MBBI->getOpcode();
      const MachineOperand &MO = MBBI->getOperand(0);
      Register Reg = MO.getReg();
      Register Base = getLoadStoreBaseOp(*MBBI).getReg();
      Register PredReg;
      ARMCC::CondCodes Pred = getInstrPredicate(*MBBI, PredReg);
      int Offset = getMemoryOpOffset(*MBBI);
      if (CurrBase == 0) {
        // Start of a new chain.
        CurrBase = Base;
        CurrOpc  = Opcode;
        CurrPred = Pred;
        MemOps.push_back(MemOpQueueEntry(*MBBI, Offset, Position));
        continue;
      }
      // Note: No need to match PredReg in the next if.
      if (CurrOpc == Opcode && CurrBase == Base && CurrPred == Pred) {
        // Watch out for:
        //   r4 := ldr [r0, #8]
        //   r4 := ldr [r0, #4]
        // or
        //   r0 := ldr [r0]
        // If a load overrides the base register or a register loaded by
        // another load in our chain, we cannot take this instruction.
        bool Overlap = false;
        if (isLoadSingle(Opcode)) {
          Overlap = (Base == Reg);
          if (!Overlap) {
            for (const MemOpQueueEntry &E : MemOps) {
              if (TRI->regsOverlap(Reg, E.MI->getOperand(0).getReg())) {
                Overlap = true;
                break;
              }
            }
          }
        }

        if (!Overlap) {
          // Check offset and sort memory operation into the current chain.
          if (Offset > MemOps.back().Offset) {
            MemOps.push_back(MemOpQueueEntry(*MBBI, Offset, Position));
            continue;
          } else {
            MemOpQueue::iterator MI, ME;
            for (MI = MemOps.begin(), ME = MemOps.end(); MI != ME; ++MI) {
              if (Offset < MI->Offset) {
                // Found a place to insert.
                break;
              }
              if (Offset == MI->Offset) {
                // Collision, abort.
                MI = ME;
                break;
              }
            }
            if (MI != MemOps.end()) {
              MemOps.insert(MI, MemOpQueueEntry(*MBBI, Offset, Position));
              continue;
            }
          }
        }
      }

      // Don't advance the iterator; The op will start a new chain next.
      MBBI = I;
      --Position;
      // Fallthrough to look into existing chain.
    } else if (MBBI->isDebugInstr()) {
      continue;
    } else if (MBBI->getOpcode() == ARM::t2LDRDi8 ||
               MBBI->getOpcode() == ARM::t2STRDi8) {
      // ARMPreAllocLoadStoreOpt has already formed some LDRD/STRD instructions
      // remember them because we may still be able to merge add/sub into them.
      MergeBaseCandidates.push_back(&*MBBI);
    }

    // If we are here then the chain is broken; Extract candidates for a merge.
    if (MemOps.size() > 0) {
      FormCandidates(MemOps);
      // Reset for the next chain.
      CurrBase = 0;
      CurrOpc = ~0u;
      CurrPred = ARMCC::AL;
      MemOps.clear();
    }
  }
  if (MemOps.size() > 0)
    FormCandidates(MemOps);

  // Sort candidates so they get processed from end to begin of the basic
  // block later; This is necessary for liveness calculation.
  auto LessThan = [](const MergeCandidate* M0, const MergeCandidate *M1) {
    return M0->InsertPos < M1->InsertPos;
  };
  llvm::sort(Candidates, LessThan);

  // Go through list of candidates and merge.
  bool Changed = false;
  for (const MergeCandidate *Candidate : Candidates) {
    if (Candidate->CanMergeToLSMulti || Candidate->CanMergeToLSDouble) {
      MachineInstr *Merged = MergeOpsUpdate(*Candidate);
      // Merge preceding/trailing base inc/dec into the merged op.
      if (Merged) {
        Changed = true;
        unsigned Opcode = Merged->getOpcode();
        if (Opcode == ARM::t2STRDi8 || Opcode == ARM::t2LDRDi8)
          MergeBaseUpdateLSDouble(*Merged);
        else
          MergeBaseUpdateLSMultiple(Merged);
      } else {
        for (MachineInstr *MI : Candidate->Instrs) {
          if (MergeBaseUpdateLoadStore(MI))
            Changed = true;
        }
      }
    } else {
      assert(Candidate->Instrs.size() == 1);
      if (MergeBaseUpdateLoadStore(Candidate->Instrs.front()))
        Changed = true;
    }
  }
  Candidates.clear();
  // Try to fold add/sub into the LDRD/STRD formed by ARMPreAllocLoadStoreOpt.
  for (MachineInstr *MI : MergeBaseCandidates)
    MergeBaseUpdateLSDouble(*MI);
  MergeBaseCandidates.clear();

  return Changed;
}

/// If this is a exit BB, try merging the return ops ("bx lr" and "mov pc, lr")
/// into the preceding stack restore so it directly restore the value of LR
/// into pc.
///   ldmfd sp!, {..., lr}
///   bx lr
/// or
///   ldmfd sp!, {..., lr}
///   mov pc, lr
/// =>
///   ldmfd sp!, {..., pc}
bool ARMLoadStoreOpt::MergeReturnIntoLDM(MachineBasicBlock &MBB) {
  // Thumb1 LDM doesn't allow high registers.
  if (isThumb1) return false;
  if (MBB.empty()) return false;

  MachineBasicBlock::iterator MBBI = MBB.getLastNonDebugInstr();
  if (MBBI != MBB.begin() && MBBI != MBB.end() &&
      (MBBI->getOpcode() == ARM::BX_RET ||
       MBBI->getOpcode() == ARM::tBX_RET ||
       MBBI->getOpcode() == ARM::MOVPCLR)) {
    MachineBasicBlock::iterator PrevI = std::prev(MBBI);
    // Ignore any debug instructions.
    while (PrevI->isDebugInstr() && PrevI != MBB.begin())
      --PrevI;
    MachineInstr &PrevMI = *PrevI;
    unsigned Opcode = PrevMI.getOpcode();
    if (Opcode == ARM::LDMIA_UPD || Opcode == ARM::LDMDA_UPD ||
        Opcode == ARM::LDMDB_UPD || Opcode == ARM::LDMIB_UPD ||
        Opcode == ARM::t2LDMIA_UPD || Opcode == ARM::t2LDMDB_UPD) {
      MachineOperand &MO = PrevMI.getOperand(PrevMI.getNumOperands() - 1);
      if (MO.getReg() != ARM::LR)
        return false;
      unsigned NewOpc = (isThumb2 ? ARM::t2LDMIA_RET : ARM::LDMIA_RET);
      assert(((isThumb2 && Opcode == ARM::t2LDMIA_UPD) ||
              Opcode == ARM::LDMIA_UPD) && "Unsupported multiple load-return!");
      PrevMI.setDesc(TII->get(NewOpc));
      MO.setReg(ARM::PC);
      PrevMI.copyImplicitOps(*MBB.getParent(), *MBBI);
      eraseInstr(MBBI);
      return true;
    }
  }
  return false;
}

bool ARMLoadStoreOpt::CombineMovBx(MachineBasicBlock &MBB) {
  MachineBasicBlock::iterator MBBI = MBB.getFirstTerminator();
  if (MBBI == MBB.begin() || MBBI == MBB.end() ||
      MBBI->getOpcode() != ARM::tBX_RET)
    return false;

  MachineBasicBlock::iterator Prev = MBBI;
  --Prev;
  if (Prev->getOpcode() != ARM::tMOVr ||
      !Prev->definesRegister(ARM::LR, /*TRI=*/nullptr))
    return false;

  for (auto Use : Prev->uses())
    if (Use.isKill()) {
      assert(STI->hasV4TOps());
      BuildMI(MBB, MBBI, MBBI->getDebugLoc(), TII->get(ARM::tBX))
          .addReg(Use.getReg(), RegState::Kill)
          .add(predOps(ARMCC::AL))
          .copyImplicitOps(*MBBI);
      eraseInstr(MBBI);
      eraseInstr(Prev);
      return true;
    }

  llvm_unreachable("tMOVr doesn't kill a reg before tBX_RET?");
}

bool ARMLoadStoreOpt::runOnMachineFunction(
    MachineFunction &Fn, const RegisterClassInfo &RegClassInfo) {
  MF = &Fn;
  STI = &Fn.getSubtarget<ARMSubtarget>();
  TL = STI->getTargetLowering();
  AFI = Fn.getInfo<ARMFunctionInfo>();
  TII = STI->getInstrInfo();
  TRI = STI->getRegisterInfo();
  RCI = &RegClassInfo;

  isThumb2 = AFI->isThumb2Function();
  isThumb1 = AFI->isThumbFunction() && !isThumb2;

  bool Modified = false, ModifiedLDMReturn = false;
  for (MachineBasicBlock &MBB : Fn) {
    Modified |= LoadStoreMultipleOpti(MBB);
    if (STI->hasV5TOps() && !AFI->shouldSignReturnAddress())
      ModifiedLDMReturn |= MergeReturnIntoLDM(MBB);
    if (isThumb1)
      Modified |= CombineMovBx(MBB);
  }
  Modified |= ModifiedLDMReturn;

  // If we merged a BX instruction into an LDM, we need to re-calculate whether
  // LR is restored. This check needs to consider the whole function, not just
  // the instruction(s) we changed, because there may be other BX returns which
  // still need LR to be restored.
  if (ModifiedLDMReturn)
    ARMFrameLowering::updateLRRestored(Fn);

  Allocator.DestroyAll();
  return Modified;
}

bool ARMLoadStoreOptLegacy::runOnMachineFunction(MachineFunction &MF) {
  if (skipFunction(MF.getFunction()))
    return false;
  ARMLoadStoreOpt Impl;
  return Impl.runOnMachineFunction(
      MF, getAnalysis<MachineRegisterClassInfoWrapperPass>().getRCI());
}

#define ARM_PREALLOC_LOAD_STORE_OPT_NAME                                       \
  "ARM pre- register allocation load / store optimization pass"

namespace {

/// Pre- register allocation pass that move load / stores from consecutive
/// locations close to make it more likely they will be combined later.
struct ARMPreAllocLoadStoreOpt {
  AliasAnalysis *AA;
  const DataLayout *TD;
  const TargetInstrInfo *TII;
  const TargetRegisterInfo *TRI;
  const ARMSubtarget *STI;
  MachineRegisterInfo *MRI;
  MachineDominatorTree *DT;
  MachineFunction *MF;

  bool runOnMachineFunction(MachineFunction &Fn, AliasAnalysis *AA,
                            MachineDominatorTree *DT);

private:
  bool CanFormLdStDWord(MachineInstr *Op0, MachineInstr *Op1, DebugLoc &dl,
                        unsigned &NewOpc, Register &EvenReg, Register &OddReg,
                        Register &BaseReg, int &Offset, Register &PredReg,
                        ARMCC::CondCodes &Pred, bool &isT2);
  bool RescheduleOps(
      MachineBasicBlock *MBB, SmallVectorImpl<MachineInstr *> &Ops,
      unsigned Base, bool isLd, DenseMap<MachineInstr *, unsigned> &MI2LocMap,
      SmallDenseMap<Register, SmallVector<MachineInstr *>, 8> &RegisterMap);
  bool RescheduleLoadStoreInstrs(MachineBasicBlock *MBB);
  bool DistributeIncrements();
  bool DistributeIncrements(Register Base);
};

struct ARMPreAllocLoadStoreOptLegacy : public MachineFunctionPass {
  static char ID;

  ARMPreAllocLoadStoreOptLegacy() : MachineFunctionPass(ID) {}

  bool runOnMachineFunction(MachineFunction &Fn) override;

  StringRef getPassName() const override {
    return ARM_PREALLOC_LOAD_STORE_OPT_NAME;
  }

  void getAnalysisUsage(AnalysisUsage &AU) const override {
    AU.addRequired<AAResultsWrapperPass>();
    AU.addRequired<MachineDominatorTreeWrapperPass>();
    AU.addPreserved<MachineDominatorTreeWrapperPass>();
    AU.addPreserved<MachineRegisterClassInfoWrapperPass>();
    MachineFunctionPass::getAnalysisUsage(AU);
  }
};

char ARMPreAllocLoadStoreOptLegacy::ID = 0;

} // end anonymous namespace

INITIALIZE_PASS_BEGIN(ARMPreAllocLoadStoreOptLegacy, "arm-prera-ldst-opt",
                      ARM_PREALLOC_LOAD_STORE_OPT_NAME, false, false)
INITIALIZE_PASS_DEPENDENCY(MachineDominatorTreeWrapperPass)
INITIALIZE_PASS_END(ARMPreAllocLoadStoreOptLegacy, "arm-prera-ldst-opt",
                    ARM_PREALLOC_LOAD_STORE_OPT_NAME, false, false)

// Limit the number of instructions to be rescheduled.
// FIXME: tune this limit, and/or come up with some better heuristics.
static cl::opt<unsigned> InstReorderLimit("arm-prera-ldst-opt-reorder-limit",
                                          cl::init(8), cl::Hidden);

bool ARMPreAllocLoadStoreOpt::runOnMachineFunction(MachineFunction &Fn,
                                                   AliasAnalysis *AAIn,
                                                   MachineDominatorTree *DTIn) {
  if (AssumeMisalignedLoadStores)
    return false;

  AA = AAIn;
  DT = DTIn;
  TD = &Fn.getDataLayout();
  STI = &Fn.getSubtarget<ARMSubtarget>();
  TII = STI->getInstrInfo();
  TRI = STI->getRegisterInfo();
  MRI = &Fn.getRegInfo();
  MF = &Fn;

  bool Modified = DistributeIncrements();
  for (MachineBasicBlock &MFI : Fn)
    Modified |= RescheduleLoadStoreInstrs(&MFI);

  return Modified;
}

bool ARMPreAllocLoadStoreOptLegacy::runOnMachineFunction(MachineFunction &Fn) {
  if (skipFunction(Fn.getFunction()))
    return false;

  ARMPreAllocLoadStoreOpt Impl;
  AliasAnalysis *AA = &getAnalysis<AAResultsWrapperPass>().getAAResults();
  MachineDominatorTree *DT =
      &getAnalysis<MachineDominatorTreeWrapperPass>().getDomTree();
  return Impl.runOnMachineFunction(Fn, AA, DT);
}

static bool IsSafeAndProfitableToMove(bool isLd, unsigned Base,
                                      MachineBasicBlock::iterator I,
                                      MachineBasicBlock::iterator E,
                                      SmallPtrSetImpl<MachineInstr*> &MemOps,
                                      SmallSet<unsigned, 4> &MemRegs,
                                      const TargetRegisterInfo *TRI,
                                      AliasAnalysis *AA) {
  // Are there stores / loads / calls between them?
  SmallSet<unsigned, 4> AddedRegPressure;
  while (++I != E) {
    if (I->isDebugInstr() || MemOps.count(&*I))
      continue;
    if (I->isCall() || I->isTerminator() || I->hasUnmodeledSideEffects())
      return false;
    if (I->mayStore() || (!isLd && I->mayLoad()))
      for (MachineInstr *MemOp : MemOps)
        if (I->mayAlias(AA, *MemOp, /*UseTBAA*/ false))
          return false;
    for (unsigned j = 0, NumOps = I->getNumOperands(); j != NumOps; ++j) {
      MachineOperand &MO = I->getOperand(j);
      if (!MO.isReg())
        continue;
      Register Reg = MO.getReg();
      if (MO.isDef() && TRI->regsOverlap(Reg, Base))
        return false;
      if (Reg != Base && !MemRegs.count(Reg))
        AddedRegPressure.insert(Reg);
    }
  }

  // Estimate register pressure increase due to the transformation.
  if (MemRegs.size() <= 4)
    // Ok if we are moving small number of instructions.
    return true;
  return AddedRegPressure.size() <= MemRegs.size() * 2;
}

bool ARMPreAllocLoadStoreOpt::CanFormLdStDWord(
    MachineInstr *Op0, MachineInstr *Op1, DebugLoc &dl, unsigned &NewOpc,
    Register &FirstReg, Register &SecondReg, Register &BaseReg, int &Offset,
    Register &PredReg, ARMCC::CondCodes &Pred, bool &isT2) {
  // Make sure we're allowed to generate LDRD/STRD.
  if (!STI->hasV5TEOps())
    return false;

  // FIXME: VLDRS / VSTRS -> VLDRD / VSTRD
  unsigned Scale = 1;
  unsigned Opcode = Op0->getOpcode();
  if (Opcode == ARM::LDRi12) {
    NewOpc = ARM::LDRD;
  } else if (Opcode == ARM::STRi12) {
    NewOpc = ARM::STRD;
  } else if (Opcode == ARM::t2LDRi8 || Opcode == ARM::t2LDRi12) {
    NewOpc = ARM::t2LDRDi8;
    Scale = 4;
    isT2 = true;
  } else if (Opcode == ARM::t2STRi8 || Opcode == ARM::t2STRi12) {
    NewOpc = ARM::t2STRDi8;
    Scale = 4;
    isT2 = true;
  } else {
    return false;
  }

  // Make sure the base address satisfies i64 ld / st alignment requirement.
  // At the moment, we ignore the memoryoperand's value.
  // If we want to use AliasAnalysis, we should check it accordingly.
  if (!Op0->hasOneMemOperand() ||
      (*Op0->memoperands_begin())->isVolatile() ||
      (*Op0->memoperands_begin())->isAtomic())
    return false;

  Align Alignment = (*Op0->memoperands_begin())->getAlign();
  Align ReqAlign = STI->getDualLoadStoreAlignment();
  if (Alignment < ReqAlign)
    return false;

  // Then make sure the immediate offset fits.
  int OffImm = getMemoryOpOffset(*Op0);
  if (isT2) {
    int Limit = (1 << 8) * Scale;
    if (OffImm >= Limit || (OffImm <= -Limit) || (OffImm & (Scale-1)))
      return false;
    Offset = OffImm;
  } else {
    ARM_AM::AddrOpc AddSub = ARM_AM::add;
    if (OffImm < 0) {
      AddSub = ARM_AM::sub;
      OffImm = - OffImm;
    }
    int Limit = (1 << 8) * Scale;
    if (OffImm >= Limit || (OffImm & (Scale-1)))
      return false;
    Offset = ARM_AM::getAM3Opc(AddSub, OffImm);
  }
  FirstReg = Op0->getOperand(0).getReg();
  SecondReg = Op1->getOperand(0).getReg();
  if (FirstReg == SecondReg)
    return false;
  BaseReg = Op0->getOperand(1).getReg();
  Pred = getInstrPredicate(*Op0, PredReg);
  dl = Op0->getDebugLoc();
  return true;
}

bool ARMPreAllocLoadStoreOpt::RescheduleOps(
    MachineBasicBlock *MBB, SmallVectorImpl<MachineInstr *> &Ops, unsigned Base,
    bool isLd, DenseMap<MachineInstr *, unsigned> &MI2LocMap,
    SmallDenseMap<Register, SmallVector<MachineInstr *>, 8> &RegisterMap) {
  bool RetVal = false;

  // Sort by offset (in reverse order).
  llvm::sort(Ops, [](const MachineInstr *LHS, const MachineInstr *RHS) {
    int LOffset = getMemoryOpOffset(*LHS);
    int ROffset = getMemoryOpOffset(*RHS);
    assert(LHS == RHS || LOffset != ROffset);
    return LOffset > ROffset;
  });

  // The loads / stores of the same base are in order. Scan them from first to
  // last and check for the following:
  // 1. Any def of base.
  // 2. Any gaps.
  while (Ops.size() > 1) {
    unsigned FirstLoc = ~0U;
    unsigned LastLoc = 0;
    MachineInstr *FirstOp = nullptr;
    MachineInstr *LastOp = nullptr;
    int LastOffset = 0;
    unsigned LastOpcode = 0;
    unsigned LastBytes = 0;
    unsigned NumMove = 0;
    for (MachineInstr *Op : llvm::reverse(Ops)) {
      // Make sure each operation has the same kind.
      unsigned LSMOpcode
        = getLoadStoreMultipleOpcode(Op->getOpcode(), ARM_AM::ia);
      if (LastOpcode && LSMOpcode != LastOpcode)
        break;

      // Check that we have a continuous set of offsets.
      int Offset = getMemoryOpOffset(*Op);
      unsigned Bytes = getLSMultipleTransferSize(Op);
      if (LastBytes) {
        if (Bytes != LastBytes || Offset != (LastOffset + (int)Bytes))
          break;
      }

      // Don't try to reschedule too many instructions.
      if (NumMove == InstReorderLimit)
        break;

      // Found a mergeable instruction; save information about it.
      ++NumMove;
      LastOffset = Offset;
      LastBytes = Bytes;
      LastOpcode = LSMOpcode;

      unsigned Loc = MI2LocMap[Op];
      if (Loc <= FirstLoc) {
        FirstLoc = Loc;
        FirstOp = Op;
      }
      if (Loc >= LastLoc) {
        LastLoc = Loc;
        LastOp = Op;
      }
    }

    if (NumMove <= 1)
      Ops.pop_back();
    else {
      SmallPtrSet<MachineInstr*, 4> MemOps;
      SmallSet<unsigned, 4> MemRegs;
      for (size_t i = Ops.size() - NumMove, e = Ops.size(); i != e; ++i) {
        MemOps.insert(Ops[i]);
        MemRegs.insert(Ops[i]->getOperand(0).getReg());
      }

      // Be conservative, if the instructions are too far apart, don't
      // move them. We want to limit the increase of register pressure.
      bool DoMove = (LastLoc - FirstLoc) <= NumMove*4; // FIXME: Tune this.
      if (DoMove)
        DoMove = IsSafeAndProfitableToMove(isLd, Base, FirstOp, LastOp,
                                           MemOps, MemRegs, TRI, AA);
      if (!DoMove) {
        for (unsigned i = 0; i != NumMove; ++i)
          Ops.pop_back();
      } else {
        // This is the new location for the loads / stores.
        MachineBasicBlock::iterator InsertPos = isLd ? FirstOp : LastOp;
        while (InsertPos != MBB->end() &&
               (MemOps.count(&*InsertPos) || InsertPos->isDebugInstr()))
          ++InsertPos;

        // If we are moving a pair of loads / stores, see if it makes sense
        // to try to allocate a pair of registers that can form register pairs.
        MachineInstr *Op0 = Ops.back();
        MachineInstr *Op1 = Ops[Ops.size()-2];
        Register FirstReg, SecondReg;
        Register BaseReg, PredReg;
        ARMCC::CondCodes Pred = ARMCC::AL;
        bool isT2 = false;
        unsigned NewOpc = 0;
        int Offset = 0;
        DebugLoc dl;
        if (NumMove == 2 && CanFormLdStDWord(Op0, Op1, dl, NewOpc,
                                             FirstReg, SecondReg, BaseReg,
                                             Offset, PredReg, Pred, isT2)) {
          Ops.pop_back();
          Ops.pop_back();

          const MCInstrDesc &MCID = TII->get(NewOpc);
          const TargetRegisterClass *TRC = TII->getRegClass(MCID, 0);
          MRI->constrainRegClass(FirstReg, TRC);
          MRI->constrainRegClass(SecondReg, TRC);

          // Form the pair instruction.
          if (isLd) {
            MachineInstrBuilder MIB = BuildMI(*MBB, InsertPos, dl, MCID)
              .addReg(FirstReg, RegState::Define)
              .addReg(SecondReg, RegState::Define)
              .addReg(BaseReg);
            // FIXME: We're converting from LDRi12 to an insn that still
            // uses addrmode2, so we need an explicit offset reg. It should
            // always by reg0 since we're transforming LDRi12s.
            if (!isT2)
              MIB.addReg(0);
            MIB.addImm(Offset).addImm(Pred).addReg(PredReg);
            MIB.cloneMergedMemRefs({Op0, Op1});
            LLVM_DEBUG(dbgs() << "Formed " << *MIB << "\n");
            ++NumLDRDFormed;
          } else {
            MachineInstrBuilder MIB = BuildMI(*MBB, InsertPos, dl, MCID)
              .addReg(FirstReg)
              .addReg(SecondReg)
              .addReg(BaseReg);
            // FIXME: We're converting from LDRi12 to an insn that still
            // uses addrmode2, so we need an explicit offset reg. It should
            // always by reg0 since we're transforming STRi12s.
            if (!isT2)
              MIB.addReg(0);
            MIB.addImm(Offset).addImm(Pred).addReg(PredReg);
            MIB.cloneMergedMemRefs({Op0, Op1});
            LLVM_DEBUG(dbgs() << "Formed " << *MIB << "\n");
            ++NumSTRDFormed;
          }
          MBB->erase(Op0);
          MBB->erase(Op1);

          if (!isT2) {
            // Add register allocation hints to form register pairs.
            MRI->setRegAllocationHint(FirstReg, ARMRI::RegPairEven, SecondReg);
            MRI->setRegAllocationHint(SecondReg,  ARMRI::RegPairOdd, FirstReg);
          }
        } else {
          for (unsigned i = 0; i != NumMove; ++i) {
            MachineInstr *Op = Ops.pop_back_val();
            if (isLd) {
              // Populate RegisterMap with all Registers defined by loads.
              Register Reg = Op->getOperand(0).getReg();
              RegisterMap[Reg];
            }

            MBB->splice(InsertPos, MBB, Op);
          }
        }

        NumLdStMoved += NumMove;
        RetVal = true;
      }
    }
  }

  return RetVal;
}

static void forEachDbgRegOperand(MachineInstr *MI,
                                 std::function<void(MachineOperand &)> Fn) {
  if (MI->isNonListDebugValue()) {
    auto &Op = MI->getOperand(0);
    if (Op.isReg())
      Fn(Op);
  } else {
    for (unsigned I = 2; I < MI->getNumOperands(); I++) {
      auto &Op = MI->getOperand(I);
      if (Op.isReg())
        Fn(Op);
    }
  }
}

// Update the RegisterMap with the instruction that was moved because a
// DBG_VALUE_LIST may need to be moved again.
static void updateRegisterMapForDbgValueListAfterMove(
    SmallDenseMap<Register, SmallVector<MachineInstr *>, 8> &RegisterMap,
    MachineInstr *DbgValueListInstr, MachineInstr *InstrToReplace) {

  forEachDbgRegOperand(DbgValueListInstr, [&](MachineOperand &Op) {
    auto RegIt = RegisterMap.find(Op.getReg());
    if (RegIt == RegisterMap.end())
      return;
    auto &InstrVec = RegIt->getSecond();
    llvm::replace(InstrVec, InstrToReplace, DbgValueListInstr);
  });
}

static DebugVariable createDebugVariableFromMachineInstr(MachineInstr *MI) {
  auto DbgVar = DebugVariable(MI->getDebugVariable(), MI->getDebugExpression(),
                              MI->getDebugLoc()->getInlinedAt());
  return DbgVar;
}

bool
ARMPreAllocLoadStoreOpt::RescheduleLoadStoreInstrs(MachineBasicBlock *MBB) {
  bool RetVal = false;

  DenseMap<MachineInstr *, unsigned> MI2LocMap;
  using Base2InstMap = DenseMap<unsigned, SmallVector<MachineInstr *, 4>>;
  using BaseVec = SmallVector<unsigned, 4>;
  Base2InstMap Base2LdsMap;
  Base2InstMap Base2StsMap;
  BaseVec LdBases;
  BaseVec StBases;
  // This map is used to track the relationship between the virtual
  // register that is the result of a load that is moved and the DBG_VALUE
  // MachineInstr pointer that uses that virtual register.
  SmallDenseMap<Register, SmallVector<MachineInstr *>, 8> RegisterMap;

  unsigned Loc = 0;
  MachineBasicBlock::iterator MBBI = MBB->begin();
  MachineBasicBlock::iterator E = MBB->end();
  while (MBBI != E) {
    for (; MBBI != E; ++MBBI) {
      MachineInstr &MI = *MBBI;
      if (MI.isCall() || MI.isTerminator()) {
        // Stop at barriers.
        ++MBBI;
        break;
      }

      if (!MI.isDebugInstr())
        MI2LocMap[&MI] = ++Loc;

      if (!isMemoryOp(MI))
        continue;
      Register PredReg;
      if (getInstrPredicate(MI, PredReg) != ARMCC::AL)
        continue;

      int Opc = MI.getOpcode();
      bool isLd = isLoadSingle(Opc);
      Register Base = MI.getOperand(1).getReg();
      int Offset = getMemoryOpOffset(MI);
      bool StopHere = false;
      auto FindBases = [&](Base2InstMap &Base2Ops, BaseVec &Bases) {
        auto [BI, Inserted] = Base2Ops.try_emplace(Base);
        if (Inserted) {
          BI->second.push_back(&MI);
          Bases.push_back(Base);
          return;
        }
        for (const MachineInstr *MI : BI->second) {
          if (Offset == getMemoryOpOffset(*MI)) {
            StopHere = true;
            break;
          }
        }
        if (!StopHere)
          BI->second.push_back(&MI);
      };

      if (isLd)
        FindBases(Base2LdsMap, LdBases);
      else
        FindBases(Base2StsMap, StBases);

      if (StopHere) {
        // Found a duplicate (a base+offset combination that's seen earlier).
        // Backtrack.
        --Loc;
        break;
      }
    }

    // Re-schedule loads.
    for (unsigned Base : LdBases) {
      SmallVectorImpl<MachineInstr *> &Lds = Base2LdsMap[Base];
      if (Lds.size() > 1)
        RetVal |= RescheduleOps(MBB, Lds, Base, true, MI2LocMap, RegisterMap);
    }

    // Re-schedule stores.
    for (unsigned Base : StBases) {
      SmallVectorImpl<MachineInstr *> &Sts = Base2StsMap[Base];
      if (Sts.size() > 1)
        RetVal |= RescheduleOps(MBB, Sts, Base, false, MI2LocMap, RegisterMap);
    }

    if (MBBI != E) {
      Base2LdsMap.clear();
      Base2StsMap.clear();
      LdBases.clear();
      StBases.clear();
    }
  }

  // Reschedule DBG_VALUEs to match any loads that were moved. When a load is
  // sunk beyond a DBG_VALUE that is referring to it, the DBG_VALUE becomes a
  // use-before-def, resulting in a loss of debug info.

  // Example:
  // Before the Pre Register Allocation Load Store Pass
  // inst_a
  // %2 = ld ...
  // inst_b
  // DBG_VALUE %2, "x", ...
  // %3 = ld ...

  // After the Pass:
  // inst_a
  // inst_b
  // DBG_VALUE %2, "x", ...
  // %2 = ld ...
  // %3 = ld ...

  // The code below addresses this by moving the DBG_VALUE to the position
  // immediately after the load.

  // Example:
  // After the code below:
  // inst_a
  // inst_b
  // %2 = ld ...
  // DBG_VALUE %2, "x", ...
  // %3 = ld ...

  // The algorithm works in two phases: First RescheduleOps() populates the
  // RegisterMap with registers that were moved as keys, there is no value
  // inserted. In the next phase, every MachineInstr in a basic block is
  // iterated over. If it is a valid DBG_VALUE or DBG_VALUE_LIST and it uses one
  // or more registers in the RegisterMap, the RegisterMap and InstrMap are
  // populated with the MachineInstr. If the DBG_VALUE or DBG_VALUE_LIST
  // describes debug information for a variable that already exists in the
  // DbgValueSinkCandidates, the MachineInstr in the DbgValueSinkCandidates must
  // be set to undef. If the current MachineInstr is a load that was moved,
  // undef the corresponding DBG_VALUE or DBG_VALUE_LIST and clone it to below
  // the load.

  // To illustrate the above algorithm visually let's take this example.

  // Before the Pre Register Allocation Load Store Pass:
  // %2 = ld ...
  // DBG_VALUE %2, A, .... # X
  // DBG_VALUE 0, A, ... # Y
  // %3 = ld ...
  // DBG_VALUE %3, A, ..., # Z
  // %4 = ld ...

  // After Pre Register Allocation Load Store Pass:
  // DBG_VALUE %2, A, .... # X
  // DBG_VALUE 0, A, ... # Y
  // DBG_VALUE %3, A, ..., # Z
  // %2 = ld ...
  // %3 = ld ...
  // %4 = ld ...

  // The algorithm below does the following:

  // In the beginning, the RegisterMap will have been populated with the virtual
  // registers %2, and %3, the DbgValueSinkCandidates and the InstrMap will be
  // empty. DbgValueSinkCandidates = {}, RegisterMap = {2 -> {}, 3 -> {}},
  // InstrMap {}
  // -> DBG_VALUE %2, A, .... # X
  // DBG_VALUE 0, A, ... # Y
  // DBG_VALUE %3, A, ..., # Z
  // %2 = ld ...
  // %3 = ld ...
  // %4 = ld ...

  // After the first DBG_VALUE (denoted with an X) is processed, the
  // DbgValueSinkCandidates and InstrMap will be populated and the RegisterMap
  // entry for %2 will be populated as well. DbgValueSinkCandidates = {A -> X},
  // RegisterMap = {2 -> {X}, 3 -> {}}, InstrMap {X -> 2}
  // DBG_VALUE %2, A, .... # X
  // -> DBG_VALUE 0, A, ... # Y
  // DBG_VALUE %3, A, ..., # Z
  // %2 = ld ...
  // %3 = ld ...
  // %4 = ld ...

  // After the DBG_VALUE Y is processed, the DbgValueSinkCandidates is updated
  // to now hold Y for A and the RegisterMap is also updated to remove X from
  // %2, this is because both X and Y describe the same debug variable A. X is
  // also updated to have a $noreg as the first operand.
  // DbgValueSinkCandidates = {A -> {Y}}, RegisterMap = {2 -> {}, 3 -> {}},
  // InstrMap = {X-> 2}
  // DBG_VALUE $noreg, A, .... # X
  // DBG_VALUE 0, A, ... # Y
  // -> DBG_VALUE %3, A, ..., # Z
  // %2 = ld ...
  // %3 = ld ...
  // %4 = ld ...

  // After DBG_VALUE Z is processed, the DbgValueSinkCandidates is updated to
  // hold Z fr A, the RegisterMap is updated to hold Z for %3, and the InstrMap
  // is updated to have Z mapped to %3. This is again because Z describes the
  // debug variable A, Y is not updated to have $noreg as first operand because
  // its first operand is an immediate, not a register.
  // DbgValueSinkCandidates = {A -> {Z}}, RegisterMap = {2 -> {}, 3 -> {Z}},
  // InstrMap = {X -> 2, Z -> 3}
  // DBG_VALUE $noreg, A, .... # X
  // DBG_VALUE 0, A, ... # Y
  // DBG_VALUE %3, A, ..., # Z
  // -> %2 = ld ...
  // %3 = ld ...
  // %4 = ld ...

  // Nothing happens here since the RegisterMap for %2 contains no value.
  // DbgValueSinkCandidates = {A -> {Z}}, RegisterMap = {2 -> {}, 3 -> {Z}},
  // InstrMap = {X -> 2, Z -> 3}
  // DBG_VALUE $noreg, A, .... # X
  // DBG_VALUE 0, A, ... # Y
  // DBG_VALUE %3, A, ..., # Z
  // %2 = ld ...
  // -> %3 = ld ...
  // %4 = ld ...

  // Since the RegisterMap contains Z as a value for %3, the MachineInstr
  // pointer Z is copied to come after the load for %3 and the old Z's first
  // operand is changed to $noreg the Basic Block iterator is moved to after the
  // DBG_VALUE Z's new position.
  // DbgValueSinkCandidates = {A -> {Z}}, RegisterMap = {2 -> {}, 3 -> {Z}},
  // InstrMap = {X -> 2, Z -> 3}
  // DBG_VALUE $noreg, A, .... # X
  // DBG_VALUE 0, A, ... # Y
  // DBG_VALUE $noreg, A, ..., # Old Z
  // %2 = ld ...
  // %3 = ld ...
  // DBG_VALUE %3, A, ..., # Z
  // -> %4 = ld ...

  // Nothing happens for %4 and the algorithm exits having processed the entire
  // Basic Block.
  // DbgValueSinkCandidates = {A -> {Z}}, RegisterMap = {2 -> {}, 3 -> {Z}},
  // InstrMap = {X -> 2, Z -> 3}
  // DBG_VALUE $noreg, A, .... # X
  // DBG_VALUE 0, A, ... # Y
  // DBG_VALUE $noreg, A, ..., # Old Z
  // %2 = ld ...
  // %3 = ld ...
  // DBG_VALUE %3, A, ..., # Z
  // %4 = ld ...

  // This map is used to track the relationship between
  // a Debug Variable and the DBG_VALUE MachineInstr pointer that describes the
  // debug information for that Debug Variable.
  SmallDenseMap<DebugVariable, MachineInstr *, 8> DbgValueSinkCandidates;
  // This map is used to track the relationship between a DBG_VALUE or
  // DBG_VALUE_LIST MachineInstr pointer and Registers that it uses.
  SmallDenseMap<MachineInstr *, SmallVector<Register>, 8> InstrMap;
  for (MBBI = MBB->begin(), E = MBB->end(); MBBI != E; ++MBBI) {
    MachineInstr &MI = *MBBI;

    auto PopulateRegisterAndInstrMapForDebugInstr = [&](Register Reg) {
      auto RegIt = RegisterMap.find(Reg);
      if (RegIt == RegisterMap.end())
        return;
      auto &InstrVec = RegIt->getSecond();
      InstrVec.push_back(&MI);
      InstrMap[&MI].push_back(Reg);
    };

    if (MI.isDebugValue()) {
      assert(MI.getDebugVariable() &&
             "DBG_VALUE or DBG_VALUE_LIST must contain a DILocalVariable");

      auto DbgVar = createDebugVariableFromMachineInstr(&MI);
      // If the first operand is a register and it exists in the RegisterMap, we
      // know this is a DBG_VALUE that uses the result of a load that was moved,
      // and is therefore a candidate to also be moved, add it to the
      // RegisterMap and InstrMap.
      forEachDbgRegOperand(&MI, [&](MachineOperand &Op) {
        PopulateRegisterAndInstrMapForDebugInstr(Op.getReg());
      });

      // If the current DBG_VALUE describes the same variable as one of the
      // in-flight DBG_VALUEs, remove the candidate from the list and set it to
      // undef. Moving one DBG_VALUE past another would result in the variable's
      // value going back in time when stepping through the block in the
      // debugger.
      auto InstrIt = DbgValueSinkCandidates.find(DbgVar);
      if (InstrIt != DbgValueSinkCandidates.end()) {
        auto *Instr = InstrIt->getSecond();
        auto RegIt = InstrMap.find(Instr);
        if (RegIt != InstrMap.end()) {
          const auto &RegVec = RegIt->getSecond();
          // For every Register in the RegVec, remove the MachineInstr in the
          // RegisterMap that describes the DbgVar.
          for (auto &Reg : RegVec) {
            auto RegIt = RegisterMap.find(Reg);
            if (RegIt == RegisterMap.end())
              continue;
            auto &InstrVec = RegIt->getSecond();
            auto IsDbgVar = [&](MachineInstr *I) -> bool {
              auto Var = createDebugVariableFromMachineInstr(I);
              return Var == DbgVar;
            };

            llvm::erase_if(InstrVec, IsDbgVar);
          }
          forEachDbgRegOperand(Instr,
                               [&](MachineOperand &Op) { Op.setReg(0); });
        }
      }
      DbgValueSinkCandidates[DbgVar] = &MI;
    } else {
      // If the first operand of a load matches with a DBG_VALUE in RegisterMap,
      // then move that DBG_VALUE to below the load.
      auto Opc = MI.getOpcode();
      if (!isLoadSingle(Opc))
        continue;
      auto Reg = MI.getOperand(0).getReg();
      auto RegIt = RegisterMap.find(Reg);
      if (RegIt == RegisterMap.end())
        continue;
      auto &DbgInstrVec = RegIt->getSecond();
      if (!DbgInstrVec.size())
        continue;
      for (auto *DbgInstr : DbgInstrVec) {
        MachineBasicBlock::iterator InsertPos = std::next(MBBI);
        auto *ClonedMI = MI.getMF()->CloneMachineInstr(DbgInstr);
        MBB->insert(InsertPos, ClonedMI);
        MBBI++;
        //  Erase the entry into the DbgValueSinkCandidates for the DBG_VALUE
        //  that was moved.
        auto DbgVar = createDebugVariableFromMachineInstr(DbgInstr);
        // Erase DbgVar from DbgValueSinkCandidates if still present.  If the
        // instruction is a DBG_VALUE_LIST, it may have already been erased from
        // DbgValueSinkCandidates.
        DbgValueSinkCandidates.erase(DbgVar);
        // Zero out original dbg instr
        forEachDbgRegOperand(DbgInstr,
                             [&](MachineOperand &Op) { Op.setReg(0); });
        // Update RegisterMap with ClonedMI because it might have to be moved
        // again.
        if (DbgInstr->isDebugValueList())
          updateRegisterMapForDbgValueListAfterMove(RegisterMap, ClonedMI,
                                                    DbgInstr);
      }
    }
  }
  return RetVal;
}

// Get the Base register operand index from the memory access MachineInst if we
// should attempt to distribute postinc on it. Return -1 if not of a valid
// instruction type. If it returns an index, it is assumed that instruction is a
// r+i indexing mode, and getBaseOperandIndex() + 1 is the Offset index.
static int getBaseOperandIndex(MachineInstr &MI) {
  switch (MI.getOpcode()) {
  case ARM::MVE_VLDRBS16:
  case ARM::MVE_VLDRBS32:
  case ARM::MVE_VLDRBU16:
  case ARM::MVE_VLDRBU32:
  case ARM::MVE_VLDRHS32:
  case ARM::MVE_VLDRHU32:
  case ARM::MVE_VLDRBU8:
  case ARM::MVE_VLDRHU16:
  case ARM::MVE_VLDRWU32:
  case ARM::MVE_VSTRB16:
  case ARM::MVE_VSTRB32:
  case ARM::MVE_VSTRH32:
  case ARM::MVE_VSTRBU8:
  case ARM::MVE_VSTRHU16:
  case ARM::MVE_VSTRWU32:
  case ARM::t2LDRHi8:
  case ARM::t2LDRHi12:
  case ARM::t2LDRSHi8:
  case ARM::t2LDRSHi12:
  case ARM::t2LDRBi8:
  case ARM::t2LDRBi12:
  case ARM::t2LDRSBi8:
  case ARM::t2LDRSBi12:
  case ARM::t2STRBi8:
  case ARM::t2STRBi12:
  case ARM::t2STRHi8:
  case ARM::t2STRHi12:
    return 1;
  case ARM::MVE_VLDRBS16_post:
  case ARM::MVE_VLDRBS32_post:
  case ARM::MVE_VLDRBU16_post:
  case ARM::MVE_VLDRBU32_post:
  case ARM::MVE_VLDRHS32_post:
  case ARM::MVE_VLDRHU32_post:
  case ARM::MVE_VLDRBU8_post:
  case ARM::MVE_VLDRHU16_post:
  case ARM::MVE_VLDRWU32_post:
  case ARM::MVE_VSTRB16_post:
  case ARM::MVE_VSTRB32_post:
  case ARM::MVE_VSTRH32_post:
  case ARM::MVE_VSTRBU8_post:
  case ARM::MVE_VSTRHU16_post:
  case ARM::MVE_VSTRWU32_post:
  case ARM::MVE_VLDRBS16_pre:
  case ARM::MVE_VLDRBS32_pre:
  case ARM::MVE_VLDRBU16_pre:
  case ARM::MVE_VLDRBU32_pre:
  case ARM::MVE_VLDRHS32_pre:
  case ARM::MVE_VLDRHU32_pre:
  case ARM::MVE_VLDRBU8_pre:
  case ARM::MVE_VLDRHU16_pre:
  case ARM::MVE_VLDRWU32_pre:
  case ARM::MVE_VSTRB16_pre:
  case ARM::MVE_VSTRB32_pre:
  case ARM::MVE_VSTRH32_pre:
  case ARM::MVE_VSTRBU8_pre:
  case ARM::MVE_VSTRHU16_pre:
  case ARM::MVE_VSTRWU32_pre:
    return 2;
  }
  return -1;
}

static bool isPostIndex(MachineInstr &MI) {
  switch (MI.getOpcode()) {
  case ARM::MVE_VLDRBS16_post:
  case ARM::MVE_VLDRBS32_post:
  case ARM::MVE_VLDRBU16_post:
  case ARM::MVE_VLDRBU32_post:
  case ARM::MVE_VLDRHS32_post:
  case ARM::MVE_VLDRHU32_post:
  case ARM::MVE_VLDRBU8_post:
  case ARM::MVE_VLDRHU16_post:
  case ARM::MVE_VLDRWU32_post:
  case ARM::MVE_VSTRB16_post:
  case ARM::MVE_VSTRB32_post:
  case ARM::MVE_VSTRH32_post:
  case ARM::MVE_VSTRBU8_post:
  case ARM::MVE_VSTRHU16_post:
  case ARM::MVE_VSTRWU32_post:
    return true;
  }
  return false;
}

static bool isPreIndex(MachineInstr &MI) {
  switch (MI.getOpcode()) {
  case ARM::MVE_VLDRBS16_pre:
  case ARM::MVE_VLDRBS32_pre:
  case ARM::MVE_VLDRBU16_pre:
  case ARM::MVE_VLDRBU32_pre:
  case ARM::MVE_VLDRHS32_pre:
  case ARM::MVE_VLDRHU32_pre:
  case ARM::MVE_VLDRBU8_pre:
  case ARM::MVE_VLDRHU16_pre:
  case ARM::MVE_VLDRWU32_pre:
  case ARM::MVE_VSTRB16_pre:
  case ARM::MVE_VSTRB32_pre:
  case ARM::MVE_VSTRH32_pre:
  case ARM::MVE_VSTRBU8_pre:
  case ARM::MVE_VSTRHU16_pre:
  case ARM::MVE_VSTRWU32_pre:
    return true;
  }
  return false;
}

// Given a memory access Opcode, check that the give Imm would be a valid Offset
// for this instruction (same as isLegalAddressImm), Or if the instruction
// could be easily converted to one where that was valid. For example converting
// t2LDRi12 to t2LDRi8 for negative offsets. Works in conjunction with
// AdjustBaseAndOffset below.
static bool isLegalOrConvertibleAddressImm(unsigned Opcode, int Imm,
                                           const TargetInstrInfo *TII,
                                           int &CodesizeEstimate) {
  if (isLegalAddressImm(Opcode, Imm, TII))
    return true;

  // We can convert AddrModeT2_i12 to AddrModeT2_i8neg.
  const MCInstrDesc &Desc = TII->get(Opcode);
  unsigned AddrMode = (Desc.TSFlags & ARMII::AddrModeMask);
  switch (AddrMode) {
  case ARMII::AddrModeT2_i12:
    CodesizeEstimate += 1;
    return Imm < 0 && -Imm < ((1 << 8) * 1);
  }
  return false;
}

// Given an MI adjust its address BaseReg to use NewBaseReg and address offset
// by -Offset. This can either happen in-place or be a replacement as MI is
// converted to another instruction type.
static void AdjustBaseAndOffset(MachineInstr *MI, Register NewBaseReg,
                                int Offset, const TargetInstrInfo *TII,
                                const TargetRegisterInfo *TRI) {
  // Set the Base reg
  unsigned BaseOp = getBaseOperandIndex(*MI);
  MI->getOperand(BaseOp).setReg(NewBaseReg);
  // and constrain the reg class to that required by the instruction.
  MachineFunction *MF = MI->getMF();
  MachineRegisterInfo &MRI = MF->getRegInfo();
  const MCInstrDesc &MCID = TII->get(MI->getOpcode());
  const TargetRegisterClass *TRC = TII->getRegClass(MCID, BaseOp);
  MRI.constrainRegClass(NewBaseReg, TRC);

  int OldOffset = MI->getOperand(BaseOp + 1).getImm();
  if (isLegalAddressImm(MI->getOpcode(), OldOffset - Offset, TII))
    MI->getOperand(BaseOp + 1).setImm(OldOffset - Offset);
  else {
    unsigned ConvOpcode;
    switch (MI->getOpcode()) {
    case ARM::t2LDRHi12:
      ConvOpcode = ARM::t2LDRHi8;
      break;
    case ARM::t2LDRSHi12:
      ConvOpcode = ARM::t2LDRSHi8;
      break;
    case ARM::t2LDRBi12:
      ConvOpcode = ARM::t2LDRBi8;
      break;
    case ARM::t2LDRSBi12:
      ConvOpcode = ARM::t2LDRSBi8;
      break;
    case ARM::t2STRHi12:
      ConvOpcode = ARM::t2STRHi8;
      break;
    case ARM::t2STRBi12:
      ConvOpcode = ARM::t2STRBi8;
      break;
    default:
      llvm_unreachable("Unhandled convertible opcode");
    }
    assert(isLegalAddressImm(ConvOpcode, OldOffset - Offset, TII) &&
           "Illegal Address Immediate after convert!");

    const MCInstrDesc &MCID = TII->get(ConvOpcode);
    BuildMI(*MI->getParent(), MI, MI->getDebugLoc(), MCID)
        .add(MI->getOperand(0))
        .add(MI->getOperand(1))
        .addImm(OldOffset - Offset)
        .add(MI->getOperand(3))
        .add(MI->getOperand(4))
        .cloneMemRefs(*MI);
    MI->eraseFromParent();
  }
}

static MachineInstr *createPostIncLoadStore(MachineInstr *MI, int Offset,
                                            Register NewReg,
                                            const TargetInstrInfo *TII,
                                            const TargetRegisterInfo *TRI) {
  MachineFunction *MF = MI->getMF();
  MachineRegisterInfo &MRI = MF->getRegInfo();

  unsigned NewOpcode = getPostIndexedLoadStoreOpcode(
      MI->getOpcode(), Offset > 0 ? ARM_AM::add : ARM_AM::sub);

  const MCInstrDesc &MCID = TII->get(NewOpcode);
  // Constrain the def register class
  const TargetRegisterClass *TRC = TII->getRegClass(MCID, 0);
  MRI.constrainRegClass(NewReg, TRC);
  // And do the same for the base operand
  TRC = TII->getRegClass(MCID, 2);
  MRI.constrainRegClass(MI->getOperand(1).getReg(), TRC);

  unsigned AddrMode = (MCID.TSFlags & ARMII::AddrModeMask);
  switch (AddrMode) {
  case ARMII::AddrModeT2_i7:
  case ARMII::AddrModeT2_i7s2:
  case ARMII::AddrModeT2_i7s4:
    // Any MVE load/store
    return BuildMI(*MI->getParent(), MI, MI->getDebugLoc(), MCID)
        .addReg(NewReg, RegState::Define)
        .add(MI->getOperand(0))
        .add(MI->getOperand(1))
        .addImm(Offset)
        .add(MI->getOperand(3))
        .add(MI->getOperand(4))
        .add(MI->getOperand(5))
        .cloneMemRefs(*MI);
  case ARMII::AddrModeT2_i8:
    if (MI->mayLoad()) {
      return BuildMI(*MI->getParent(), MI, MI->getDebugLoc(), MCID)
          .add(MI->getOperand(0))
          .addReg(NewReg, RegState::Define)
          .add(MI->getOperand(1))
          .addImm(Offset)
          .add(MI->getOperand(3))
          .add(MI->getOperand(4))
          .cloneMemRefs(*MI);
    } else {
      return BuildMI(*MI->getParent(), MI, MI->getDebugLoc(), MCID)
          .addReg(NewReg, RegState::Define)
          .add(MI->getOperand(0))
          .add(MI->getOperand(1))
          .addImm(Offset)
          .add(MI->getOperand(3))
          .add(MI->getOperand(4))
          .cloneMemRefs(*MI);
    }
  default:
    llvm_unreachable("Unhandled createPostIncLoadStore");
  }
}

// Given a Base Register, optimise the load/store uses to attempt to create more
// post-inc accesses and less register moves. We do this by taking zero offset
// loads/stores with an add, and convert them to a postinc load/store of the
// same type. Any subsequent accesses will be adjusted to use and account for
// the post-inc value.
// For example:
// LDR #0            LDR_POSTINC #16
// LDR #4            LDR #-12
// LDR #8            LDR #-8
// LDR #12           LDR #-4
// ADD #16
//
// At the same time if we do not find an increment but do find an existing
// pre/post inc instruction, we can still adjust the offsets of subsequent
// instructions to save the register move that would otherwise be needed for the
// in-place increment.
bool ARMPreAllocLoadStoreOpt::DistributeIncrements(Register Base) {
  // We are looking for:
  // One zero offset load/store that can become postinc
  MachineInstr *BaseAccess = nullptr;
  MachineInstr *PrePostInc = nullptr;
  // An increment that can be folded in
  MachineInstr *Increment = nullptr;
  // Other accesses after BaseAccess that will need to be updated to use the
  // postinc value.
  SmallPtrSet<MachineInstr *, 8> OtherAccesses;
  for (auto &Use : MRI->use_nodbg_instructions(Base)) {
    if (!Increment && getAddSubImmediate(Use) != 0) {
      Increment = &Use;
      continue;
    }

    int BaseOp = getBaseOperandIndex(Use);
    if (BaseOp == -1)
      return false;

    if (!Use.getOperand(BaseOp).isReg() ||
        Use.getOperand(BaseOp).getReg() != Base)
      return false;
    if (isPreIndex(Use) || isPostIndex(Use))
      PrePostInc = &Use;
    else if (Use.getOperand(BaseOp + 1).getImm() == 0)
      BaseAccess = &Use;
    else
      OtherAccesses.insert(&Use);
  }

  int IncrementOffset;
  Register NewBaseReg;
  if (BaseAccess && Increment) {
    if (PrePostInc || BaseAccess->getParent() != Increment->getParent())
      return false;
    Register PredReg;
    if (Increment->definesRegister(ARM::CPSR, /*TRI=*/nullptr) ||
        getInstrPredicate(*Increment, PredReg) != ARMCC::AL)
      return false;

    LLVM_DEBUG(dbgs() << "\nAttempting to distribute increments on VirtualReg "
                      << Base.virtRegIndex() << "\n");

    // Make sure that Increment has no uses before BaseAccess that are not PHI
    // uses.
    for (MachineInstr &Use :
        MRI->use_nodbg_instructions(Increment->getOperand(0).getReg())) {
      if (&Use == BaseAccess || (Use.getOpcode() != TargetOpcode::PHI &&
                                 !DT->dominates(BaseAccess, &Use))) {
        LLVM_DEBUG(dbgs() << "  BaseAccess doesn't dominate use of increment\n");
        return false;
      }
    }

    // Make sure that Increment can be folded into Base
    IncrementOffset = getAddSubImmediate(*Increment);
    unsigned NewPostIncOpcode = getPostIndexedLoadStoreOpcode(
        BaseAccess->getOpcode(), IncrementOffset > 0 ? ARM_AM::add : ARM_AM::sub);
    if (!isLegalAddressImm(NewPostIncOpcode, IncrementOffset, TII)) {
      LLVM_DEBUG(dbgs() << "  Illegal addressing mode immediate on postinc\n");
      return false;
    }
  }
  else if (PrePostInc) {
    // If we already have a pre/post index load/store then set BaseAccess,
    // IncrementOffset and NewBaseReg to the values it already produces,
    // allowing us to update and subsequent uses of BaseOp reg with the
    // incremented value.
    if (Increment)
      return false;

    LLVM_DEBUG(dbgs() << "\nAttempting to distribute increments on already "
                      << "indexed VirtualReg " << Base.virtRegIndex() << "\n");
    int BaseOp = getBaseOperandIndex(*PrePostInc);
    IncrementOffset = PrePostInc->getOperand(BaseOp+1).getImm();
    BaseAccess = PrePostInc;
    NewBaseReg = PrePostInc->getOperand(0).getReg();
  }
  else
    return false;

  // And make sure that the negative value of increment can be added to all
  // other offsets after the BaseAccess. We rely on either
  // dominates(BaseAccess, OtherAccess) or dominates(OtherAccess, BaseAccess)
  // to keep things simple.
  // This also adds a simple codesize metric, to detect if an instruction (like
  // t2LDRBi12) which can often be shrunk to a thumb1 instruction (tLDRBi)
  // cannot because it is converted to something else (t2LDRBi8). We start this
  // at -1 for the gain from removing the increment.
  SmallPtrSet<MachineInstr *, 4> SuccessorAccesses;
  int CodesizeEstimate = -1;
  for (auto *Use : OtherAccesses) {
    if (DT->dominates(BaseAccess, Use)) {
      SuccessorAccesses.insert(Use);
      unsigned BaseOp = getBaseOperandIndex(*Use);
      if (!isLegalOrConvertibleAddressImm(Use->getOpcode(),
                                          Use->getOperand(BaseOp + 1).getImm() -
                                              IncrementOffset,
                                          TII, CodesizeEstimate)) {
        LLVM_DEBUG(dbgs() << "  Illegal addressing mode immediate on use\n");
        return false;
      }
    } else if (!DT->dominates(Use, BaseAccess)) {
      LLVM_DEBUG(
          dbgs() << "  Unknown dominance relation between Base and Use\n");
      return false;
    }
  }
  if (STI->hasMinSize() && CodesizeEstimate > 0) {
    LLVM_DEBUG(dbgs() << "  Expected to grow instructions under minsize\n");
    return false;
  }

  if (!PrePostInc) {
    // Replace BaseAccess with a post inc
    LLVM_DEBUG(dbgs() << "Changing: "; BaseAccess->dump());
    LLVM_DEBUG(dbgs() << "  And   : "; Increment->dump());
    NewBaseReg = Increment->getOperand(0).getReg();
    MachineInstr *BaseAccessPost =
        createPostIncLoadStore(BaseAccess, IncrementOffset, NewBaseReg, TII, TRI);
    BaseAccess->eraseFromParent();
    Increment->eraseFromParent();
    (void)BaseAccessPost;
    LLVM_DEBUG(dbgs() << "  To    : "; BaseAccessPost->dump());
  }

  for (auto *Use : SuccessorAccesses) {
    LLVM_DEBUG(dbgs() << "Changing: "; Use->dump());
    AdjustBaseAndOffset(Use, NewBaseReg, IncrementOffset, TII, TRI);
    LLVM_DEBUG(dbgs() << "  To    : "; Use->dump());
  }

  // Remove the kill flag from all uses of NewBaseReg, in case any old uses
  // remain.
  for (MachineOperand &Op : MRI->use_nodbg_operands(NewBaseReg))
    Op.setIsKill(false);
  return true;
}

bool ARMPreAllocLoadStoreOpt::DistributeIncrements() {
  bool Changed = false;
  SmallSetVector<Register, 4> Visited;
  for (auto &MBB : *MF) {
    for (auto &MI : MBB) {
      int BaseOp = getBaseOperandIndex(MI);
      if (BaseOp == -1 || !MI.getOperand(BaseOp).isReg())
        continue;

      Register Base = MI.getOperand(BaseOp).getReg();
      if (!Base.isVirtual())
        continue;

      Visited.insert(Base);
    }
  }

  for (auto Base : Visited)
    Changed |= DistributeIncrements(Base);

  return Changed;
}

/// Returns an instance of the load / store optimization pass.
FunctionPass *llvm::createARMLoadStoreOptLegacyPass(bool PreAlloc) {
  if (PreAlloc)
    return new ARMPreAllocLoadStoreOptLegacy();
  return new ARMLoadStoreOptLegacy();
}

PreservedAnalyses
ARMLoadStoreOptPass::run(MachineFunction &MF,
                         MachineFunctionAnalysisManager &MFAM) {
  ARMLoadStoreOpt Impl;
  bool Changed = Impl.runOnMachineFunction(
      MF, MFAM.getResult<MachineRegisterClassAnalysis>(MF));
  if (!Changed)
    return PreservedAnalyses::all();
  PreservedAnalyses PA = getMachineFunctionPassPreservedAnalyses();
  PA.preserveSet<CFGAnalyses>();
  PA.preserve<MachineRegisterClassAnalysis>();
  return PA;
}

PreservedAnalyses
ARMPreAllocLoadStoreOptPass::run(MachineFunction &MF,
                                 MachineFunctionAnalysisManager &MFAM) {
  ARMPreAllocLoadStoreOpt Impl;
  AliasAnalysis *AA =
      &MFAM.getResult<FunctionAnalysisManagerMachineFunctionProxy>(MF)
           .getManager()
           .getResult<AAManager>(MF.getFunction());
  MachineDominatorTree *DT = &MFAM.getResult<MachineDominatorTreeAnalysis>(MF);
  bool Changed = Impl.runOnMachineFunction(MF, AA, DT);
  if (!Changed)
    return PreservedAnalyses::all();
  PreservedAnalyses PA = getMachineFunctionPassPreservedAnalyses();
  PA.preserveSet<CFGAnalyses>();
  return PA;
}
