Skip to content

Commit 56e5632

Browse files
author
Jim Grosbach
committed
Better handling of offsets on frame index references. rdar://8277890
llvm-svn: 111585
1 parent b3774b5 commit 56e5632

File tree

4 files changed

+99
-23
lines changed

4 files changed

+99
-23
lines changed

llvm/include/llvm/Target/TargetRegisterInfo.h

+13-7
Original file line numberDiff line numberDiff line change
@@ -636,6 +636,12 @@ class TargetRegisterInfo {
636636
return false;
637637
}
638638

639+
/// getFrameIndexInstrOffset - Get the offset from the referenced frame
640+
/// index in the instruction, if the is one.
641+
virtual int64_t getFrameIndexInstrOffset(MachineInstr *MI, int Idx) const {
642+
return 0;
643+
}
644+
639645
/// needsFrameBaseReg - Returns true if the instruction's frame index
640646
/// reference would be better served by a base register other than FP
641647
/// or SP. Used by LocalStackFrameAllocation to determine which frame index
@@ -647,8 +653,8 @@ class TargetRegisterInfo {
647653
/// materializeFrameBaseRegister - Insert defining instruction(s) for
648654
/// BaseReg to be a pointer to FrameIdx before insertion point I.
649655
virtual void materializeFrameBaseRegister(MachineBasicBlock::iterator I,
650-
unsigned BaseReg,
651-
int FrameIdx) const {
656+
unsigned BaseReg, int FrameIdx,
657+
int64_t Offset) const {
652658
assert(0 && "materializeFrameBaseRegister does not exist on this target");
653659
}
654660

@@ -659,11 +665,11 @@ class TargetRegisterInfo {
659665
assert(0 && "resolveFrameIndex does not exist on this target");
660666
}
661667

662-
/// isBaseRegInRange - Determine whether a given base register definition
663-
/// is in range to resolve a frame index.
664-
virtual bool isBaseRegInRange(const MachineInstr *MI, unsigned Reg,
665-
int64_t Offset) const {
666-
assert(0 && "isBaseRegInRange does not exist on this target");
668+
/// isFrameOffsetLegal - Determine whether a given offset immediate is
669+
/// encodable to resolve a frame index.
670+
virtual bool isFrameOffsetLegal(const MachineInstr *MI,
671+
int64_t Offset) const {
672+
assert(0 && "isFrameOffsetLegal does not exist on this target");
667673
return false; // Must return a value in order to compile with VS 2005
668674
}
669675

llvm/lib/CodeGen/LocalStackSlotAllocation.cpp

+21-7
Original file line numberDiff line numberDiff line change
@@ -182,7 +182,7 @@ lookupCandidateBaseReg(const SmallVector<std::pair<unsigned, int64_t>, 8> &Regs,
182182
// Check if the relative offset from the where the base register references
183183
// to the target address is in range for the instruction.
184184
int64_t Offset = LocalFrameOffset - RegOffset.second;
185-
if (TRI->isBaseRegInRange(MI, RegOffset.first, Offset))
185+
if (TRI->isFrameOffsetLegal(MI, Offset))
186186
return true;
187187
}
188188
return false;
@@ -225,20 +225,23 @@ void LocalStackSlotPass::insertFrameReferenceRegisters(MachineFunction &Fn) {
225225
// an object allocated in the local block.
226226
if (MI->getOperand(i).isFI()) {
227227
int FrameIdx = MI->getOperand(i).getIndex();
228+
228229
// Don't try this with values not in the local block.
229230
if (!MFI->isObjectPreAllocated(FrameIdx))
230231
continue;
231232

232233
DEBUG(dbgs() << "Considering: " << *MI);
233234
if (TRI->needsFrameBaseReg(MI, i)) {
234235
unsigned BaseReg = 0;
235-
unsigned Offset = 0;
236+
int64_t Offset = 0;
236237

237238
DEBUG(dbgs() << " Replacing FI in: " << *MI);
238239

239240
// If we have a suitable base register available, use it; otherwise
240-
// create a new one.
241-
241+
// create a new one. Note that any offset encoded in the
242+
// instruction itself will be taken into account by the target,
243+
// so we don't have to adjust for it here when reusing a base
244+
// register.
242245
std::pair<unsigned, int64_t> RegOffset;
243246
if (lookupCandidateBaseReg(BaseRegisters, RegOffset,
244247
LocalOffsets[FrameIdx], MI, TRI)) {
@@ -250,15 +253,26 @@ void LocalStackSlotPass::insertFrameReferenceRegisters(MachineFunction &Fn) {
250253
} else {
251254
// No previously defined register was in range, so create a
252255
// new one.
256+
int64_t InstrOffset = TRI->getFrameIndexInstrOffset(MI, i);
253257
const TargetRegisterClass *RC = TRI->getPointerRegClass();
254258
BaseReg = Fn.getRegInfo().createVirtualRegister(RC);
255259

260+
DEBUG(dbgs() << " Materializing base register " << BaseReg <<
261+
" at frame local offset " <<
262+
LocalOffsets[FrameIdx] + InstrOffset << "\n");
256263
// Tell the target to insert the instruction to initialize
257264
// the base register.
258-
TRI->materializeFrameBaseRegister(I, BaseReg, FrameIdx);
265+
TRI->materializeFrameBaseRegister(I, BaseReg, FrameIdx,
266+
InstrOffset);
267+
268+
// The base register already includes any offset specified
269+
// by the instruction, so account for that so it doesn't get
270+
// applied twice.
271+
Offset = -InstrOffset;
259272

260-
BaseRegisters.push_back(std::pair<unsigned, int64_t>(BaseReg,
261-
Offset));
273+
BaseRegisters.push_back(
274+
std::pair<unsigned, int64_t>(BaseReg,
275+
LocalOffsets[FrameIdx] + InstrOffset));
262276
++NumBaseRegisters;
263277
}
264278
assert(BaseReg != 0 && "Unable to allocate virtual base register!");

llvm/lib/Target/ARM/ARMBaseRegisterInfo.cpp

+61-6
Original file line numberDiff line numberDiff line change
@@ -1367,6 +1367,59 @@ eliminateCallFramePseudoInstr(MachineFunction &MF, MachineBasicBlock &MBB,
13671367
MBB.erase(I);
13681368
}
13691369

1370+
1371+
int64_t ARMBaseRegisterInfo::
1372+
getFrameIndexInstrOffset(MachineInstr *MI, int Idx) const {
1373+
const TargetInstrDesc &Desc = MI->getDesc();
1374+
unsigned AddrMode = (Desc.TSFlags & ARMII::AddrModeMask);
1375+
int64_t InstrOffs = 0;;
1376+
int Scale = 1;
1377+
unsigned ImmIdx = 0;
1378+
switch(AddrMode) {
1379+
case ARMII::AddrModeT2_i8:
1380+
case ARMII::AddrModeT2_i12:
1381+
// i8 supports only negative, and i12 supports only positive, so
1382+
// based on Offset sign, consider the appropriate instruction
1383+
InstrOffs = MI->getOperand(Idx+1).getImm();
1384+
Scale = 1;
1385+
break;
1386+
case ARMII::AddrMode5: {
1387+
// VFP address mode.
1388+
const MachineOperand &OffOp = MI->getOperand(Idx+1);
1389+
int InstrOffs = ARM_AM::getAM5Offset(OffOp.getImm());
1390+
if (ARM_AM::getAM5Op(OffOp.getImm()) == ARM_AM::sub)
1391+
InstrOffs = -InstrOffs;
1392+
Scale = 4;
1393+
break;
1394+
}
1395+
case ARMII::AddrMode2: {
1396+
ImmIdx = Idx+2;
1397+
InstrOffs = ARM_AM::getAM2Offset(MI->getOperand(ImmIdx).getImm());
1398+
if (ARM_AM::getAM2Op(MI->getOperand(ImmIdx).getImm()) == ARM_AM::sub)
1399+
InstrOffs = -InstrOffs;
1400+
break;
1401+
}
1402+
case ARMII::AddrMode3: {
1403+
ImmIdx = Idx+2;
1404+
InstrOffs = ARM_AM::getAM3Offset(MI->getOperand(ImmIdx).getImm());
1405+
if (ARM_AM::getAM3Op(MI->getOperand(ImmIdx).getImm()) == ARM_AM::sub)
1406+
InstrOffs = -InstrOffs;
1407+
break;
1408+
}
1409+
case ARMII::AddrModeT1_s: {
1410+
ImmIdx = Idx+1;
1411+
InstrOffs = MI->getOperand(ImmIdx).getImm();
1412+
Scale = 4;
1413+
break;
1414+
}
1415+
default:
1416+
llvm_unreachable("Unsupported addressing mode!");
1417+
break;
1418+
}
1419+
1420+
return InstrOffs * Scale;
1421+
}
1422+
13701423
/// needsFrameBaseReg - Returns true if the instruction's frame index
13711424
/// reference would be better served by a base register other than FP
13721425
/// or SP. Used by LocalStackFrameAllocation to determine which frame index
@@ -1404,16 +1457,16 @@ needsFrameBaseReg(MachineInstr *MI, unsigned operand) const {
14041457
/// materializeFrameBaseRegister - Insert defining instruction(s) for
14051458
/// BaseReg to be a pointer to FrameIdx before insertion point I.
14061459
void ARMBaseRegisterInfo::
1407-
materializeFrameBaseRegister(MachineBasicBlock::iterator I,
1408-
unsigned BaseReg, int FrameIdx) const {
1460+
materializeFrameBaseRegister(MachineBasicBlock::iterator I, unsigned BaseReg,
1461+
int FrameIdx, int64_t Offset) const {
14091462
ARMFunctionInfo *AFI =
14101463
I->getParent()->getParent()->getInfo<ARMFunctionInfo>();
14111464
unsigned ADDriOpc = !AFI->isThumbFunction() ? ARM::ADDri :
14121465
(AFI->isThumb1OnlyFunction() ? ARM::tADDrSPi : ARM::t2ADDri);
14131466

14141467
MachineInstrBuilder MIB =
14151468
BuildMI(*I->getParent(), I, I->getDebugLoc(), TII.get(ADDriOpc), BaseReg)
1416-
.addFrameIndex(FrameIdx).addImm(0);
1469+
.addFrameIndex(FrameIdx).addImm(Offset);
14171470
if (!AFI->isThumb1OnlyFunction())
14181471
AddDefaultCC(AddDefaultPred(MIB));
14191472
}
@@ -1445,8 +1498,8 @@ ARMBaseRegisterInfo::resolveFrameIndex(MachineBasicBlock::iterator I,
14451498
assert (Done && "Unable to resolve frame index!");
14461499
}
14471500

1448-
bool ARMBaseRegisterInfo::isBaseRegInRange(const MachineInstr *MI,
1449-
unsigned Reg, int64_t Offset) const {
1501+
bool ARMBaseRegisterInfo::isFrameOffsetLegal(const MachineInstr *MI,
1502+
int64_t Offset) const {
14501503
const TargetInstrDesc &Desc = MI->getDesc();
14511504
unsigned AddrMode = (Desc.TSFlags & ARMII::AddrModeMask);
14521505
unsigned i = 0;
@@ -1464,6 +1517,7 @@ bool ARMBaseRegisterInfo::isBaseRegInRange(const MachineInstr *MI,
14641517
unsigned Scale = 1;
14651518
unsigned ImmIdx = 0;
14661519
int InstrOffs = 0;;
1520+
bool isSigned = true;
14671521
switch(AddrMode) {
14681522
case ARMII::AddrModeT2_i8:
14691523
case ARMII::AddrModeT2_i12:
@@ -1509,6 +1563,7 @@ bool ARMBaseRegisterInfo::isBaseRegInRange(const MachineInstr *MI,
15091563
InstrOffs = MI->getOperand(ImmIdx).getImm();
15101564
NumBits = 5;
15111565
Scale = 4;
1566+
isSigned = false;
15121567
break;
15131568
}
15141569
default:
@@ -1518,7 +1573,7 @@ bool ARMBaseRegisterInfo::isBaseRegInRange(const MachineInstr *MI,
15181573

15191574
Offset += InstrOffs * Scale;
15201575
assert((Offset & (Scale-1)) == 0 && "Can't encode this offset!");
1521-
if (Offset < 0)
1576+
if (isSigned && Offset < 0)
15221577
Offset = -Offset;
15231578

15241579
unsigned Mask = (1 << NumBits) - 1;

llvm/lib/Target/ARM/ARMBaseRegisterInfo.h

+4-3
Original file line numberDiff line numberDiff line change
@@ -105,13 +105,14 @@ class ARMBaseRegisterInfo : public ARMGenRegisterInfo {
105105

106106
bool canRealignStack(const MachineFunction &MF) const;
107107
bool needsStackRealignment(const MachineFunction &MF) const;
108+
int64_t getFrameIndexInstrOffset(MachineInstr *MI, int Idx) const;
108109
bool needsFrameBaseReg(MachineInstr *MI, unsigned operand) const;
109110
void materializeFrameBaseRegister(MachineBasicBlock::iterator I,
110-
unsigned BaseReg, int FrameIdx) const;
111+
unsigned BaseReg, int FrameIdx,
112+
int64_t Offset) const;
111113
void resolveFrameIndex(MachineBasicBlock::iterator I,
112114
unsigned BaseReg, int64_t Offset) const;
113-
bool isBaseRegInRange(const MachineInstr *MI, unsigned Reg,
114-
int64_t Offset) const;
115+
bool isFrameOffsetLegal(const MachineInstr *MI, int64_t Offset) const;
115116

116117
bool cannotEliminateFrame(const MachineFunction &MF) const;
117118

0 commit comments

Comments
 (0)