diff --git a/llvm/lib/Target/ARM/Thumb1InstrInfo.h b/llvm/lib/Target/ARM/Thumb1InstrInfo.h --- a/llvm/lib/Target/ARM/Thumb1InstrInfo.h +++ b/llvm/lib/Target/ARM/Thumb1InstrInfo.h @@ -53,6 +53,15 @@ const TargetRegisterInfo *TRI) const override; bool canCopyGluedNodeDuringSchedule(SDNode *N) const override; + + // foldMemoryOperand + using TargetInstrInfo::foldMemoryOperandImpl; + + virtual MachineInstr *foldMemoryOperandImpl( + MachineFunction &MF, MachineInstr &MI, ArrayRef Ops, + MachineBasicBlock::iterator InsertPt, MachineInstr &LoadMI, + LiveIntervals *LIS = nullptr) const override; + private: void expandLoadStackGuard(MachineBasicBlock::iterator MI) const override; }; diff --git a/llvm/lib/Target/ARM/Thumb1InstrInfo.cpp b/llvm/lib/Target/ARM/Thumb1InstrInfo.cpp --- a/llvm/lib/Target/ARM/Thumb1InstrInfo.cpp +++ b/llvm/lib/Target/ARM/Thumb1InstrInfo.cpp @@ -152,3 +152,34 @@ return false; } + +MachineInstr *Thumb1InstrInfo::foldMemoryOperandImpl( + MachineFunction &MF, MachineInstr &MI, ArrayRef Ops, + MachineBasicBlock::iterator InsertPt, MachineInstr &LoadMI, + LiveIntervals *LIS) const +{ + // Replace: + // ldr Rd, func address + // blx Rd + // with: + // bl func + + if (MI.getOpcode() == ARM::tBLXr && LoadMI.getOpcode() == ARM::tLDRpci + && MI.getParent() == LoadMI.getParent()) { + unsigned CPI = LoadMI.getOperand(1).getIndex(); + const MachineConstantPool *MCP = MF.getConstantPool(); + const MachineConstantPoolEntry &CPE = MCP->getConstants()[CPI]; + assert(!CPE.isMachineConstantPoolEntry() && "Invalid constpool entry"); + const Constant *callee = cast(CPE.Val.ConstVal); + const char *func_name = MF.createExternalSymbolName(callee->getName()); + MachineInstrBuilder MIB = BuildMI(*MI.getParent(), InsertPt, MI.getDebugLoc(), get(ARM::tBL)) + .add(predOps(ARMCC::AL)) + .addExternalSymbol(func_name) + .addReg(ARM::R0, RegState::Implicit | RegState::Kill) + .addReg(ARM::R1, RegState::Implicit | RegState::Kill) + .addReg(ARM::R2, RegState::Implicit | RegState::Kill); + return MIB.getInstr(); + } + + return nullptr; +}