#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/DerivedTypes.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 <algorithm>
#include <cassert>
#include <cstddef>
#include <cstdlib>
#include <iterator>
#include <limits>
#include <utility>
usingnamespacellvm;
#define DEBUG_TYPE …
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");
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 …
namespace {
struct ARMLoadStoreOpt : public MachineFunctionPass { … };
}
char ARMLoadStoreOpt::ID = …;
INITIALIZE_PASS(…)
static bool definesCPSR(const MachineInstr &MI) { … }
static int getMemoryOpOffset(const MachineInstr &MI) { … }
static const MachineOperand &getLoadStoreBaseOp(const MachineInstr &MI) { … }
static const MachineOperand &getLoadStoreRegOp(const MachineInstr &MI) { … }
static int getLoadStoreMultipleOpcode(unsigned Opcode, ARM_AM::AMSubMode Mode) { … }
static ARM_AM::AMSubMode getLoadStoreMultipleSubMode(unsigned Opcode) { … }
static bool isT1i32Load(unsigned Opc) { … }
static bool isT2i32Load(unsigned Opc) { … }
static bool isi32Load(unsigned Opc) { … }
static bool isT1i32Store(unsigned Opc) { … }
static bool isT2i32Store(unsigned Opc) { … }
static bool isi32Store(unsigned Opc) { … }
static bool isLoadSingle(unsigned Opc) { … }
static unsigned getImmScale(unsigned Opc) { … }
static unsigned getLSMultipleTransferSize(const MachineInstr *MI) { … }
void ARMLoadStoreOpt::UpdateBaseRegUses(MachineBasicBlock &MBB,
MachineBasicBlock::iterator MBBI,
const DebugLoc &DL, unsigned Base,
unsigned WordOffset,
ARMCC::CondCodes Pred,
unsigned PredReg) { … }
unsigned ARMLoadStoreOpt::findFreeReg(const TargetRegisterClass &RegClass) { … }
void ARMLoadStoreOpt::moveLiveRegsBefore(const MachineBasicBlock &MBB,
MachineBasicBlock::const_iterator Before) { … }
static bool ContainsReg(const ArrayRef<std::pair<unsigned, bool>> &Regs,
unsigned Reg) { … }
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) { … }
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 { … }
MachineInstr *ARMLoadStoreOpt::MergeOpsUpdate(const MergeCandidate &Cand) { … }
static bool isValidLSDoubleOffset(int Offset) { … }
static bool mayCombineMisaligned(const TargetSubtargetInfo &STI,
const MachineInstr &MI) { … }
void ARMLoadStoreOpt::FormCandidates(const MemOpQueue &MemOps) { … }
static unsigned getUpdatingLSMultipleOpcode(unsigned Opc,
ARM_AM::AMSubMode Mode) { … }
static int isIncrementOrDecrement(const MachineInstr &MI, Register Reg,
ARMCC::CondCodes Pred, Register PredReg) { … }
static MachineBasicBlock::iterator
findIncDecBefore(MachineBasicBlock::iterator MBBI, Register Reg,
ARMCC::CondCodes Pred, Register PredReg, int &Offset) { … }
static MachineBasicBlock::iterator
findIncDecAfter(MachineBasicBlock::iterator MBBI, Register Reg,
ARMCC::CondCodes Pred, Register PredReg, int &Offset,
const TargetRegisterInfo *TRI) { … }
bool ARMLoadStoreOpt::MergeBaseUpdateLSMultiple(MachineInstr *MI) { … }
static unsigned getPreIndexedLoadStoreOpcode(unsigned Opc,
ARM_AM::AddrOpc Mode) { … }
static unsigned getPostIndexedLoadStoreOpcode(unsigned Opc,
ARM_AM::AddrOpc Mode) { … }
bool ARMLoadStoreOpt::MergeBaseUpdateLoadStore(MachineInstr *MI) { … }
bool ARMLoadStoreOpt::MergeBaseUpdateLSDouble(MachineInstr &MI) const { … }
static bool isMemoryOp(const MachineInstr &MI) { … }
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) { … }
bool ARMLoadStoreOpt::FixInvalidRegPairOp(MachineBasicBlock &MBB,
MachineBasicBlock::iterator &MBBI) { … }
bool ARMLoadStoreOpt::LoadStoreMultipleOpti(MachineBasicBlock &MBB) { … }
bool ARMLoadStoreOpt::MergeReturnIntoLDM(MachineBasicBlock &MBB) { … }
bool ARMLoadStoreOpt::CombineMovBx(MachineBasicBlock &MBB) { … }
bool ARMLoadStoreOpt::runOnMachineFunction(MachineFunction &Fn) { … }
#define ARM_PREALLOC_LOAD_STORE_OPT_NAME …
namespace {
struct ARMPreAllocLoadStoreOpt : public MachineFunctionPass{ … };
}
char ARMPreAllocLoadStoreOpt::ID = …;
INITIALIZE_PASS_BEGIN(ARMPreAllocLoadStoreOpt, "arm-prera-ldst-opt",
ARM_PREALLOC_LOAD_STORE_OPT_NAME, false, false)
INITIALIZE_PASS_DEPENDENCY(MachineDominatorTreeWrapperPass)
INITIALIZE_PASS_END(ARMPreAllocLoadStoreOpt, "arm-prera-ldst-opt",
ARM_PREALLOC_LOAD_STORE_OPT_NAME, false, false)
static cl::opt<unsigned> InstReorderLimit("arm-prera-ldst-opt-reorder-limit",
cl::init(8), cl::Hidden);
bool ARMPreAllocLoadStoreOpt::runOnMachineFunction(MachineFunction &Fn) { … }
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) { … }
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) { … }
bool ARMPreAllocLoadStoreOpt::RescheduleOps(
MachineBasicBlock *MBB, SmallVectorImpl<MachineInstr *> &Ops, unsigned Base,
bool isLd, DenseMap<MachineInstr *, unsigned> &MI2LocMap,
SmallDenseMap<Register, SmallVector<MachineInstr *>, 8> &RegisterMap) { … }
static void forEachDbgRegOperand(MachineInstr *MI,
std::function<void(MachineOperand &)> Fn) { … }
static void updateRegisterMapForDbgValueListAfterMove(
SmallDenseMap<Register, SmallVector<MachineInstr *>, 8> &RegisterMap,
MachineInstr *DbgValueListInstr, MachineInstr *InstrToReplace) { … }
static DebugVariable createDebugVariableFromMachineInstr(MachineInstr *MI) { … }
bool
ARMPreAllocLoadStoreOpt::RescheduleLoadStoreInstrs(MachineBasicBlock *MBB) { … }
static int getBaseOperandIndex(MachineInstr &MI) { … }
static bool isPostIndex(MachineInstr &MI) { … }
static bool isPreIndex(MachineInstr &MI) { … }
static bool isLegalOrConvertableAddressImm(unsigned Opcode, int Imm,
const TargetInstrInfo *TII,
int &CodesizeEstimate) { … }
static void AdjustBaseAndOffset(MachineInstr *MI, Register NewBaseReg,
int Offset, const TargetInstrInfo *TII,
const TargetRegisterInfo *TRI) { … }
static MachineInstr *createPostIncLoadStore(MachineInstr *MI, int Offset,
Register NewReg,
const TargetInstrInfo *TII,
const TargetRegisterInfo *TRI) { … }
bool ARMPreAllocLoadStoreOpt::DistributeIncrements(Register Base) { … }
bool ARMPreAllocLoadStoreOpt::DistributeIncrements() { … }
FunctionPass *llvm::createARMLoadStoreOptimizationPass(bool PreAlloc) { … }