diff --git a/include/llvm/Target/TargetRegisterInfo.h b/include/llvm/Target/TargetRegisterInfo.h index b1cf3e9db4e..e36cc4f9cec 100644 --- a/include/llvm/Target/TargetRegisterInfo.h +++ b/include/llvm/Target/TargetRegisterInfo.h @@ -659,6 +659,13 @@ public: assert(0 && "resolveFrameIndex does not exist on this target"); } + /// isBaseRegInRange - Determine whether a given base register definition + /// is in range to resolve a frame index. + virtual bool isBaseRegInRange(const MachineInstr *MI, unsigned Reg, + int64_t Offset) const { + assert(0 && "isBaseRegInRange does not exist on this target"); + return false; // Must return a value in order to compile with VS 2005 + } /// getCallFrameSetup/DestroyOpcode - These methods return the opcode of the /// frame setup/destroy instructions if they exist (-1 otherwise). Some diff --git a/lib/CodeGen/LocalStackSlotAllocation.cpp b/lib/CodeGen/LocalStackSlotAllocation.cpp index 3927beec114..219b845c021 100644 --- a/lib/CodeGen/LocalStackSlotAllocation.cpp +++ b/lib/CodeGen/LocalStackSlotAllocation.cpp @@ -146,6 +146,20 @@ void LocalStackSlotPass::calculateFrameObjectOffsets(MachineFunction &Fn) { MFI->setLocalFrameMaxAlign(MaxAlign); } +static inline bool +lookupCandidateBaseReg(const SmallVector, 8> &Regs, + std::pair &RegOffset, + const MachineInstr *MI, + const TargetRegisterInfo *TRI) { + unsigned e = Regs.size(); + for (unsigned i = 0; i < e; ++i) { + RegOffset = Regs[i]; + if (TRI->isBaseRegInRange(MI, RegOffset.first, RegOffset.second)) + return true; + } + return false; +} + void LocalStackSlotPass::insertFrameReferenceRegisters(MachineFunction &Fn) { // Scan the function's instructions looking for frame index references. // For each, ask the target if it wants a virtual base register for it @@ -169,6 +183,9 @@ void LocalStackSlotPass::insertFrameReferenceRegisters(MachineFunction &Fn) { if (MI->isDebugValue()) continue; + // A base register definition is a register+offset pair. + SmallVector, 8> BaseRegisters; + // For now, allocate the base register(s) within the basic block // where they're used, and don't try to keep them around outside // of that. It may be beneficial to try sharing them more broadly @@ -186,27 +203,39 @@ void LocalStackSlotPass::insertFrameReferenceRegisters(MachineFunction &Fn) { DEBUG(dbgs() << "Considering: " << *MI); if (TRI->needsFrameBaseReg(MI, i)) { + unsigned BaseReg = 0; + unsigned Offset = 0; + DEBUG(dbgs() << " Replacing FI in: " << *MI); - // FIXME: Make sure any new base reg is aligned reasonably. TBD - // what "reasonably" really means. Conservatively, can just - // use the alignment of the local block. // If we have a suitable base register available, use it; otherwise // create a new one. - // FIXME: For the moment, just always create a new one. - const TargetRegisterClass *RC = TRI->getPointerRegClass(); - unsigned BaseReg = Fn.getRegInfo().createVirtualRegister(RC); + std::pair RegOffset; + if (lookupCandidateBaseReg(BaseRegisters, RegOffset, MI, TRI)) { + // We found a register to reuse. + BaseReg = RegOffset.first; + Offset = RegOffset.second; + } else { + // No previously defined register was in range, so create a + // new one. + const TargetRegisterClass *RC = TRI->getPointerRegClass(); + BaseReg = Fn.getRegInfo().createVirtualRegister(RC); - // Tell the target to insert the instruction to initialize - // the base register. - TRI->materializeFrameBaseRegister(I, BaseReg, FrameIdx); + // Tell the target to insert the instruction to initialize + // the base register. + TRI->materializeFrameBaseRegister(I, BaseReg, FrameIdx); + + BaseRegisters.push_back(std::pair(BaseReg, + Offset)); + ++NumBaseRegisters; + } + assert(BaseReg != 0 && "Unable to allocate virtual base register!"); // Modify the instruction to use the new base register rather // than the frame index operand. - TRI->resolveFrameIndex(I, BaseReg, 0); + TRI->resolveFrameIndex(I, BaseReg, Offset); - ++NumBaseRegisters; ++NumReplacements; } diff --git a/lib/Target/ARM/ARMBaseRegisterInfo.cpp b/lib/Target/ARM/ARMBaseRegisterInfo.cpp index 23fe6216f61..b498075999f 100644 --- a/lib/Target/ARM/ARMBaseRegisterInfo.cpp +++ b/lib/Target/ARM/ARMBaseRegisterInfo.cpp @@ -1451,6 +1451,12 @@ ARMBaseRegisterInfo::resolveFrameIndex(MachineBasicBlock::iterator I, assert (Done && "Unable to resolve frame index!"); } +bool ARMBaseRegisterInfo::isBaseRegInRange(const MachineInstr *MI, + unsigned Reg, int64_t Offset) const { + + return false; +} + unsigned ARMBaseRegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II, int SPAdj, FrameIndexValue *Value, diff --git a/lib/Target/ARM/ARMBaseRegisterInfo.h b/lib/Target/ARM/ARMBaseRegisterInfo.h index 7570d1fd161..716c91d9ad0 100644 --- a/lib/Target/ARM/ARMBaseRegisterInfo.h +++ b/lib/Target/ARM/ARMBaseRegisterInfo.h @@ -110,6 +110,8 @@ public: unsigned BaseReg, int FrameIdx) const; void resolveFrameIndex(MachineBasicBlock::iterator I, unsigned BaseReg, int64_t Offset) const; + bool isBaseRegInRange(const MachineInstr *MI, unsigned Reg, + int64_t Offset) const; bool cannotEliminateFrame(const MachineFunction &MF) const;