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
This commit is contained in:
Jim Grosbach
2010-08-19 23:52:25 +00:00
parent b08ceb8135
commit e2f556933e
4 changed files with 99 additions and 23 deletions

View File

@@ -636,6 +636,12 @@ public:
return false; return false;
} }
/// getFrameIndexInstrOffset - Get the offset from the referenced frame
/// index in the instruction, if the is one.
virtual int64_t getFrameIndexInstrOffset(MachineInstr *MI, int Idx) const {
return 0;
}
/// needsFrameBaseReg - Returns true if the instruction's frame index /// needsFrameBaseReg - Returns true if the instruction's frame index
/// reference would be better served by a base register other than FP /// reference would be better served by a base register other than FP
/// or SP. Used by LocalStackFrameAllocation to determine which frame index /// or SP. Used by LocalStackFrameAllocation to determine which frame index
@@ -647,8 +653,8 @@ public:
/// materializeFrameBaseRegister - Insert defining instruction(s) for /// materializeFrameBaseRegister - Insert defining instruction(s) for
/// BaseReg to be a pointer to FrameIdx before insertion point I. /// BaseReg to be a pointer to FrameIdx before insertion point I.
virtual void materializeFrameBaseRegister(MachineBasicBlock::iterator I, virtual void materializeFrameBaseRegister(MachineBasicBlock::iterator I,
unsigned BaseReg, unsigned BaseReg, int FrameIdx,
int FrameIdx) const { int64_t Offset) const {
assert(0 && "materializeFrameBaseRegister does not exist on this target"); assert(0 && "materializeFrameBaseRegister does not exist on this target");
} }
@@ -659,11 +665,11 @@ public:
assert(0 && "resolveFrameIndex does not exist on this target"); assert(0 && "resolveFrameIndex does not exist on this target");
} }
/// isBaseRegInRange - Determine whether a given base register definition /// isFrameOffsetLegal - Determine whether a given offset immediate is
/// is in range to resolve a frame index. /// encodable to resolve a frame index.
virtual bool isBaseRegInRange(const MachineInstr *MI, unsigned Reg, virtual bool isFrameOffsetLegal(const MachineInstr *MI,
int64_t Offset) const { int64_t Offset) const {
assert(0 && "isBaseRegInRange does not exist on this target"); assert(0 && "isFrameOffsetLegal does not exist on this target");
return false; // Must return a value in order to compile with VS 2005 return false; // Must return a value in order to compile with VS 2005
} }

View File

@@ -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 // Check if the relative offset from the where the base register references
// to the target address is in range for the instruction. // to the target address is in range for the instruction.
int64_t Offset = LocalFrameOffset - RegOffset.second; int64_t Offset = LocalFrameOffset - RegOffset.second;
if (TRI->isBaseRegInRange(MI, RegOffset.first, Offset)) if (TRI->isFrameOffsetLegal(MI, Offset))
return true; return true;
} }
return false; return false;
@@ -225,6 +225,7 @@ void LocalStackSlotPass::insertFrameReferenceRegisters(MachineFunction &Fn) {
// an object allocated in the local block. // an object allocated in the local block.
if (MI->getOperand(i).isFI()) { if (MI->getOperand(i).isFI()) {
int FrameIdx = MI->getOperand(i).getIndex(); int FrameIdx = MI->getOperand(i).getIndex();
// Don't try this with values not in the local block. // Don't try this with values not in the local block.
if (!MFI->isObjectPreAllocated(FrameIdx)) if (!MFI->isObjectPreAllocated(FrameIdx))
continue; continue;
@@ -232,13 +233,15 @@ void LocalStackSlotPass::insertFrameReferenceRegisters(MachineFunction &Fn) {
DEBUG(dbgs() << "Considering: " << *MI); DEBUG(dbgs() << "Considering: " << *MI);
if (TRI->needsFrameBaseReg(MI, i)) { if (TRI->needsFrameBaseReg(MI, i)) {
unsigned BaseReg = 0; unsigned BaseReg = 0;
unsigned Offset = 0; int64_t Offset = 0;
DEBUG(dbgs() << " Replacing FI in: " << *MI); DEBUG(dbgs() << " Replacing FI in: " << *MI);
// If we have a suitable base register available, use it; otherwise // 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; std::pair<unsigned, int64_t> RegOffset;
if (lookupCandidateBaseReg(BaseRegisters, RegOffset, if (lookupCandidateBaseReg(BaseRegisters, RegOffset,
LocalOffsets[FrameIdx], MI, TRI)) { LocalOffsets[FrameIdx], MI, TRI)) {
@@ -250,15 +253,26 @@ void LocalStackSlotPass::insertFrameReferenceRegisters(MachineFunction &Fn) {
} else { } else {
// No previously defined register was in range, so create a // No previously defined register was in range, so create a
// new one. // new one.
int64_t InstrOffset = TRI->getFrameIndexInstrOffset(MI, i);
const TargetRegisterClass *RC = TRI->getPointerRegClass(); const TargetRegisterClass *RC = TRI->getPointerRegClass();
BaseReg = Fn.getRegInfo().createVirtualRegister(RC); 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 // Tell the target to insert the instruction to initialize
// the base register. // the base register.
TRI->materializeFrameBaseRegister(I, BaseReg, FrameIdx); TRI->materializeFrameBaseRegister(I, BaseReg, FrameIdx,
InstrOffset);
BaseRegisters.push_back(std::pair<unsigned, int64_t>(BaseReg, // The base register already includes any offset specified
Offset)); // 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,
LocalOffsets[FrameIdx] + InstrOffset));
++NumBaseRegisters; ++NumBaseRegisters;
} }
assert(BaseReg != 0 && "Unable to allocate virtual base register!"); assert(BaseReg != 0 && "Unable to allocate virtual base register!");

View File

@@ -1367,6 +1367,59 @@ eliminateCallFramePseudoInstr(MachineFunction &MF, MachineBasicBlock &MBB,
MBB.erase(I); 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 /// needsFrameBaseReg - Returns true if the instruction's frame index
/// reference would be better served by a base register other than FP /// reference would be better served by a base register other than FP
/// or SP. Used by LocalStackFrameAllocation to determine which frame index /// 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 /// materializeFrameBaseRegister - Insert defining instruction(s) for
/// BaseReg to be a pointer to FrameIdx before insertion point I. /// BaseReg to be a pointer to FrameIdx before insertion point I.
void ARMBaseRegisterInfo:: void ARMBaseRegisterInfo::
materializeFrameBaseRegister(MachineBasicBlock::iterator I, materializeFrameBaseRegister(MachineBasicBlock::iterator I, unsigned BaseReg,
unsigned BaseReg, int FrameIdx) const { int FrameIdx, int64_t Offset) const {
ARMFunctionInfo *AFI = ARMFunctionInfo *AFI =
I->getParent()->getParent()->getInfo<ARMFunctionInfo>(); I->getParent()->getParent()->getInfo<ARMFunctionInfo>();
unsigned ADDriOpc = !AFI->isThumbFunction() ? ARM::ADDri : unsigned ADDriOpc = !AFI->isThumbFunction() ? ARM::ADDri :
@@ -1413,7 +1466,7 @@ materializeFrameBaseRegister(MachineBasicBlock::iterator I,
MachineInstrBuilder MIB = MachineInstrBuilder MIB =
BuildMI(*I->getParent(), I, I->getDebugLoc(), TII.get(ADDriOpc), BaseReg) BuildMI(*I->getParent(), I, I->getDebugLoc(), TII.get(ADDriOpc), BaseReg)
.addFrameIndex(FrameIdx).addImm(0); .addFrameIndex(FrameIdx).addImm(Offset);
if (!AFI->isThumb1OnlyFunction()) if (!AFI->isThumb1OnlyFunction())
AddDefaultCC(AddDefaultPred(MIB)); AddDefaultCC(AddDefaultPred(MIB));
} }
@@ -1445,8 +1498,8 @@ ARMBaseRegisterInfo::resolveFrameIndex(MachineBasicBlock::iterator I,
assert (Done && "Unable to resolve frame index!"); assert (Done && "Unable to resolve frame index!");
} }
bool ARMBaseRegisterInfo::isBaseRegInRange(const MachineInstr *MI, bool ARMBaseRegisterInfo::isFrameOffsetLegal(const MachineInstr *MI,
unsigned Reg, int64_t Offset) const { int64_t Offset) const {
const TargetInstrDesc &Desc = MI->getDesc(); const TargetInstrDesc &Desc = MI->getDesc();
unsigned AddrMode = (Desc.TSFlags & ARMII::AddrModeMask); unsigned AddrMode = (Desc.TSFlags & ARMII::AddrModeMask);
unsigned i = 0; unsigned i = 0;
@@ -1464,6 +1517,7 @@ bool ARMBaseRegisterInfo::isBaseRegInRange(const MachineInstr *MI,
unsigned Scale = 1; unsigned Scale = 1;
unsigned ImmIdx = 0; unsigned ImmIdx = 0;
int InstrOffs = 0;; int InstrOffs = 0;;
bool isSigned = true;
switch(AddrMode) { switch(AddrMode) {
case ARMII::AddrModeT2_i8: case ARMII::AddrModeT2_i8:
case ARMII::AddrModeT2_i12: case ARMII::AddrModeT2_i12:
@@ -1509,6 +1563,7 @@ bool ARMBaseRegisterInfo::isBaseRegInRange(const MachineInstr *MI,
InstrOffs = MI->getOperand(ImmIdx).getImm(); InstrOffs = MI->getOperand(ImmIdx).getImm();
NumBits = 5; NumBits = 5;
Scale = 4; Scale = 4;
isSigned = false;
break; break;
} }
default: default:
@@ -1518,7 +1573,7 @@ bool ARMBaseRegisterInfo::isBaseRegInRange(const MachineInstr *MI,
Offset += InstrOffs * Scale; Offset += InstrOffs * Scale;
assert((Offset & (Scale-1)) == 0 && "Can't encode this offset!"); assert((Offset & (Scale-1)) == 0 && "Can't encode this offset!");
if (Offset < 0) if (isSigned && Offset < 0)
Offset = -Offset; Offset = -Offset;
unsigned Mask = (1 << NumBits) - 1; unsigned Mask = (1 << NumBits) - 1;

View File

@@ -105,13 +105,14 @@ public:
bool canRealignStack(const MachineFunction &MF) const; bool canRealignStack(const MachineFunction &MF) const;
bool needsStackRealignment(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; bool needsFrameBaseReg(MachineInstr *MI, unsigned operand) const;
void materializeFrameBaseRegister(MachineBasicBlock::iterator I, void materializeFrameBaseRegister(MachineBasicBlock::iterator I,
unsigned BaseReg, int FrameIdx) const; unsigned BaseReg, int FrameIdx,
int64_t Offset) const;
void resolveFrameIndex(MachineBasicBlock::iterator I, void resolveFrameIndex(MachineBasicBlock::iterator I,
unsigned BaseReg, int64_t Offset) const; unsigned BaseReg, int64_t Offset) const;
bool isBaseRegInRange(const MachineInstr *MI, unsigned Reg, bool isFrameOffsetLegal(const MachineInstr *MI, int64_t Offset) const;
int64_t Offset) const;
bool cannotEliminateFrame(const MachineFunction &MF) const; bool cannotEliminateFrame(const MachineFunction &MF) const;