diff options
-rw-r--r-- | include/llvm/Target/TargetRegisterInfo.h | 8 | ||||
-rw-r--r-- | lib/CodeGen/LocalStackSlotAllocation.cpp | 54 | ||||
-rw-r--r-- | lib/Target/ARM/ARMBaseRegisterInfo.cpp | 41 | ||||
-rw-r--r-- | lib/Target/ARM/ARMBaseRegisterInfo.h | 1 |
4 files changed, 102 insertions, 2 deletions
diff --git a/include/llvm/Target/TargetRegisterInfo.h b/include/llvm/Target/TargetRegisterInfo.h index d8d4d07bde..1a5cf0aaca 100644 --- a/include/llvm/Target/TargetRegisterInfo.h +++ b/include/llvm/Target/TargetRegisterInfo.h @@ -636,6 +636,14 @@ public: return false; } + /// needsFrameBaseReg - Returns true if the instruction's frame index + /// reference would be better served by a base register other than FP + /// or SP. Used by LocalStackFrameAllocation to determine which frame index + /// references it should create new base registers for. + virtual bool needsFrameBaseReg(MachineInstr *MI, unsigned operand) const { + return false; + } + /// 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 8aabca0cd3..bfc62cf2d1 100644 --- a/lib/CodeGen/LocalStackSlotAllocation.cpp +++ b/lib/CodeGen/LocalStackSlotAllocation.cpp @@ -19,11 +19,11 @@ #include "llvm/DerivedTypes.h" #include "llvm/Instructions.h" #include "llvm/Intrinsics.h" -#include "llvm/ADT/Statistic.h" #include "llvm/LLVMContext.h" #include "llvm/Module.h" #include "llvm/Pass.h" #include "llvm/ADT/SmallSet.h" +#include "llvm/ADT/Statistic.h" #include "llvm/CodeGen/MachineFrameInfo.h" #include "llvm/CodeGen/MachineFunction.h" #include "llvm/CodeGen/MachineFunctionPass.h" @@ -36,11 +36,15 @@ using namespace llvm; -STATISTIC(NumAllocations, "Number of frame indices processed"); +STATISTIC(NumAllocations, "Number of frame indices allocated into local block"); +STATISTIC(NumBaseRegisters, "Number of virtual frame base registers allocated"); +STATISTIC(NumReplacements, "Number of frame indices references replaced"); namespace { class LocalStackSlotPass: public MachineFunctionPass { void calculateFrameObjectOffsets(MachineFunction &Fn); + + void insertFrameReferenceRegisters(MachineFunction &Fn); public: static char ID; // Pass identification, replacement for typeid explicit LocalStackSlotPass() : MachineFunctionPass(ID) { } @@ -65,7 +69,11 @@ FunctionPass *llvm::createLocalStackSlotAllocationPass() { } bool LocalStackSlotPass::runOnMachineFunction(MachineFunction &MF) { + // Lay out the local blob. calculateFrameObjectOffsets(MF); + + // Insert virtual base registers to resolve frame index references. + insertFrameReferenceRegisters(MF); return true; } @@ -136,3 +144,45 @@ void LocalStackSlotPass::calculateFrameObjectOffsets(MachineFunction &Fn) { MFI->setLocalFrameSize(Offset); MFI->setLocalFrameMaxAlign(MaxAlign); } + +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 + // based on what we can tell it about where the local will end up in the + // stack frame. If it wants one, re-use a suitable one we've previously + // allocated, or if there isn't one that fits the bill, allocate a new one + // and ask the target to create a defining instruction for it. + + MachineFrameInfo *MFI = Fn.getFrameInfo(); + const TargetRegisterInfo *TRI = Fn.getTarget().getRegisterInfo(); + + for (MachineFunction::iterator BB = Fn.begin(), + E = Fn.end(); BB != E; ++BB) { + for (MachineBasicBlock::iterator I = BB->begin(); I != BB->end(); ++I) { + MachineInstr *MI = I; + // 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 + // than that, but the increased register pressure makes that a + // tricky thing to balance. Investigate if re-materializing these + // becomes an issue. + 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())) { + DEBUG(dbgs() << "Considering: " << *MI); + if (TRI->needsFrameBaseReg(MI, i)) { + 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. + + ++NumReplacements; + } + + } + } + } + } +} diff --git a/lib/Target/ARM/ARMBaseRegisterInfo.cpp b/lib/Target/ARM/ARMBaseRegisterInfo.cpp index 12308c4340..5612f04c5f 100644 --- a/lib/Target/ARM/ARMBaseRegisterInfo.cpp +++ b/lib/Target/ARM/ARMBaseRegisterInfo.cpp @@ -1367,6 +1367,47 @@ eliminateCallFramePseudoInstr(MachineFunction &MF, MachineBasicBlock &MBB, MBB.erase(I); } +/// needsFrameBaseReg - Returns true if the instruction's frame index +/// reference would be better served by a base register other than FP +/// or SP. Used by LocalStackFrameAllocation to determine which frame index +/// references it should create new base registers for. +bool ARMBaseRegisterInfo:: +needsFrameBaseReg(MachineInstr *MI, unsigned operand) const { + assert (MI->getOperand(operand).isFI() && + "needsFrameBaseReg() called on non Frame Index operand!"); + + // It's the load/store FI references that cause issues, as it can be difficult + // to materialize the offset if it won't fit in the literal field. Estimate + // based on the size of the local frame and some conservative assumptions + // about the rest of the stack frame (note, this is pre-regalloc, so + // we don't know everything for certain yet) whether this offset is likely + // to be out of range of the immediate. Return true if so. + + // FIXME: For testing, return true for all loads/stores and false for + // everything else. We want to create lots of base regs to shake out bugs. + // + // FIXME: This is Thumb2/ARM only for now to keep it simpler. + ARMFunctionInfo *AFI = + MI->getParent()->getParent()->getInfo<ARMFunctionInfo>(); + if (AFI->isThumb1OnlyFunction()) + return false; + + unsigned Opc = MI->getOpcode(); + + switch (Opc) { + case ARM::LDR: case ARM::LDRH: case ARM::LDRB: + case ARM::STR: case ARM::STRH: case ARM::STRB: + case ARM::t2LDRi12: case ARM::t2LDRi8: + case ARM::t2STRi12: case ARM::t2STRi8: + case ARM::VLDRS: case ARM::VLDRD: + case ARM::VSTRS: case ARM::VSTRD: + return true; + default: + 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 d644ecc1ab..f3ccfb4cc4 100644 --- a/lib/Target/ARM/ARMBaseRegisterInfo.h +++ b/lib/Target/ARM/ARMBaseRegisterInfo.h @@ -105,6 +105,7 @@ public: bool canRealignStack(const MachineFunction &MF) const; bool needsStackRealignment(const MachineFunction &MF) const; + bool needsFrameBaseReg(MachineInstr *MI, unsigned operand) const; bool cannotEliminateFrame(const MachineFunction &MF) const; |