From: Jim Grosbach Date: Wed, 18 Aug 2010 22:44:49 +0000 (+0000) Subject: Enable ARM base register reuse to local stack slot allocation. Whenever a new X-Git-Url: http://demsky.eecs.uci.edu/git/?a=commitdiff_plain;h=2b1e202e1c2137b03f7c6ecc18668e40819fa22f;p=oota-llvm.git Enable ARM base register reuse to local stack slot allocation. Whenever a new frame index reference to an object in the local block is seen, check if it's near enough to any previously allocaated base register to re-use. rdar://8277890 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@111443 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/CodeGen/LocalStackSlotAllocation.cpp b/lib/CodeGen/LocalStackSlotAllocation.cpp index 219b845c021..61d6b106ec6 100644 --- a/lib/CodeGen/LocalStackSlotAllocation.cpp +++ b/lib/CodeGen/LocalStackSlotAllocation.cpp @@ -43,8 +43,11 @@ STATISTIC(NumReplacements, "Number of frame indices references replaced"); namespace { class LocalStackSlotPass: public MachineFunctionPass { - void calculateFrameObjectOffsets(MachineFunction &Fn); + SmallVector LocalOffsets; + void AdjustStackOffset(MachineFrameInfo *MFI, int FrameIdx, int64_t &Offset, + unsigned &MaxAlign); + void calculateFrameObjectOffsets(MachineFunction &Fn); void insertFrameReferenceRegisters(MachineFunction &Fn); public: static char ID; // Pass identification, replacement for typeid @@ -70,18 +73,29 @@ FunctionPass *llvm::createLocalStackSlotAllocationPass() { } bool LocalStackSlotPass::runOnMachineFunction(MachineFunction &MF) { + MachineFrameInfo *MFI = MF.getFrameInfo(); + unsigned LocalObjectCount = MFI->getObjectIndexEnd(); + + // Early exit if there are no locals to consider + if (!LocalObjectCount) + return true; + + // Make sure we have enough space to store the local offsets. + LocalOffsets.resize(MFI->getObjectIndexEnd()); + // Lay out the local blob. calculateFrameObjectOffsets(MF); // Insert virtual base registers to resolve frame index references. insertFrameReferenceRegisters(MF); + return true; } /// AdjustStackOffset - Helper function used to adjust the stack frame offset. -static inline void -AdjustStackOffset(MachineFrameInfo *MFI, int FrameIdx, int64_t &Offset, - unsigned &MaxAlign) { +void LocalStackSlotPass::AdjustStackOffset(MachineFrameInfo *MFI, + int FrameIdx, int64_t &Offset, + unsigned &MaxAlign) { unsigned Align = MFI->getObjectAlignment(FrameIdx); // If the alignment of this object is greater than that of the stack, then @@ -93,6 +107,9 @@ AdjustStackOffset(MachineFrameInfo *MFI, int FrameIdx, int64_t &Offset, DEBUG(dbgs() << "Allocate FI(" << FrameIdx << ") to local offset " << Offset << "\n"); + // Keep the offset available for base register allocation + LocalOffsets[FrameIdx] = Offset; + // And tell MFI about it for PEI to use later MFI->mapLocalFrameObject(FrameIdx, Offset); Offset += MFI->getObjectSize(FrameIdx); @@ -149,12 +166,16 @@ void LocalStackSlotPass::calculateFrameObjectOffsets(MachineFunction &Fn) { static inline bool lookupCandidateBaseReg(const SmallVector, 8> &Regs, std::pair &RegOffset, + int64_t LocalFrameOffset, 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)) + // Check if the relative offset from the where the base register references + // to the target address is in range for the instruction. + int64_t Offset = LocalFrameOffset - RegOffset.second; + if (TRI->isBaseRegInRange(MI, RegOffset.first, Offset)) return true; } return false; @@ -173,6 +194,9 @@ void LocalStackSlotPass::insertFrameReferenceRegisters(MachineFunction &Fn) { for (MachineFunction::iterator BB = Fn.begin(), E = Fn.end(); BB != E; ++BB) { + // A base register definition is a register+offset pair. + SmallVector, 8> BaseRegisters; + 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 @@ -183,9 +207,6 @@ 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 @@ -212,10 +233,12 @@ void LocalStackSlotPass::insertFrameReferenceRegisters(MachineFunction &Fn) { // create a new one. std::pair RegOffset; - if (lookupCandidateBaseReg(BaseRegisters, RegOffset, MI, TRI)) { + if (lookupCandidateBaseReg(BaseRegisters, RegOffset, + LocalOffsets[FrameIdx], MI, TRI)) { + DEBUG(dbgs() << " Reusing base register " << RegOffset.first); // We found a register to reuse. BaseReg = RegOffset.first; - Offset = RegOffset.second; + Offset = LocalOffsets[FrameIdx] - RegOffset.second; } else { // No previously defined register was in range, so create a // new one. diff --git a/lib/Target/ARM/ARMBaseRegisterInfo.cpp b/lib/Target/ARM/ARMBaseRegisterInfo.cpp index b498075999f..0330faca4c0 100644 --- a/lib/Target/ARM/ARMBaseRegisterInfo.cpp +++ b/lib/Target/ARM/ARMBaseRegisterInfo.cpp @@ -1453,6 +1453,75 @@ ARMBaseRegisterInfo::resolveFrameIndex(MachineBasicBlock::iterator I, bool ARMBaseRegisterInfo::isBaseRegInRange(const MachineInstr *MI, unsigned Reg, int64_t Offset) const { + const TargetInstrDesc &Desc = MI->getDesc(); + unsigned AddrMode = (Desc.TSFlags & ARMII::AddrModeMask); + unsigned i = 0; + + while (!MI->getOperand(i).isFI()) { + ++i; + assert(i < MI->getNumOperands() &&"Instr doesn't have FrameIndex operand!"); + } + + // AddrMode4 and AddrMode6 cannot handle any offset. + if (AddrMode == ARMII::AddrMode4 || AddrMode == ARMII::AddrMode6) + return Offset == 0; + + unsigned NumBits = 0; + unsigned Scale = 1; + unsigned ImmIdx = 0; + int InstrOffs; + switch(AddrMode) { + case ARMII::AddrModeT2_i8: + case ARMII::AddrModeT2_i12: + // i8 supports only negative, and i12 supports only positive, so + // based on Offset sign, consider the appropriate instruction + Offset += MI->getOperand(i+1).getImm(); + if (Offset < 0) { + NumBits = 8; + Offset = -Offset; + } else { + NumBits = 12; + } + break; + case ARMII::AddrMode5: { + // VFP address mode. + const MachineOperand &OffOp = MI->getOperand(i+1); + int InstrOffs = ARM_AM::getAM5Offset(OffOp.getImm()); + if (ARM_AM::getAM5Op(OffOp.getImm()) == ARM_AM::sub) + InstrOffs = -InstrOffs; + NumBits = 8; + Scale = 4; + break; + } + case ARMII::AddrMode2: { + ImmIdx = i+2; + InstrOffs = ARM_AM::getAM2Offset(MI->getOperand(ImmIdx).getImm()); + if (ARM_AM::getAM2Op(MI->getOperand(ImmIdx).getImm()) == ARM_AM::sub) + InstrOffs = -InstrOffs; + NumBits = 12; + break; + } + case ARMII::AddrMode3: { + ImmIdx = i+2; + InstrOffs = ARM_AM::getAM3Offset(MI->getOperand(ImmIdx).getImm()); + if (ARM_AM::getAM3Op(MI->getOperand(ImmIdx).getImm()) == ARM_AM::sub) + InstrOffs = -InstrOffs; + NumBits = 8; + break; + } + default: + llvm_unreachable("Unsupported addressing mode!"); + break; + } + + Offset += InstrOffs * Scale; + assert((Offset & (Scale-1)) == 0 && "Can't encode this offset!"); + if (Offset < 0) + Offset = -Offset; + + unsigned Mask = (1 << NumBits) - 1; + if ((unsigned)Offset <= Mask * Scale) + return true; return false; }