diff options
-rw-r--r-- | include/llvm/Target/TargetRegisterInfo.h | 16 | ||||
-rw-r--r-- | lib/CodeGen/LocalStackSlotAllocation.cpp | 28 | ||||
-rw-r--r-- | lib/CodeGen/PrologEpilogInserter.cpp | 2 | ||||
-rw-r--r-- | lib/Target/ARM/ARMBaseRegisterInfo.cpp | 43 | ||||
-rw-r--r-- | lib/Target/ARM/ARMBaseRegisterInfo.h | 4 |
5 files changed, 90 insertions, 3 deletions
diff --git a/include/llvm/Target/TargetRegisterInfo.h b/include/llvm/Target/TargetRegisterInfo.h index 1a5cf0aaca..b1cf3e9db4 100644 --- a/include/llvm/Target/TargetRegisterInfo.h +++ b/include/llvm/Target/TargetRegisterInfo.h @@ -644,6 +644,22 @@ public: return false; } + /// materializeFrameBaseRegister - Insert defining instruction(s) for + /// BaseReg to be a pointer to FrameIdx before insertion point I. + virtual void materializeFrameBaseRegister(MachineBasicBlock::iterator I, + unsigned BaseReg, + int FrameIdx) const { + assert(0 && "materializeFrameBaseRegister does not exist on this target"); + } + + /// resolveFrameIndex - Resolve a frame index operand of an instruction + /// to reference the indicated base register plus offset instead. + virtual void resolveFrameIndex(MachineBasicBlock::iterator I, + unsigned BaseReg, int64_t Offset) const { + assert(0 && "resolveFrameIndex does not exist on this target"); + } + + /// getCallFrameSetup/DestroyOpcode - These methods return the opcode of the /// frame setup/destroy instructions if they exist (-1 otherwise). Some /// targets use pseudo instructions in order to abstract away the difference diff --git a/lib/CodeGen/LocalStackSlotAllocation.cpp b/lib/CodeGen/LocalStackSlotAllocation.cpp index 065cf80ca4..3927beec11 100644 --- a/lib/CodeGen/LocalStackSlotAllocation.cpp +++ b/lib/CodeGen/LocalStackSlotAllocation.cpp @@ -27,6 +27,7 @@ #include "llvm/CodeGen/MachineFrameInfo.h" #include "llvm/CodeGen/MachineFunction.h" #include "llvm/CodeGen/MachineFunctionPass.h" +#include "llvm/CodeGen/MachineRegisterInfo.h" #include "llvm/CodeGen/Passes.h" #include "llvm/Support/Debug.h" #include "llvm/Support/ErrorHandling.h" @@ -160,6 +161,14 @@ void LocalStackSlotPass::insertFrameReferenceRegisters(MachineFunction &Fn) { E = Fn.end(); BB != E; ++BB) { for (MachineBasicBlock::iterator I = BB->begin(); I != BB->end(); ++I) { MachineInstr *MI = I; + // Debug value instructions can't be out of range, so they don't need + // any updates. + // FIXME: When we extend this stuff to handle functions with both + // VLAs and dynamic realignment, we should update the debug values + // to reference the new base pointer when possible. + if (MI->isDebugValue()) + continue; + // 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 @@ -169,8 +178,12 @@ void LocalStackSlotPass::insertFrameReferenceRegisters(MachineFunction &Fn) { for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) { // Consider replacing all frame index operands that reference // an object allocated in the local block. - if (MI->getOperand(i).isFI() && - MFI->isObjectPreAllocated(MI->getOperand(i).getIndex())) { + if (MI->getOperand(i).isFI()) { + int FrameIdx = MI->getOperand(i).getIndex(); + // Don't try this with values not in the local block. + if (!MFI->isObjectPreAllocated(FrameIdx)) + continue; + DEBUG(dbgs() << "Considering: " << *MI); if (TRI->needsFrameBaseReg(MI, i)) { DEBUG(dbgs() << " Replacing FI in: " << *MI); @@ -182,6 +195,17 @@ void LocalStackSlotPass::insertFrameReferenceRegisters(MachineFunction &Fn) { // 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); + + // Tell the target to insert the instruction to initialize + // the base register. + TRI->materializeFrameBaseRegister(I, BaseReg, FrameIdx); + + // Modify the instruction to use the new base register rather + // than the frame index operand. + TRI->resolveFrameIndex(I, BaseReg, 0); + ++NumBaseRegisters; ++NumReplacements; } diff --git a/lib/CodeGen/PrologEpilogInserter.cpp b/lib/CodeGen/PrologEpilogInserter.cpp index 7b67473636..569faceffd 100644 --- a/lib/CodeGen/PrologEpilogInserter.cpp +++ b/lib/CodeGen/PrologEpilogInserter.cpp @@ -560,7 +560,7 @@ void PEI::calculateFrameObjectOffsets(MachineFunction &Fn) { // check for whether the frame is large enough to want to use virtual // frame index registers. Functions which don't want/need this optimization // will continue to use the existing code path. - if (EnableLocalStackAlloc) { + if (EnableLocalStackAlloc && MFI->getLocalFrameSize()) { unsigned Align = MFI->getLocalFrameMaxAlign(); // Adjust to alignment boundary. diff --git a/lib/Target/ARM/ARMBaseRegisterInfo.cpp b/lib/Target/ARM/ARMBaseRegisterInfo.cpp index 5612f04c5f..23fe6216f6 100644 --- a/lib/Target/ARM/ARMBaseRegisterInfo.cpp +++ b/lib/Target/ARM/ARMBaseRegisterInfo.cpp @@ -1407,6 +1407,49 @@ needsFrameBaseReg(MachineInstr *MI, unsigned operand) const { } } +/// materializeFrameBaseRegister - Insert defining instruction(s) for +/// BaseReg to be a pointer to FrameIdx before insertion point I. +void ARMBaseRegisterInfo:: +materializeFrameBaseRegister(MachineBasicBlock::iterator I, + unsigned BaseReg, int FrameIdx) const { + ARMFunctionInfo *AFI = + I->getParent()->getParent()->getInfo<ARMFunctionInfo>(); + unsigned ADDriOpc = !AFI->isThumbFunction() ? ARM::ADDri : ARM::t2ADDri; + assert(!AFI->isThumb1OnlyFunction() && + "This materializeFrameBaseRegister does not support Thumb1!"); + + MachineInstrBuilder MIB = + BuildMI(*I->getParent(), I, I->getDebugLoc(), TII.get(ADDriOpc), BaseReg) + .addFrameIndex(FrameIdx).addImm(0); + AddDefaultCC(AddDefaultPred(MIB)); +} + +void +ARMBaseRegisterInfo::resolveFrameIndex(MachineBasicBlock::iterator I, + unsigned BaseReg, int64_t Offset) const { + MachineInstr &MI = *I; + MachineBasicBlock &MBB = *MI.getParent(); + MachineFunction &MF = *MBB.getParent(); + ARMFunctionInfo *AFI = MF.getInfo<ARMFunctionInfo>(); + int Off = Offset; // ARM doesn't need the general 64-bit offsets + unsigned i = 0; + + assert(!AFI->isThumb1OnlyFunction() && + "This resolveFrameIndex does not support Thumb1!"); + + while (!MI.getOperand(i).isFI()) { + ++i; + assert(i < MI.getNumOperands() && "Instr doesn't have FrameIndex operand!"); + } + bool Done = false; + if (!AFI->isThumbFunction()) + Done = rewriteARMFrameIndex(MI, i, BaseReg, Off, TII); + else { + assert(AFI->isThumb2Function()); + Done = rewriteT2FrameIndex(MI, i, BaseReg, Off, TII); + } + assert (Done && "Unable to resolve frame index!"); +} unsigned ARMBaseRegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II, diff --git a/lib/Target/ARM/ARMBaseRegisterInfo.h b/lib/Target/ARM/ARMBaseRegisterInfo.h index f3ccfb4cc4..7570d1fd16 100644 --- a/lib/Target/ARM/ARMBaseRegisterInfo.h +++ b/lib/Target/ARM/ARMBaseRegisterInfo.h @@ -106,6 +106,10 @@ public: bool canRealignStack(const MachineFunction &MF) const; bool needsStackRealignment(const MachineFunction &MF) const; bool needsFrameBaseReg(MachineInstr *MI, unsigned operand) const; + void materializeFrameBaseRegister(MachineBasicBlock::iterator I, + unsigned BaseReg, int FrameIdx) const; + void resolveFrameIndex(MachineBasicBlock::iterator I, + unsigned BaseReg, int64_t Offset) const; bool cannotEliminateFrame(const MachineFunction &MF) const; |