Skip to content

Commit 3cf0866

Browse files
author
Jim Grosbach
committed
Add materialization of virtual base registers for frame indices allocated into
the local block. Resolve references to those indices to a new base register. For simplification and testing purposes, a new virtual base register is allocated for each frame index being resolved. The result is truly horrible, but correct, code that's good for exercising the new code paths. Next up is adding thumb1 support, which should be very simple. Following that will be adding base register re-use and implementing a reasonable ARM heuristic for when a virtual base register should be generated at all. llvm-svn: 111315
1 parent 56df977 commit 3cf0866

File tree

5 files changed

+90
-3
lines changed

5 files changed

+90
-3
lines changed

llvm/include/llvm/Target/TargetRegisterInfo.h

+16
Original file line numberDiff line numberDiff line change
@@ -644,6 +644,22 @@ class TargetRegisterInfo {
644644
return false;
645645
}
646646

647+
/// materializeFrameBaseRegister - Insert defining instruction(s) for
648+
/// BaseReg to be a pointer to FrameIdx before insertion point I.
649+
virtual void materializeFrameBaseRegister(MachineBasicBlock::iterator I,
650+
unsigned BaseReg,
651+
int FrameIdx) const {
652+
assert(0 && "materializeFrameBaseRegister does not exist on this target");
653+
}
654+
655+
/// resolveFrameIndex - Resolve a frame index operand of an instruction
656+
/// to reference the indicated base register plus offset instead.
657+
virtual void resolveFrameIndex(MachineBasicBlock::iterator I,
658+
unsigned BaseReg, int64_t Offset) const {
659+
assert(0 && "resolveFrameIndex does not exist on this target");
660+
}
661+
662+
647663
/// getCallFrameSetup/DestroyOpcode - These methods return the opcode of the
648664
/// frame setup/destroy instructions if they exist (-1 otherwise). Some
649665
/// targets use pseudo instructions in order to abstract away the difference

llvm/lib/CodeGen/LocalStackSlotAllocation.cpp

+26-2
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
#include "llvm/CodeGen/MachineFrameInfo.h"
2828
#include "llvm/CodeGen/MachineFunction.h"
2929
#include "llvm/CodeGen/MachineFunctionPass.h"
30+
#include "llvm/CodeGen/MachineRegisterInfo.h"
3031
#include "llvm/CodeGen/Passes.h"
3132
#include "llvm/Support/Debug.h"
3233
#include "llvm/Support/ErrorHandling.h"
@@ -160,6 +161,14 @@ void LocalStackSlotPass::insertFrameReferenceRegisters(MachineFunction &Fn) {
160161
E = Fn.end(); BB != E; ++BB) {
161162
for (MachineBasicBlock::iterator I = BB->begin(); I != BB->end(); ++I) {
162163
MachineInstr *MI = I;
164+
// Debug value instructions can't be out of range, so they don't need
165+
// any updates.
166+
// FIXME: When we extend this stuff to handle functions with both
167+
// VLAs and dynamic realignment, we should update the debug values
168+
// to reference the new base pointer when possible.
169+
if (MI->isDebugValue())
170+
continue;
171+
163172
// For now, allocate the base register(s) within the basic block
164173
// where they're used, and don't try to keep them around outside
165174
// of that. It may be beneficial to try sharing them more broadly
@@ -169,8 +178,12 @@ void LocalStackSlotPass::insertFrameReferenceRegisters(MachineFunction &Fn) {
169178
for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) {
170179
// Consider replacing all frame index operands that reference
171180
// an object allocated in the local block.
172-
if (MI->getOperand(i).isFI() &&
173-
MFI->isObjectPreAllocated(MI->getOperand(i).getIndex())) {
181+
if (MI->getOperand(i).isFI()) {
182+
int FrameIdx = MI->getOperand(i).getIndex();
183+
// Don't try this with values not in the local block.
184+
if (!MFI->isObjectPreAllocated(FrameIdx))
185+
continue;
186+
174187
DEBUG(dbgs() << "Considering: " << *MI);
175188
if (TRI->needsFrameBaseReg(MI, i)) {
176189
DEBUG(dbgs() << " Replacing FI in: " << *MI);
@@ -182,6 +195,17 @@ void LocalStackSlotPass::insertFrameReferenceRegisters(MachineFunction &Fn) {
182195
// create a new one.
183196
// FIXME: For the moment, just always create a new one.
184197

198+
const TargetRegisterClass *RC = TRI->getPointerRegClass();
199+
unsigned BaseReg = Fn.getRegInfo().createVirtualRegister(RC);
200+
201+
// Tell the target to insert the instruction to initialize
202+
// the base register.
203+
TRI->materializeFrameBaseRegister(I, BaseReg, FrameIdx);
204+
205+
// Modify the instruction to use the new base register rather
206+
// than the frame index operand.
207+
TRI->resolveFrameIndex(I, BaseReg, 0);
208+
185209
++NumBaseRegisters;
186210
++NumReplacements;
187211
}

llvm/lib/CodeGen/PrologEpilogInserter.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -560,7 +560,7 @@ void PEI::calculateFrameObjectOffsets(MachineFunction &Fn) {
560560
// check for whether the frame is large enough to want to use virtual
561561
// frame index registers. Functions which don't want/need this optimization
562562
// will continue to use the existing code path.
563-
if (EnableLocalStackAlloc) {
563+
if (EnableLocalStackAlloc && MFI->getLocalFrameSize()) {
564564
unsigned Align = MFI->getLocalFrameMaxAlign();
565565

566566
// Adjust to alignment boundary.

llvm/lib/Target/ARM/ARMBaseRegisterInfo.cpp

+43
Original file line numberDiff line numberDiff line change
@@ -1407,6 +1407,49 @@ needsFrameBaseReg(MachineInstr *MI, unsigned operand) const {
14071407
}
14081408
}
14091409

1410+
/// materializeFrameBaseRegister - Insert defining instruction(s) for
1411+
/// BaseReg to be a pointer to FrameIdx before insertion point I.
1412+
void ARMBaseRegisterInfo::
1413+
materializeFrameBaseRegister(MachineBasicBlock::iterator I,
1414+
unsigned BaseReg, int FrameIdx) const {
1415+
ARMFunctionInfo *AFI =
1416+
I->getParent()->getParent()->getInfo<ARMFunctionInfo>();
1417+
unsigned ADDriOpc = !AFI->isThumbFunction() ? ARM::ADDri : ARM::t2ADDri;
1418+
assert(!AFI->isThumb1OnlyFunction() &&
1419+
"This materializeFrameBaseRegister does not support Thumb1!");
1420+
1421+
MachineInstrBuilder MIB =
1422+
BuildMI(*I->getParent(), I, I->getDebugLoc(), TII.get(ADDriOpc), BaseReg)
1423+
.addFrameIndex(FrameIdx).addImm(0);
1424+
AddDefaultCC(AddDefaultPred(MIB));
1425+
}
1426+
1427+
void
1428+
ARMBaseRegisterInfo::resolveFrameIndex(MachineBasicBlock::iterator I,
1429+
unsigned BaseReg, int64_t Offset) const {
1430+
MachineInstr &MI = *I;
1431+
MachineBasicBlock &MBB = *MI.getParent();
1432+
MachineFunction &MF = *MBB.getParent();
1433+
ARMFunctionInfo *AFI = MF.getInfo<ARMFunctionInfo>();
1434+
int Off = Offset; // ARM doesn't need the general 64-bit offsets
1435+
unsigned i = 0;
1436+
1437+
assert(!AFI->isThumb1OnlyFunction() &&
1438+
"This resolveFrameIndex does not support Thumb1!");
1439+
1440+
while (!MI.getOperand(i).isFI()) {
1441+
++i;
1442+
assert(i < MI.getNumOperands() && "Instr doesn't have FrameIndex operand!");
1443+
}
1444+
bool Done = false;
1445+
if (!AFI->isThumbFunction())
1446+
Done = rewriteARMFrameIndex(MI, i, BaseReg, Off, TII);
1447+
else {
1448+
assert(AFI->isThumb2Function());
1449+
Done = rewriteT2FrameIndex(MI, i, BaseReg, Off, TII);
1450+
}
1451+
assert (Done && "Unable to resolve frame index!");
1452+
}
14101453

14111454
unsigned
14121455
ARMBaseRegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II,

llvm/lib/Target/ARM/ARMBaseRegisterInfo.h

+4
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,10 @@ class ARMBaseRegisterInfo : public ARMGenRegisterInfo {
106106
bool canRealignStack(const MachineFunction &MF) const;
107107
bool needsStackRealignment(const MachineFunction &MF) const;
108108
bool needsFrameBaseReg(MachineInstr *MI, unsigned operand) const;
109+
void materializeFrameBaseRegister(MachineBasicBlock::iterator I,
110+
unsigned BaseReg, int FrameIdx) const;
111+
void resolveFrameIndex(MachineBasicBlock::iterator I,
112+
unsigned BaseReg, int64_t Offset) const;
109113

110114
bool cannotEliminateFrame(const MachineFunction &MF) const;
111115

0 commit comments

Comments
 (0)