diff options
author | Jim Grosbach <grosbach@apple.com> | 2010-08-19 23:52:25 +0000 |
---|---|---|
committer | Jim Grosbach <grosbach@apple.com> | 2010-08-19 23:52:25 +0000 |
commit | e2f556933e1a19cddf6d4f370e2770c0f763b025 (patch) | |
tree | 5dd6b09fab81ed02643c883b33e9e06c2acceaa3 /lib | |
parent | b08ceb8135daf015dc38f9d9048cb075215da383 (diff) |
Better handling of offsets on frame index references. rdar://8277890
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@111585 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib')
-rw-r--r-- | lib/CodeGen/LocalStackSlotAllocation.cpp | 28 | ||||
-rw-r--r-- | lib/Target/ARM/ARMBaseRegisterInfo.cpp | 67 | ||||
-rw-r--r-- | lib/Target/ARM/ARMBaseRegisterInfo.h | 7 |
3 files changed, 86 insertions, 16 deletions
diff --git a/lib/CodeGen/LocalStackSlotAllocation.cpp b/lib/CodeGen/LocalStackSlotAllocation.cpp index a4a43875ce..01a1af1be6 100644 --- a/lib/CodeGen/LocalStackSlotAllocation.cpp +++ b/lib/CodeGen/LocalStackSlotAllocation.cpp @@ -182,7 +182,7 @@ lookupCandidateBaseReg(const SmallVector<std::pair<unsigned, int64_t>, 8> &Regs, // 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)) + if (TRI->isFrameOffsetLegal(MI, Offset)) return true; } return false; @@ -225,6 +225,7 @@ void LocalStackSlotPass::insertFrameReferenceRegisters(MachineFunction &Fn) { // an object allocated in the local block. 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; @@ -232,13 +233,15 @@ void LocalStackSlotPass::insertFrameReferenceRegisters(MachineFunction &Fn) { DEBUG(dbgs() << "Considering: " << *MI); if (TRI->needsFrameBaseReg(MI, i)) { unsigned BaseReg = 0; - unsigned Offset = 0; + int64_t Offset = 0; DEBUG(dbgs() << " Replacing FI in: " << *MI); // If we have a suitable base register available, use it; otherwise - // create a new one. - + // create a new one. Note that any offset encoded in the + // instruction itself will be taken into account by the target, + // so we don't have to adjust for it here when reusing a base + // register. std::pair<unsigned, int64_t> RegOffset; if (lookupCandidateBaseReg(BaseRegisters, RegOffset, LocalOffsets[FrameIdx], MI, TRI)) { @@ -250,15 +253,26 @@ void LocalStackSlotPass::insertFrameReferenceRegisters(MachineFunction &Fn) { } else { // No previously defined register was in range, so create a // new one. + int64_t InstrOffset = TRI->getFrameIndexInstrOffset(MI, i); const TargetRegisterClass *RC = TRI->getPointerRegClass(); BaseReg = Fn.getRegInfo().createVirtualRegister(RC); + DEBUG(dbgs() << " Materializing base register " << BaseReg << + " at frame local offset " << + LocalOffsets[FrameIdx] + InstrOffset << "\n"); // Tell the target to insert the instruction to initialize // the base register. - TRI->materializeFrameBaseRegister(I, BaseReg, FrameIdx); + TRI->materializeFrameBaseRegister(I, BaseReg, FrameIdx, + InstrOffset); + + // The base register already includes any offset specified + // by the instruction, so account for that so it doesn't get + // applied twice. + Offset = -InstrOffset; - BaseRegisters.push_back(std::pair<unsigned, int64_t>(BaseReg, - Offset)); + BaseRegisters.push_back( + std::pair<unsigned, int64_t>(BaseReg, + LocalOffsets[FrameIdx] + InstrOffset)); ++NumBaseRegisters; } assert(BaseReg != 0 && "Unable to allocate virtual base register!"); diff --git a/lib/Target/ARM/ARMBaseRegisterInfo.cpp b/lib/Target/ARM/ARMBaseRegisterInfo.cpp index ef316a53fc..1408e34b2f 100644 --- a/lib/Target/ARM/ARMBaseRegisterInfo.cpp +++ b/lib/Target/ARM/ARMBaseRegisterInfo.cpp @@ -1367,6 +1367,59 @@ eliminateCallFramePseudoInstr(MachineFunction &MF, MachineBasicBlock &MBB, MBB.erase(I); } + +int64_t ARMBaseRegisterInfo:: +getFrameIndexInstrOffset(MachineInstr *MI, int Idx) const { + const TargetInstrDesc &Desc = MI->getDesc(); + unsigned AddrMode = (Desc.TSFlags & ARMII::AddrModeMask); + int64_t InstrOffs = 0;; + int Scale = 1; + unsigned ImmIdx = 0; + 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 + InstrOffs = MI->getOperand(Idx+1).getImm(); + Scale = 1; + break; + case ARMII::AddrMode5: { + // VFP address mode. + const MachineOperand &OffOp = MI->getOperand(Idx+1); + int InstrOffs = ARM_AM::getAM5Offset(OffOp.getImm()); + if (ARM_AM::getAM5Op(OffOp.getImm()) == ARM_AM::sub) + InstrOffs = -InstrOffs; + Scale = 4; + break; + } + case ARMII::AddrMode2: { + ImmIdx = Idx+2; + InstrOffs = ARM_AM::getAM2Offset(MI->getOperand(ImmIdx).getImm()); + if (ARM_AM::getAM2Op(MI->getOperand(ImmIdx).getImm()) == ARM_AM::sub) + InstrOffs = -InstrOffs; + break; + } + case ARMII::AddrMode3: { + ImmIdx = Idx+2; + InstrOffs = ARM_AM::getAM3Offset(MI->getOperand(ImmIdx).getImm()); + if (ARM_AM::getAM3Op(MI->getOperand(ImmIdx).getImm()) == ARM_AM::sub) + InstrOffs = -InstrOffs; + break; + } + case ARMII::AddrModeT1_s: { + ImmIdx = Idx+1; + InstrOffs = MI->getOperand(ImmIdx).getImm(); + Scale = 4; + break; + } + default: + llvm_unreachable("Unsupported addressing mode!"); + break; + } + + return InstrOffs * Scale; +} + /// 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 @@ -1404,8 +1457,8 @@ 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 { +materializeFrameBaseRegister(MachineBasicBlock::iterator I, unsigned BaseReg, + int FrameIdx, int64_t Offset) const { ARMFunctionInfo *AFI = I->getParent()->getParent()->getInfo<ARMFunctionInfo>(); unsigned ADDriOpc = !AFI->isThumbFunction() ? ARM::ADDri : @@ -1413,7 +1466,7 @@ materializeFrameBaseRegister(MachineBasicBlock::iterator I, MachineInstrBuilder MIB = BuildMI(*I->getParent(), I, I->getDebugLoc(), TII.get(ADDriOpc), BaseReg) - .addFrameIndex(FrameIdx).addImm(0); + .addFrameIndex(FrameIdx).addImm(Offset); if (!AFI->isThumb1OnlyFunction()) AddDefaultCC(AddDefaultPred(MIB)); } @@ -1445,8 +1498,8 @@ ARMBaseRegisterInfo::resolveFrameIndex(MachineBasicBlock::iterator I, assert (Done && "Unable to resolve frame index!"); } -bool ARMBaseRegisterInfo::isBaseRegInRange(const MachineInstr *MI, - unsigned Reg, int64_t Offset) const { +bool ARMBaseRegisterInfo::isFrameOffsetLegal(const MachineInstr *MI, + int64_t Offset) const { const TargetInstrDesc &Desc = MI->getDesc(); unsigned AddrMode = (Desc.TSFlags & ARMII::AddrModeMask); unsigned i = 0; @@ -1464,6 +1517,7 @@ bool ARMBaseRegisterInfo::isBaseRegInRange(const MachineInstr *MI, unsigned Scale = 1; unsigned ImmIdx = 0; int InstrOffs = 0;; + bool isSigned = true; switch(AddrMode) { case ARMII::AddrModeT2_i8: case ARMII::AddrModeT2_i12: @@ -1509,6 +1563,7 @@ bool ARMBaseRegisterInfo::isBaseRegInRange(const MachineInstr *MI, InstrOffs = MI->getOperand(ImmIdx).getImm(); NumBits = 5; Scale = 4; + isSigned = false; break; } default: @@ -1518,7 +1573,7 @@ bool ARMBaseRegisterInfo::isBaseRegInRange(const MachineInstr *MI, Offset += InstrOffs * Scale; assert((Offset & (Scale-1)) == 0 && "Can't encode this offset!"); - if (Offset < 0) + if (isSigned && Offset < 0) Offset = -Offset; unsigned Mask = (1 << NumBits) - 1; diff --git a/lib/Target/ARM/ARMBaseRegisterInfo.h b/lib/Target/ARM/ARMBaseRegisterInfo.h index 716c91d9ad..afd43eaeb3 100644 --- a/lib/Target/ARM/ARMBaseRegisterInfo.h +++ b/lib/Target/ARM/ARMBaseRegisterInfo.h @@ -105,13 +105,14 @@ public: bool canRealignStack(const MachineFunction &MF) const; bool needsStackRealignment(const MachineFunction &MF) const; + int64_t getFrameIndexInstrOffset(MachineInstr *MI, int Idx) const; bool needsFrameBaseReg(MachineInstr *MI, unsigned operand) const; void materializeFrameBaseRegister(MachineBasicBlock::iterator I, - unsigned BaseReg, int FrameIdx) const; + unsigned BaseReg, int FrameIdx, + int64_t Offset) const; void resolveFrameIndex(MachineBasicBlock::iterator I, unsigned BaseReg, int64_t Offset) const; - bool isBaseRegInRange(const MachineInstr *MI, unsigned Reg, - int64_t Offset) const; + bool isFrameOffsetLegal(const MachineInstr *MI, int64_t Offset) const; bool cannotEliminateFrame(const MachineFunction &MF) const; |