mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-06-28 06:24:57 +00:00
Move more PEI-related hooks to TFI
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@120229 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
@ -24,6 +24,7 @@ namespace llvm {
|
|||||||
class MachineFunction;
|
class MachineFunction;
|
||||||
class MachineBasicBlock;
|
class MachineBasicBlock;
|
||||||
class MachineMove;
|
class MachineMove;
|
||||||
|
class RegScavenger;
|
||||||
|
|
||||||
/// Information about stack frame layout on the target. It holds the direction
|
/// Information about stack frame layout on the target. It holds the direction
|
||||||
/// of stack growth, the known stack alignment on entry to each function, and
|
/// of stack growth, the known stack alignment on entry to each function, and
|
||||||
@ -172,6 +173,22 @@ public:
|
|||||||
/// returned directly, and the base register is returned via FrameReg.
|
/// returned directly, and the base register is returned via FrameReg.
|
||||||
virtual int getFrameIndexReference(const MachineFunction &MF, int FI,
|
virtual int getFrameIndexReference(const MachineFunction &MF, int FI,
|
||||||
unsigned &FrameReg) const;
|
unsigned &FrameReg) const;
|
||||||
|
|
||||||
|
/// processFunctionBeforeCalleeSavedScan - This method is called immediately
|
||||||
|
/// before PrologEpilogInserter scans the physical registers used to determine
|
||||||
|
/// what callee saved registers should be spilled. This method is optional.
|
||||||
|
virtual void processFunctionBeforeCalleeSavedScan(MachineFunction &MF,
|
||||||
|
RegScavenger *RS = NULL) const {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/// processFunctionBeforeFrameFinalized - This method is called immediately
|
||||||
|
/// before the specified function's frame layout (MF.getFrameInfo()) is
|
||||||
|
/// finalized. Once the frame is finalized, MO_FrameIndex operands are
|
||||||
|
/// replaced with direct constants. This method is optional.
|
||||||
|
///
|
||||||
|
virtual void processFunctionBeforeFrameFinalized(MachineFunction &MF) const {
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
} // End llvm namespace
|
} // End llvm namespace
|
||||||
|
@ -678,21 +678,6 @@ public:
|
|||||||
assert(0 && "Call Frame Pseudo Instructions do not exist on this target!");
|
assert(0 && "Call Frame Pseudo Instructions do not exist on this target!");
|
||||||
}
|
}
|
||||||
|
|
||||||
/// processFunctionBeforeCalleeSavedScan - This method is called immediately
|
|
||||||
/// before PrologEpilogInserter scans the physical registers used to determine
|
|
||||||
/// what callee saved registers should be spilled. This method is optional.
|
|
||||||
virtual void processFunctionBeforeCalleeSavedScan(MachineFunction &MF,
|
|
||||||
RegScavenger *RS = NULL) const {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/// processFunctionBeforeFrameFinalized - This method is called immediately
|
|
||||||
/// before the specified function's frame layout (MF.getFrameInfo()) is
|
|
||||||
/// finalized. Once the frame is finalized, MO_FrameIndex operands are
|
|
||||||
/// replaced with direct constants. This method is optional.
|
|
||||||
///
|
|
||||||
virtual void processFunctionBeforeFrameFinalized(MachineFunction &MF) const {
|
|
||||||
}
|
|
||||||
|
|
||||||
/// saveScavengerRegister - Spill the register so it can be used by the
|
/// saveScavengerRegister - Spill the register so it can be used by the
|
||||||
/// register scavenger. Return true if the register was spilled, false
|
/// register scavenger. Return true if the register was spilled, false
|
||||||
|
@ -65,6 +65,8 @@ FunctionPass *llvm::createPrologEpilogCodeInserter() { return new PEI(); }
|
|||||||
bool PEI::runOnMachineFunction(MachineFunction &Fn) {
|
bool PEI::runOnMachineFunction(MachineFunction &Fn) {
|
||||||
const Function* F = Fn.getFunction();
|
const Function* F = Fn.getFunction();
|
||||||
const TargetRegisterInfo *TRI = Fn.getTarget().getRegisterInfo();
|
const TargetRegisterInfo *TRI = Fn.getTarget().getRegisterInfo();
|
||||||
|
const TargetFrameInfo *TFI = Fn.getTarget().getFrameInfo();
|
||||||
|
|
||||||
RS = TRI->requiresRegisterScavenging(Fn) ? new RegScavenger() : NULL;
|
RS = TRI->requiresRegisterScavenging(Fn) ? new RegScavenger() : NULL;
|
||||||
FrameIndexVirtualScavenging = TRI->requiresFrameIndexScavenging(Fn);
|
FrameIndexVirtualScavenging = TRI->requiresFrameIndexScavenging(Fn);
|
||||||
|
|
||||||
@ -75,7 +77,7 @@ bool PEI::runOnMachineFunction(MachineFunction &Fn) {
|
|||||||
|
|
||||||
// Allow the target machine to make some adjustments to the function
|
// Allow the target machine to make some adjustments to the function
|
||||||
// e.g. UsedPhysRegs before calculateCalleeSavedRegisters.
|
// e.g. UsedPhysRegs before calculateCalleeSavedRegisters.
|
||||||
TRI->processFunctionBeforeCalleeSavedScan(Fn, RS);
|
TFI->processFunctionBeforeCalleeSavedScan(Fn, RS);
|
||||||
|
|
||||||
// Scan the function for modified callee saved registers and insert spill code
|
// Scan the function for modified callee saved registers and insert spill code
|
||||||
// for any callee saved registers that are modified.
|
// for any callee saved registers that are modified.
|
||||||
@ -95,7 +97,7 @@ bool PEI::runOnMachineFunction(MachineFunction &Fn) {
|
|||||||
|
|
||||||
// Allow the target machine to make final modifications to the function
|
// Allow the target machine to make final modifications to the function
|
||||||
// before the frame layout is finalized.
|
// before the frame layout is finalized.
|
||||||
TRI->processFunctionBeforeFrameFinalized(Fn);
|
TFI->processFunctionBeforeFrameFinalized(Fn);
|
||||||
|
|
||||||
// Calculate actual frame offsets for all abstract stack objects...
|
// Calculate actual frame offsets for all abstract stack objects...
|
||||||
calculateFrameObjectOffsets(Fn);
|
calculateFrameObjectOffsets(Fn);
|
||||||
|
@ -591,328 +591,6 @@ cannotEliminateFrame(const MachineFunction &MF) const {
|
|||||||
|| needsStackRealignment(MF);
|
|| needsStackRealignment(MF);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// estimateStackSize - Estimate and return the size of the frame.
|
|
||||||
static unsigned estimateStackSize(MachineFunction &MF) {
|
|
||||||
const MachineFrameInfo *FFI = MF.getFrameInfo();
|
|
||||||
int Offset = 0;
|
|
||||||
for (int i = FFI->getObjectIndexBegin(); i != 0; ++i) {
|
|
||||||
int FixedOff = -FFI->getObjectOffset(i);
|
|
||||||
if (FixedOff > Offset) Offset = FixedOff;
|
|
||||||
}
|
|
||||||
for (unsigned i = 0, e = FFI->getObjectIndexEnd(); i != e; ++i) {
|
|
||||||
if (FFI->isDeadObjectIndex(i))
|
|
||||||
continue;
|
|
||||||
Offset += FFI->getObjectSize(i);
|
|
||||||
unsigned Align = FFI->getObjectAlignment(i);
|
|
||||||
// Adjust to alignment boundary
|
|
||||||
Offset = (Offset+Align-1)/Align*Align;
|
|
||||||
}
|
|
||||||
return (unsigned)Offset;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// estimateRSStackSizeLimit - Look at each instruction that references stack
|
|
||||||
/// frames and return the stack size limit beyond which some of these
|
|
||||||
/// instructions will require a scratch register during their expansion later.
|
|
||||||
unsigned
|
|
||||||
ARMBaseRegisterInfo::estimateRSStackSizeLimit(MachineFunction &MF) const {
|
|
||||||
const TargetFrameInfo *TFI = MF.getTarget().getFrameInfo();
|
|
||||||
const ARMFunctionInfo *AFI = MF.getInfo<ARMFunctionInfo>();
|
|
||||||
unsigned Limit = (1 << 12) - 1;
|
|
||||||
for (MachineFunction::iterator BB = MF.begin(),E = MF.end(); BB != E; ++BB) {
|
|
||||||
for (MachineBasicBlock::iterator I = BB->begin(), E = BB->end();
|
|
||||||
I != E; ++I) {
|
|
||||||
for (unsigned i = 0, e = I->getNumOperands(); i != e; ++i) {
|
|
||||||
if (!I->getOperand(i).isFI()) continue;
|
|
||||||
|
|
||||||
// When using ADDri to get the address of a stack object, 255 is the
|
|
||||||
// largest offset guaranteed to fit in the immediate offset.
|
|
||||||
if (I->getOpcode() == ARM::ADDri) {
|
|
||||||
Limit = std::min(Limit, (1U << 8) - 1);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Otherwise check the addressing mode.
|
|
||||||
switch (I->getDesc().TSFlags & ARMII::AddrModeMask) {
|
|
||||||
case ARMII::AddrMode3:
|
|
||||||
case ARMII::AddrModeT2_i8:
|
|
||||||
Limit = std::min(Limit, (1U << 8) - 1);
|
|
||||||
break;
|
|
||||||
case ARMII::AddrMode5:
|
|
||||||
case ARMII::AddrModeT2_i8s4:
|
|
||||||
Limit = std::min(Limit, ((1U << 8) - 1) * 4);
|
|
||||||
break;
|
|
||||||
case ARMII::AddrModeT2_i12:
|
|
||||||
// i12 supports only positive offset so these will be converted to
|
|
||||||
// i8 opcodes. See llvm::rewriteT2FrameIndex.
|
|
||||||
if (TFI->hasFP(MF) && AFI->hasStackFrame())
|
|
||||||
Limit = std::min(Limit, (1U << 8) - 1);
|
|
||||||
break;
|
|
||||||
case ARMII::AddrMode4:
|
|
||||||
case ARMII::AddrMode6:
|
|
||||||
// Addressing modes 4 & 6 (load/store) instructions can't encode an
|
|
||||||
// immediate offset for stack references.
|
|
||||||
return 0;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
break; // At most one FI per instruction
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return Limit;
|
|
||||||
}
|
|
||||||
|
|
||||||
static unsigned GetFunctionSizeInBytes(const MachineFunction &MF,
|
|
||||||
const ARMBaseInstrInfo &TII) {
|
|
||||||
unsigned FnSize = 0;
|
|
||||||
for (MachineFunction::const_iterator MBBI = MF.begin(), E = MF.end();
|
|
||||||
MBBI != E; ++MBBI) {
|
|
||||||
const MachineBasicBlock &MBB = *MBBI;
|
|
||||||
for (MachineBasicBlock::const_iterator I = MBB.begin(),E = MBB.end();
|
|
||||||
I != E; ++I)
|
|
||||||
FnSize += TII.GetInstSizeInBytes(I);
|
|
||||||
}
|
|
||||||
return FnSize;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
ARMBaseRegisterInfo::processFunctionBeforeCalleeSavedScan(MachineFunction &MF,
|
|
||||||
RegScavenger *RS) const {
|
|
||||||
// This tells PEI to spill the FP as if it is any other callee-save register
|
|
||||||
// to take advantage the eliminateFrameIndex machinery. This also ensures it
|
|
||||||
// is spilled in the order specified by getCalleeSavedRegs() to make it easier
|
|
||||||
// to combine multiple loads / stores.
|
|
||||||
bool CanEliminateFrame = true;
|
|
||||||
bool CS1Spilled = false;
|
|
||||||
bool LRSpilled = false;
|
|
||||||
unsigned NumGPRSpills = 0;
|
|
||||||
SmallVector<unsigned, 4> UnspilledCS1GPRs;
|
|
||||||
SmallVector<unsigned, 4> UnspilledCS2GPRs;
|
|
||||||
const TargetFrameInfo *TFI = MF.getTarget().getFrameInfo();
|
|
||||||
ARMFunctionInfo *AFI = MF.getInfo<ARMFunctionInfo>();
|
|
||||||
MachineFrameInfo *MFI = MF.getFrameInfo();
|
|
||||||
|
|
||||||
// Spill R4 if Thumb2 function requires stack realignment - it will be used as
|
|
||||||
// scratch register. Also spill R4 if Thumb2 function has varsized objects,
|
|
||||||
// since it's always posible to restore sp from fp in a single instruction.
|
|
||||||
// FIXME: It will be better just to find spare register here.
|
|
||||||
if (AFI->isThumb2Function() &&
|
|
||||||
(MFI->hasVarSizedObjects() || needsStackRealignment(MF)))
|
|
||||||
MF.getRegInfo().setPhysRegUsed(ARM::R4);
|
|
||||||
|
|
||||||
// Spill LR if Thumb1 function uses variable length argument lists.
|
|
||||||
if (AFI->isThumb1OnlyFunction() && AFI->getVarArgsRegSaveSize() > 0)
|
|
||||||
MF.getRegInfo().setPhysRegUsed(ARM::LR);
|
|
||||||
|
|
||||||
// Spill the BasePtr if it's used.
|
|
||||||
if (hasBasePointer(MF))
|
|
||||||
MF.getRegInfo().setPhysRegUsed(BasePtr);
|
|
||||||
|
|
||||||
// Don't spill FP if the frame can be eliminated. This is determined
|
|
||||||
// by scanning the callee-save registers to see if any is used.
|
|
||||||
const unsigned *CSRegs = getCalleeSavedRegs();
|
|
||||||
for (unsigned i = 0; CSRegs[i]; ++i) {
|
|
||||||
unsigned Reg = CSRegs[i];
|
|
||||||
bool Spilled = false;
|
|
||||||
if (MF.getRegInfo().isPhysRegUsed(Reg)) {
|
|
||||||
AFI->setCSRegisterIsSpilled(Reg);
|
|
||||||
Spilled = true;
|
|
||||||
CanEliminateFrame = false;
|
|
||||||
} else {
|
|
||||||
// Check alias registers too.
|
|
||||||
for (const unsigned *Aliases = getAliasSet(Reg); *Aliases; ++Aliases) {
|
|
||||||
if (MF.getRegInfo().isPhysRegUsed(*Aliases)) {
|
|
||||||
Spilled = true;
|
|
||||||
CanEliminateFrame = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!ARM::GPRRegisterClass->contains(Reg))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (Spilled) {
|
|
||||||
NumGPRSpills++;
|
|
||||||
|
|
||||||
if (!STI.isTargetDarwin()) {
|
|
||||||
if (Reg == ARM::LR)
|
|
||||||
LRSpilled = true;
|
|
||||||
CS1Spilled = true;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Keep track if LR and any of R4, R5, R6, and R7 is spilled.
|
|
||||||
switch (Reg) {
|
|
||||||
case ARM::LR:
|
|
||||||
LRSpilled = true;
|
|
||||||
// Fallthrough
|
|
||||||
case ARM::R4:
|
|
||||||
case ARM::R5:
|
|
||||||
case ARM::R6:
|
|
||||||
case ARM::R7:
|
|
||||||
CS1Spilled = true;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (!STI.isTargetDarwin()) {
|
|
||||||
UnspilledCS1GPRs.push_back(Reg);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (Reg) {
|
|
||||||
case ARM::R4:
|
|
||||||
case ARM::R5:
|
|
||||||
case ARM::R6:
|
|
||||||
case ARM::R7:
|
|
||||||
case ARM::LR:
|
|
||||||
UnspilledCS1GPRs.push_back(Reg);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
UnspilledCS2GPRs.push_back(Reg);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool ForceLRSpill = false;
|
|
||||||
if (!LRSpilled && AFI->isThumb1OnlyFunction()) {
|
|
||||||
unsigned FnSize = GetFunctionSizeInBytes(MF, TII);
|
|
||||||
// Force LR to be spilled if the Thumb function size is > 2048. This enables
|
|
||||||
// use of BL to implement far jump. If it turns out that it's not needed
|
|
||||||
// then the branch fix up path will undo it.
|
|
||||||
if (FnSize >= (1 << 11)) {
|
|
||||||
CanEliminateFrame = false;
|
|
||||||
ForceLRSpill = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// If any of the stack slot references may be out of range of an immediate
|
|
||||||
// offset, make sure a register (or a spill slot) is available for the
|
|
||||||
// register scavenger. Note that if we're indexing off the frame pointer, the
|
|
||||||
// effective stack size is 4 bytes larger since the FP points to the stack
|
|
||||||
// slot of the previous FP. Also, if we have variable sized objects in the
|
|
||||||
// function, stack slot references will often be negative, and some of
|
|
||||||
// our instructions are positive-offset only, so conservatively consider
|
|
||||||
// that case to want a spill slot (or register) as well. Similarly, if
|
|
||||||
// the function adjusts the stack pointer during execution and the
|
|
||||||
// adjustments aren't already part of our stack size estimate, our offset
|
|
||||||
// calculations may be off, so be conservative.
|
|
||||||
// FIXME: We could add logic to be more precise about negative offsets
|
|
||||||
// and which instructions will need a scratch register for them. Is it
|
|
||||||
// worth the effort and added fragility?
|
|
||||||
bool BigStack =
|
|
||||||
(RS &&
|
|
||||||
(estimateStackSize(MF) + ((TFI->hasFP(MF) && AFI->hasStackFrame()) ? 4:0) >=
|
|
||||||
estimateRSStackSizeLimit(MF)))
|
|
||||||
|| MFI->hasVarSizedObjects()
|
|
||||||
|| (MFI->adjustsStack() && !TFI->canSimplifyCallFramePseudos(MF));
|
|
||||||
|
|
||||||
bool ExtraCSSpill = false;
|
|
||||||
if (BigStack || !CanEliminateFrame || cannotEliminateFrame(MF)) {
|
|
||||||
AFI->setHasStackFrame(true);
|
|
||||||
|
|
||||||
// If LR is not spilled, but at least one of R4, R5, R6, and R7 is spilled.
|
|
||||||
// Spill LR as well so we can fold BX_RET to the registers restore (LDM).
|
|
||||||
if (!LRSpilled && CS1Spilled) {
|
|
||||||
MF.getRegInfo().setPhysRegUsed(ARM::LR);
|
|
||||||
AFI->setCSRegisterIsSpilled(ARM::LR);
|
|
||||||
NumGPRSpills++;
|
|
||||||
UnspilledCS1GPRs.erase(std::find(UnspilledCS1GPRs.begin(),
|
|
||||||
UnspilledCS1GPRs.end(), (unsigned)ARM::LR));
|
|
||||||
ForceLRSpill = false;
|
|
||||||
ExtraCSSpill = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (TFI->hasFP(MF)) {
|
|
||||||
MF.getRegInfo().setPhysRegUsed(FramePtr);
|
|
||||||
NumGPRSpills++;
|
|
||||||
}
|
|
||||||
|
|
||||||
// If stack and double are 8-byte aligned and we are spilling an odd number
|
|
||||||
// of GPRs, spill one extra callee save GPR so we won't have to pad between
|
|
||||||
// the integer and double callee save areas.
|
|
||||||
unsigned TargetAlign = MF.getTarget().getFrameInfo()->getStackAlignment();
|
|
||||||
if (TargetAlign == 8 && (NumGPRSpills & 1)) {
|
|
||||||
if (CS1Spilled && !UnspilledCS1GPRs.empty()) {
|
|
||||||
for (unsigned i = 0, e = UnspilledCS1GPRs.size(); i != e; ++i) {
|
|
||||||
unsigned Reg = UnspilledCS1GPRs[i];
|
|
||||||
// Don't spill high register if the function is thumb1
|
|
||||||
if (!AFI->isThumb1OnlyFunction() ||
|
|
||||||
isARMLowRegister(Reg) || Reg == ARM::LR) {
|
|
||||||
MF.getRegInfo().setPhysRegUsed(Reg);
|
|
||||||
AFI->setCSRegisterIsSpilled(Reg);
|
|
||||||
if (!isReservedReg(MF, Reg))
|
|
||||||
ExtraCSSpill = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else if (!UnspilledCS2GPRs.empty() &&
|
|
||||||
!AFI->isThumb1OnlyFunction()) {
|
|
||||||
unsigned Reg = UnspilledCS2GPRs.front();
|
|
||||||
MF.getRegInfo().setPhysRegUsed(Reg);
|
|
||||||
AFI->setCSRegisterIsSpilled(Reg);
|
|
||||||
if (!isReservedReg(MF, Reg))
|
|
||||||
ExtraCSSpill = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Estimate if we might need to scavenge a register at some point in order
|
|
||||||
// to materialize a stack offset. If so, either spill one additional
|
|
||||||
// callee-saved register or reserve a special spill slot to facilitate
|
|
||||||
// register scavenging. Thumb1 needs a spill slot for stack pointer
|
|
||||||
// adjustments also, even when the frame itself is small.
|
|
||||||
if (BigStack && !ExtraCSSpill) {
|
|
||||||
// If any non-reserved CS register isn't spilled, just spill one or two
|
|
||||||
// extra. That should take care of it!
|
|
||||||
unsigned NumExtras = TargetAlign / 4;
|
|
||||||
SmallVector<unsigned, 2> Extras;
|
|
||||||
while (NumExtras && !UnspilledCS1GPRs.empty()) {
|
|
||||||
unsigned Reg = UnspilledCS1GPRs.back();
|
|
||||||
UnspilledCS1GPRs.pop_back();
|
|
||||||
if (!isReservedReg(MF, Reg) &&
|
|
||||||
(!AFI->isThumb1OnlyFunction() || isARMLowRegister(Reg) ||
|
|
||||||
Reg == ARM::LR)) {
|
|
||||||
Extras.push_back(Reg);
|
|
||||||
NumExtras--;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// For non-Thumb1 functions, also check for hi-reg CS registers
|
|
||||||
if (!AFI->isThumb1OnlyFunction()) {
|
|
||||||
while (NumExtras && !UnspilledCS2GPRs.empty()) {
|
|
||||||
unsigned Reg = UnspilledCS2GPRs.back();
|
|
||||||
UnspilledCS2GPRs.pop_back();
|
|
||||||
if (!isReservedReg(MF, Reg)) {
|
|
||||||
Extras.push_back(Reg);
|
|
||||||
NumExtras--;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (Extras.size() && NumExtras == 0) {
|
|
||||||
for (unsigned i = 0, e = Extras.size(); i != e; ++i) {
|
|
||||||
MF.getRegInfo().setPhysRegUsed(Extras[i]);
|
|
||||||
AFI->setCSRegisterIsSpilled(Extras[i]);
|
|
||||||
}
|
|
||||||
} else if (!AFI->isThumb1OnlyFunction()) {
|
|
||||||
// note: Thumb1 functions spill to R12, not the stack. Reserve a slot
|
|
||||||
// closest to SP or frame pointer.
|
|
||||||
const TargetRegisterClass *RC = ARM::GPRRegisterClass;
|
|
||||||
RS->setScavengingFrameIndex(MFI->CreateStackObject(RC->getSize(),
|
|
||||||
RC->getAlignment(),
|
|
||||||
false));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ForceLRSpill) {
|
|
||||||
MF.getRegInfo().setPhysRegUsed(ARM::LR);
|
|
||||||
AFI->setCSRegisterIsSpilled(ARM::LR);
|
|
||||||
AFI->setLRIsSpilledForFarJump(true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned ARMBaseRegisterInfo::getRARegister() const {
|
unsigned ARMBaseRegisterInfo::getRARegister() const {
|
||||||
return ARM::LR;
|
return ARM::LR;
|
||||||
}
|
}
|
||||||
|
@ -154,9 +154,6 @@ public:
|
|||||||
|
|
||||||
bool cannotEliminateFrame(const MachineFunction &MF) const;
|
bool cannotEliminateFrame(const MachineFunction &MF) const;
|
||||||
|
|
||||||
void processFunctionBeforeCalleeSavedScan(MachineFunction &MF,
|
|
||||||
RegScavenger *RS = NULL) const;
|
|
||||||
|
|
||||||
// Debug information queries.
|
// Debug information queries.
|
||||||
unsigned getRARegister() const;
|
unsigned getRARegister() const;
|
||||||
unsigned getFrameRegister(const MachineFunction &MF) const;
|
unsigned getFrameRegister(const MachineFunction &MF) const;
|
||||||
@ -198,8 +195,6 @@ public:
|
|||||||
int SPAdj, RegScavenger *RS = NULL) const;
|
int SPAdj, RegScavenger *RS = NULL) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
unsigned estimateRSStackSizeLimit(MachineFunction &MF) const;
|
|
||||||
|
|
||||||
unsigned getRegisterPairEven(unsigned Reg, const MachineFunction &MF) const;
|
unsigned getRegisterPairEven(unsigned Reg, const MachineFunction &MF) const;
|
||||||
|
|
||||||
unsigned getRegisterPairOdd(unsigned Reg, const MachineFunction &MF) const;
|
unsigned getRegisterPairOdd(unsigned Reg, const MachineFunction &MF) const;
|
||||||
|
@ -18,6 +18,7 @@
|
|||||||
#include "llvm/CodeGen/MachineFunction.h"
|
#include "llvm/CodeGen/MachineFunction.h"
|
||||||
#include "llvm/CodeGen/MachineInstrBuilder.h"
|
#include "llvm/CodeGen/MachineInstrBuilder.h"
|
||||||
#include "llvm/CodeGen/MachineRegisterInfo.h"
|
#include "llvm/CodeGen/MachineRegisterInfo.h"
|
||||||
|
#include "llvm/CodeGen/RegisterScavenging.h"
|
||||||
#include "llvm/Target/TargetOptions.h"
|
#include "llvm/Target/TargetOptions.h"
|
||||||
|
|
||||||
using namespace llvm;
|
using namespace llvm;
|
||||||
@ -614,3 +615,327 @@ bool ARMFrameInfo::restoreCalleeSavedRegisters(MachineBasicBlock &MBB,
|
|||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// FIXME: Make generic?
|
||||||
|
static unsigned GetFunctionSizeInBytes(const MachineFunction &MF,
|
||||||
|
const ARMBaseInstrInfo &TII) {
|
||||||
|
unsigned FnSize = 0;
|
||||||
|
for (MachineFunction::const_iterator MBBI = MF.begin(), E = MF.end();
|
||||||
|
MBBI != E; ++MBBI) {
|
||||||
|
const MachineBasicBlock &MBB = *MBBI;
|
||||||
|
for (MachineBasicBlock::const_iterator I = MBB.begin(),E = MBB.end();
|
||||||
|
I != E; ++I)
|
||||||
|
FnSize += TII.GetInstSizeInBytes(I);
|
||||||
|
}
|
||||||
|
return FnSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// estimateStackSize - Estimate and return the size of the frame.
|
||||||
|
/// FIXME: Make generic?
|
||||||
|
static unsigned estimateStackSize(MachineFunction &MF) {
|
||||||
|
const MachineFrameInfo *FFI = MF.getFrameInfo();
|
||||||
|
int Offset = 0;
|
||||||
|
for (int i = FFI->getObjectIndexBegin(); i != 0; ++i) {
|
||||||
|
int FixedOff = -FFI->getObjectOffset(i);
|
||||||
|
if (FixedOff > Offset) Offset = FixedOff;
|
||||||
|
}
|
||||||
|
for (unsigned i = 0, e = FFI->getObjectIndexEnd(); i != e; ++i) {
|
||||||
|
if (FFI->isDeadObjectIndex(i))
|
||||||
|
continue;
|
||||||
|
Offset += FFI->getObjectSize(i);
|
||||||
|
unsigned Align = FFI->getObjectAlignment(i);
|
||||||
|
// Adjust to alignment boundary
|
||||||
|
Offset = (Offset+Align-1)/Align*Align;
|
||||||
|
}
|
||||||
|
return (unsigned)Offset;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// estimateRSStackSizeLimit - Look at each instruction that references stack
|
||||||
|
/// frames and return the stack size limit beyond which some of these
|
||||||
|
/// instructions will require a scratch register during their expansion later.
|
||||||
|
// FIXME: Move to TII?
|
||||||
|
static unsigned estimateRSStackSizeLimit(MachineFunction &MF,
|
||||||
|
const TargetFrameInfo *TFI) {
|
||||||
|
const ARMFunctionInfo *AFI = MF.getInfo<ARMFunctionInfo>();
|
||||||
|
unsigned Limit = (1 << 12) - 1;
|
||||||
|
for (MachineFunction::iterator BB = MF.begin(),E = MF.end(); BB != E; ++BB) {
|
||||||
|
for (MachineBasicBlock::iterator I = BB->begin(), E = BB->end();
|
||||||
|
I != E; ++I) {
|
||||||
|
for (unsigned i = 0, e = I->getNumOperands(); i != e; ++i) {
|
||||||
|
if (!I->getOperand(i).isFI()) continue;
|
||||||
|
|
||||||
|
// When using ADDri to get the address of a stack object, 255 is the
|
||||||
|
// largest offset guaranteed to fit in the immediate offset.
|
||||||
|
if (I->getOpcode() == ARM::ADDri) {
|
||||||
|
Limit = std::min(Limit, (1U << 8) - 1);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Otherwise check the addressing mode.
|
||||||
|
switch (I->getDesc().TSFlags & ARMII::AddrModeMask) {
|
||||||
|
case ARMII::AddrMode3:
|
||||||
|
case ARMII::AddrModeT2_i8:
|
||||||
|
Limit = std::min(Limit, (1U << 8) - 1);
|
||||||
|
break;
|
||||||
|
case ARMII::AddrMode5:
|
||||||
|
case ARMII::AddrModeT2_i8s4:
|
||||||
|
Limit = std::min(Limit, ((1U << 8) - 1) * 4);
|
||||||
|
break;
|
||||||
|
case ARMII::AddrModeT2_i12:
|
||||||
|
// i12 supports only positive offset so these will be converted to
|
||||||
|
// i8 opcodes. See llvm::rewriteT2FrameIndex.
|
||||||
|
if (TFI->hasFP(MF) && AFI->hasStackFrame())
|
||||||
|
Limit = std::min(Limit, (1U << 8) - 1);
|
||||||
|
break;
|
||||||
|
case ARMII::AddrMode4:
|
||||||
|
case ARMII::AddrMode6:
|
||||||
|
// Addressing modes 4 & 6 (load/store) instructions can't encode an
|
||||||
|
// immediate offset for stack references.
|
||||||
|
return 0;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break; // At most one FI per instruction
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return Limit;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
ARMFrameInfo::processFunctionBeforeCalleeSavedScan(MachineFunction &MF,
|
||||||
|
RegScavenger *RS) const {
|
||||||
|
// This tells PEI to spill the FP as if it is any other callee-save register
|
||||||
|
// to take advantage the eliminateFrameIndex machinery. This also ensures it
|
||||||
|
// is spilled in the order specified by getCalleeSavedRegs() to make it easier
|
||||||
|
// to combine multiple loads / stores.
|
||||||
|
bool CanEliminateFrame = true;
|
||||||
|
bool CS1Spilled = false;
|
||||||
|
bool LRSpilled = false;
|
||||||
|
unsigned NumGPRSpills = 0;
|
||||||
|
SmallVector<unsigned, 4> UnspilledCS1GPRs;
|
||||||
|
SmallVector<unsigned, 4> UnspilledCS2GPRs;
|
||||||
|
const ARMBaseRegisterInfo *RegInfo =
|
||||||
|
static_cast<const ARMBaseRegisterInfo*>(MF.getTarget().getRegisterInfo());
|
||||||
|
const ARMBaseInstrInfo &TII =
|
||||||
|
*static_cast<const ARMBaseInstrInfo*>(MF.getTarget().getInstrInfo());
|
||||||
|
ARMFunctionInfo *AFI = MF.getInfo<ARMFunctionInfo>();
|
||||||
|
MachineFrameInfo *MFI = MF.getFrameInfo();
|
||||||
|
unsigned FramePtr = RegInfo->getFrameRegister(MF);
|
||||||
|
|
||||||
|
// Spill R4 if Thumb2 function requires stack realignment - it will be used as
|
||||||
|
// scratch register. Also spill R4 if Thumb2 function has varsized objects,
|
||||||
|
// since it's always posible to restore sp from fp in a single instruction.
|
||||||
|
// FIXME: It will be better just to find spare register here.
|
||||||
|
if (AFI->isThumb2Function() &&
|
||||||
|
(MFI->hasVarSizedObjects() || RegInfo->needsStackRealignment(MF)))
|
||||||
|
MF.getRegInfo().setPhysRegUsed(ARM::R4);
|
||||||
|
|
||||||
|
// Spill LR if Thumb1 function uses variable length argument lists.
|
||||||
|
if (AFI->isThumb1OnlyFunction() && AFI->getVarArgsRegSaveSize() > 0)
|
||||||
|
MF.getRegInfo().setPhysRegUsed(ARM::LR);
|
||||||
|
|
||||||
|
// Spill the BasePtr if it's used.
|
||||||
|
if (RegInfo->hasBasePointer(MF))
|
||||||
|
MF.getRegInfo().setPhysRegUsed(RegInfo->getBaseRegister());
|
||||||
|
|
||||||
|
// Don't spill FP if the frame can be eliminated. This is determined
|
||||||
|
// by scanning the callee-save registers to see if any is used.
|
||||||
|
const unsigned *CSRegs = RegInfo->getCalleeSavedRegs();
|
||||||
|
for (unsigned i = 0; CSRegs[i]; ++i) {
|
||||||
|
unsigned Reg = CSRegs[i];
|
||||||
|
bool Spilled = false;
|
||||||
|
if (MF.getRegInfo().isPhysRegUsed(Reg)) {
|
||||||
|
AFI->setCSRegisterIsSpilled(Reg);
|
||||||
|
Spilled = true;
|
||||||
|
CanEliminateFrame = false;
|
||||||
|
} else {
|
||||||
|
// Check alias registers too.
|
||||||
|
for (const unsigned *Aliases =
|
||||||
|
RegInfo->getAliasSet(Reg); *Aliases; ++Aliases) {
|
||||||
|
if (MF.getRegInfo().isPhysRegUsed(*Aliases)) {
|
||||||
|
Spilled = true;
|
||||||
|
CanEliminateFrame = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!ARM::GPRRegisterClass->contains(Reg))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (Spilled) {
|
||||||
|
NumGPRSpills++;
|
||||||
|
|
||||||
|
if (!STI.isTargetDarwin()) {
|
||||||
|
if (Reg == ARM::LR)
|
||||||
|
LRSpilled = true;
|
||||||
|
CS1Spilled = true;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Keep track if LR and any of R4, R5, R6, and R7 is spilled.
|
||||||
|
switch (Reg) {
|
||||||
|
case ARM::LR:
|
||||||
|
LRSpilled = true;
|
||||||
|
// Fallthrough
|
||||||
|
case ARM::R4: case ARM::R5:
|
||||||
|
case ARM::R6: case ARM::R7:
|
||||||
|
CS1Spilled = true;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (!STI.isTargetDarwin()) {
|
||||||
|
UnspilledCS1GPRs.push_back(Reg);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (Reg) {
|
||||||
|
case ARM::R4: case ARM::R5:
|
||||||
|
case ARM::R6: case ARM::R7:
|
||||||
|
case ARM::LR:
|
||||||
|
UnspilledCS1GPRs.push_back(Reg);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
UnspilledCS2GPRs.push_back(Reg);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ForceLRSpill = false;
|
||||||
|
if (!LRSpilled && AFI->isThumb1OnlyFunction()) {
|
||||||
|
unsigned FnSize = GetFunctionSizeInBytes(MF, TII);
|
||||||
|
// Force LR to be spilled if the Thumb function size is > 2048. This enables
|
||||||
|
// use of BL to implement far jump. If it turns out that it's not needed
|
||||||
|
// then the branch fix up path will undo it.
|
||||||
|
if (FnSize >= (1 << 11)) {
|
||||||
|
CanEliminateFrame = false;
|
||||||
|
ForceLRSpill = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// If any of the stack slot references may be out of range of an immediate
|
||||||
|
// offset, make sure a register (or a spill slot) is available for the
|
||||||
|
// register scavenger. Note that if we're indexing off the frame pointer, the
|
||||||
|
// effective stack size is 4 bytes larger since the FP points to the stack
|
||||||
|
// slot of the previous FP. Also, if we have variable sized objects in the
|
||||||
|
// function, stack slot references will often be negative, and some of
|
||||||
|
// our instructions are positive-offset only, so conservatively consider
|
||||||
|
// that case to want a spill slot (or register) as well. Similarly, if
|
||||||
|
// the function adjusts the stack pointer during execution and the
|
||||||
|
// adjustments aren't already part of our stack size estimate, our offset
|
||||||
|
// calculations may be off, so be conservative.
|
||||||
|
// FIXME: We could add logic to be more precise about negative offsets
|
||||||
|
// and which instructions will need a scratch register for them. Is it
|
||||||
|
// worth the effort and added fragility?
|
||||||
|
bool BigStack =
|
||||||
|
(RS &&
|
||||||
|
(estimateStackSize(MF) + ((hasFP(MF) && AFI->hasStackFrame()) ? 4:0) >=
|
||||||
|
estimateRSStackSizeLimit(MF, this)))
|
||||||
|
|| MFI->hasVarSizedObjects()
|
||||||
|
|| (MFI->adjustsStack() && !canSimplifyCallFramePseudos(MF));
|
||||||
|
|
||||||
|
bool ExtraCSSpill = false;
|
||||||
|
if (BigStack || !CanEliminateFrame || RegInfo->cannotEliminateFrame(MF)) {
|
||||||
|
AFI->setHasStackFrame(true);
|
||||||
|
|
||||||
|
// If LR is not spilled, but at least one of R4, R5, R6, and R7 is spilled.
|
||||||
|
// Spill LR as well so we can fold BX_RET to the registers restore (LDM).
|
||||||
|
if (!LRSpilled && CS1Spilled) {
|
||||||
|
MF.getRegInfo().setPhysRegUsed(ARM::LR);
|
||||||
|
AFI->setCSRegisterIsSpilled(ARM::LR);
|
||||||
|
NumGPRSpills++;
|
||||||
|
UnspilledCS1GPRs.erase(std::find(UnspilledCS1GPRs.begin(),
|
||||||
|
UnspilledCS1GPRs.end(), (unsigned)ARM::LR));
|
||||||
|
ForceLRSpill = false;
|
||||||
|
ExtraCSSpill = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (hasFP(MF)) {
|
||||||
|
MF.getRegInfo().setPhysRegUsed(FramePtr);
|
||||||
|
NumGPRSpills++;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If stack and double are 8-byte aligned and we are spilling an odd number
|
||||||
|
// of GPRs, spill one extra callee save GPR so we won't have to pad between
|
||||||
|
// the integer and double callee save areas.
|
||||||
|
unsigned TargetAlign = MF.getTarget().getFrameInfo()->getStackAlignment();
|
||||||
|
if (TargetAlign == 8 && (NumGPRSpills & 1)) {
|
||||||
|
if (CS1Spilled && !UnspilledCS1GPRs.empty()) {
|
||||||
|
for (unsigned i = 0, e = UnspilledCS1GPRs.size(); i != e; ++i) {
|
||||||
|
unsigned Reg = UnspilledCS1GPRs[i];
|
||||||
|
// Don't spill high register if the function is thumb1
|
||||||
|
if (!AFI->isThumb1OnlyFunction() ||
|
||||||
|
isARMLowRegister(Reg) || Reg == ARM::LR) {
|
||||||
|
MF.getRegInfo().setPhysRegUsed(Reg);
|
||||||
|
AFI->setCSRegisterIsSpilled(Reg);
|
||||||
|
if (!RegInfo->isReservedReg(MF, Reg))
|
||||||
|
ExtraCSSpill = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (!UnspilledCS2GPRs.empty() && !AFI->isThumb1OnlyFunction()) {
|
||||||
|
unsigned Reg = UnspilledCS2GPRs.front();
|
||||||
|
MF.getRegInfo().setPhysRegUsed(Reg);
|
||||||
|
AFI->setCSRegisterIsSpilled(Reg);
|
||||||
|
if (!RegInfo->isReservedReg(MF, Reg))
|
||||||
|
ExtraCSSpill = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Estimate if we might need to scavenge a register at some point in order
|
||||||
|
// to materialize a stack offset. If so, either spill one additional
|
||||||
|
// callee-saved register or reserve a special spill slot to facilitate
|
||||||
|
// register scavenging. Thumb1 needs a spill slot for stack pointer
|
||||||
|
// adjustments also, even when the frame itself is small.
|
||||||
|
if (BigStack && !ExtraCSSpill) {
|
||||||
|
// If any non-reserved CS register isn't spilled, just spill one or two
|
||||||
|
// extra. That should take care of it!
|
||||||
|
unsigned NumExtras = TargetAlign / 4;
|
||||||
|
SmallVector<unsigned, 2> Extras;
|
||||||
|
while (NumExtras && !UnspilledCS1GPRs.empty()) {
|
||||||
|
unsigned Reg = UnspilledCS1GPRs.back();
|
||||||
|
UnspilledCS1GPRs.pop_back();
|
||||||
|
if (!RegInfo->isReservedReg(MF, Reg) &&
|
||||||
|
(!AFI->isThumb1OnlyFunction() || isARMLowRegister(Reg) ||
|
||||||
|
Reg == ARM::LR)) {
|
||||||
|
Extras.push_back(Reg);
|
||||||
|
NumExtras--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// For non-Thumb1 functions, also check for hi-reg CS registers
|
||||||
|
if (!AFI->isThumb1OnlyFunction()) {
|
||||||
|
while (NumExtras && !UnspilledCS2GPRs.empty()) {
|
||||||
|
unsigned Reg = UnspilledCS2GPRs.back();
|
||||||
|
UnspilledCS2GPRs.pop_back();
|
||||||
|
if (!RegInfo->isReservedReg(MF, Reg)) {
|
||||||
|
Extras.push_back(Reg);
|
||||||
|
NumExtras--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (Extras.size() && NumExtras == 0) {
|
||||||
|
for (unsigned i = 0, e = Extras.size(); i != e; ++i) {
|
||||||
|
MF.getRegInfo().setPhysRegUsed(Extras[i]);
|
||||||
|
AFI->setCSRegisterIsSpilled(Extras[i]);
|
||||||
|
}
|
||||||
|
} else if (!AFI->isThumb1OnlyFunction()) {
|
||||||
|
// note: Thumb1 functions spill to R12, not the stack. Reserve a slot
|
||||||
|
// closest to SP or frame pointer.
|
||||||
|
const TargetRegisterClass *RC = ARM::GPRRegisterClass;
|
||||||
|
RS->setScavengingFrameIndex(MFI->CreateStackObject(RC->getSize(),
|
||||||
|
RC->getAlignment(),
|
||||||
|
false));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ForceLRSpill) {
|
||||||
|
MF.getRegInfo().setPhysRegUsed(ARM::LR);
|
||||||
|
AFI->setCSRegisterIsSpilled(ARM::LR);
|
||||||
|
AFI->setLRIsSpilledForFarJump(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -54,6 +54,9 @@ public:
|
|||||||
unsigned &FrameReg, int SPAdj) const;
|
unsigned &FrameReg, int SPAdj) const;
|
||||||
int getFrameIndexOffset(const MachineFunction &MF, int FI) const;
|
int getFrameIndexOffset(const MachineFunction &MF, int FI) const;
|
||||||
|
|
||||||
|
void processFunctionBeforeCalleeSavedScan(MachineFunction &MF,
|
||||||
|
RegScavenger *RS) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void emitPopInst(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI,
|
void emitPopInst(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI,
|
||||||
const std::vector<CalleeSavedInfo> &CSI, unsigned Opc,
|
const std::vector<CalleeSavedInfo> &CSI, unsigned Opc,
|
||||||
|
@ -16,6 +16,7 @@
|
|||||||
#include "llvm/CodeGen/MachineFrameInfo.h"
|
#include "llvm/CodeGen/MachineFrameInfo.h"
|
||||||
#include "llvm/CodeGen/MachineFunction.h"
|
#include "llvm/CodeGen/MachineFunction.h"
|
||||||
#include "llvm/CodeGen/MachineInstrBuilder.h"
|
#include "llvm/CodeGen/MachineInstrBuilder.h"
|
||||||
|
#include "llvm/CodeGen/RegisterScavenging.h"
|
||||||
#include "llvm/Target/TargetOptions.h"
|
#include "llvm/Target/TargetOptions.h"
|
||||||
|
|
||||||
using namespace llvm;
|
using namespace llvm;
|
||||||
@ -105,3 +106,19 @@ void BlackfinFrameInfo::emitEpilogue(MachineFunction &MF,
|
|||||||
// emit an UNLINK instruction
|
// emit an UNLINK instruction
|
||||||
BuildMI(MBB, MBBI, dl, TII.get(BF::UNLINK));
|
BuildMI(MBB, MBBI, dl, TII.get(BF::UNLINK));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void BlackfinFrameInfo::
|
||||||
|
processFunctionBeforeCalleeSavedScan(MachineFunction &MF,
|
||||||
|
RegScavenger *RS) const {
|
||||||
|
MachineFrameInfo *MFI = MF.getFrameInfo();
|
||||||
|
const BlackfinRegisterInfo *RegInfo =
|
||||||
|
static_cast<const BlackfinRegisterInfo*>(MF.getTarget().getRegisterInfo());
|
||||||
|
const TargetRegisterClass *RC = BF::DPRegisterClass;
|
||||||
|
|
||||||
|
if (RegInfo->requiresRegisterScavenging(MF)) {
|
||||||
|
// Reserve a slot close to SP or frame pointer.
|
||||||
|
RS->setScavengingFrameIndex(MFI->CreateStackObject(RC->getSize(),
|
||||||
|
RC->getAlignment(),
|
||||||
|
false));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -36,6 +36,9 @@ public:
|
|||||||
void emitEpilogue(MachineFunction &MF, MachineBasicBlock &MBB) const;
|
void emitEpilogue(MachineFunction &MF, MachineBasicBlock &MBB) const;
|
||||||
|
|
||||||
bool hasFP(const MachineFunction &MF) const;
|
bool hasFP(const MachineFunction &MF) const;
|
||||||
|
|
||||||
|
void processFunctionBeforeCalleeSavedScan(MachineFunction &MF,
|
||||||
|
RegScavenger *RS) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // End llvm namespace
|
} // End llvm namespace
|
||||||
|
@ -325,19 +325,6 @@ BlackfinRegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void BlackfinRegisterInfo::
|
|
||||||
processFunctionBeforeCalleeSavedScan(MachineFunction &MF,
|
|
||||||
RegScavenger *RS) const {
|
|
||||||
MachineFrameInfo *MFI = MF.getFrameInfo();
|
|
||||||
const TargetRegisterClass *RC = BF::DPRegisterClass;
|
|
||||||
if (requiresRegisterScavenging(MF)) {
|
|
||||||
// Reserve a slot close to SP or frame pointer.
|
|
||||||
RS->setScavengingFrameIndex(MFI->CreateStackObject(RC->getSize(),
|
|
||||||
RC->getAlignment(),
|
|
||||||
false));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned BlackfinRegisterInfo::getRARegister() const {
|
unsigned BlackfinRegisterInfo::getRARegister() const {
|
||||||
return BF::RETS;
|
return BF::RETS;
|
||||||
}
|
}
|
||||||
|
@ -52,9 +52,6 @@ namespace llvm {
|
|||||||
void eliminateFrameIndex(MachineBasicBlock::iterator II,
|
void eliminateFrameIndex(MachineBasicBlock::iterator II,
|
||||||
int SPAdj, RegScavenger *RS = NULL) const;
|
int SPAdj, RegScavenger *RS = NULL) const;
|
||||||
|
|
||||||
void processFunctionBeforeCalleeSavedScan(MachineFunction &MF,
|
|
||||||
RegScavenger *RS) const;
|
|
||||||
|
|
||||||
unsigned getFrameRegister(const MachineFunction &MF) const;
|
unsigned getFrameRegister(const MachineFunction &MF) const;
|
||||||
unsigned getRARegister() const;
|
unsigned getRARegister() const;
|
||||||
|
|
||||||
|
@ -22,6 +22,7 @@
|
|||||||
#include "llvm/CodeGen/MachineInstrBuilder.h"
|
#include "llvm/CodeGen/MachineInstrBuilder.h"
|
||||||
#include "llvm/CodeGen/MachineModuleInfo.h"
|
#include "llvm/CodeGen/MachineModuleInfo.h"
|
||||||
#include "llvm/CodeGen/MachineRegisterInfo.h"
|
#include "llvm/CodeGen/MachineRegisterInfo.h"
|
||||||
|
#include "llvm/CodeGen/RegisterScavenging.h"
|
||||||
#include "llvm/Target/TargetData.h"
|
#include "llvm/Target/TargetData.h"
|
||||||
#include "llvm/Target/TargetOptions.h"
|
#include "llvm/Target/TargetOptions.h"
|
||||||
#include "llvm/Support/CommandLine.h"
|
#include "llvm/Support/CommandLine.h"
|
||||||
@ -255,3 +256,20 @@ void SPUFrameInfo::getInitialFrameState(std::vector<MachineMove> &Moves) const {
|
|||||||
MachineLocation Src(SPU::R1, 0);
|
MachineLocation Src(SPU::R1, 0);
|
||||||
Moves.push_back(MachineMove(0, Dst, Src));
|
Moves.push_back(MachineMove(0, Dst, Src));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SPUFrameInfo::processFunctionBeforeCalleeSavedScan(MachineFunction &MF,
|
||||||
|
RegScavenger *RS) const{
|
||||||
|
// Mark LR and SP unused, since the prolog spills them to stack and
|
||||||
|
// we don't want anyone else to spill them for us.
|
||||||
|
//
|
||||||
|
// Also, unless R2 is really used someday, don't spill it automatically.
|
||||||
|
MF.getRegInfo().setPhysRegUnused(SPU::R0);
|
||||||
|
MF.getRegInfo().setPhysRegUnused(SPU::R1);
|
||||||
|
MF.getRegInfo().setPhysRegUnused(SPU::R2);
|
||||||
|
|
||||||
|
MachineFrameInfo *MFI = MF.getFrameInfo();
|
||||||
|
const TargetRegisterClass *RC = &SPU::R32CRegClass;
|
||||||
|
RS->setScavengingFrameIndex(MFI->CreateStackObject(RC->getSize(),
|
||||||
|
RC->getAlignment(),
|
||||||
|
false));
|
||||||
|
}
|
||||||
|
@ -40,6 +40,9 @@ namespace llvm {
|
|||||||
//! Prediate: Target has dedicated frame pointer
|
//! Prediate: Target has dedicated frame pointer
|
||||||
bool hasFP(const MachineFunction &MF) const;
|
bool hasFP(const MachineFunction &MF) const;
|
||||||
|
|
||||||
|
void processFunctionBeforeCalleeSavedScan(MachineFunction &MF,
|
||||||
|
RegScavenger *RS = NULL) const;
|
||||||
|
|
||||||
//! Perform target-specific stack frame setup.
|
//! Perform target-specific stack frame setup.
|
||||||
void getInitialFrameState(std::vector<MachineMove> &Moves) const;
|
void getInitialFrameState(std::vector<MachineMove> &Moves) const;
|
||||||
|
|
||||||
|
@ -310,24 +310,6 @@ SPURegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II, int SPAdj,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void SPURegisterInfo::processFunctionBeforeCalleeSavedScan(MachineFunction &MF,
|
|
||||||
RegScavenger *RS)
|
|
||||||
const {
|
|
||||||
// Mark LR and SP unused, since the prolog spills them to stack and
|
|
||||||
// we don't want anyone else to spill them for us.
|
|
||||||
//
|
|
||||||
// Also, unless R2 is really used someday, don't spill it automatically.
|
|
||||||
MF.getRegInfo().setPhysRegUnused(SPU::R0);
|
|
||||||
MF.getRegInfo().setPhysRegUnused(SPU::R1);
|
|
||||||
MF.getRegInfo().setPhysRegUnused(SPU::R2);
|
|
||||||
|
|
||||||
MachineFrameInfo *MFI = MF.getFrameInfo();
|
|
||||||
const TargetRegisterClass *RC = &SPU::R32CRegClass;
|
|
||||||
RS->setScavengingFrameIndex(MFI->CreateStackObject(RC->getSize(),
|
|
||||||
RC->getAlignment(),
|
|
||||||
false));
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned
|
unsigned
|
||||||
SPURegisterInfo::getRARegister() const
|
SPURegisterInfo::getRARegister() const
|
||||||
{
|
{
|
||||||
|
@ -64,9 +64,6 @@ namespace llvm {
|
|||||||
void eliminateFrameIndex(MachineBasicBlock::iterator II, int SPAdj,
|
void eliminateFrameIndex(MachineBasicBlock::iterator II, int SPAdj,
|
||||||
RegScavenger *RS = NULL) const;
|
RegScavenger *RS = NULL) const;
|
||||||
|
|
||||||
void processFunctionBeforeCalleeSavedScan(MachineFunction &MF,
|
|
||||||
RegScavenger *RS = NULL) const;
|
|
||||||
|
|
||||||
//! Get return address register (LR, aka R0)
|
//! Get return address register (LR, aka R0)
|
||||||
unsigned getRARegister() const;
|
unsigned getRARegister() const;
|
||||||
//! Get the stack frame register (SP, aka R1)
|
//! Get the stack frame register (SP, aka R1)
|
||||||
|
@ -20,6 +20,7 @@
|
|||||||
#include "llvm/CodeGen/MachineInstrBuilder.h"
|
#include "llvm/CodeGen/MachineInstrBuilder.h"
|
||||||
#include "llvm/CodeGen/MachineModuleInfo.h"
|
#include "llvm/CodeGen/MachineModuleInfo.h"
|
||||||
#include "llvm/CodeGen/MachineRegisterInfo.h"
|
#include "llvm/CodeGen/MachineRegisterInfo.h"
|
||||||
|
#include "llvm/CodeGen/RegisterScavenging.h"
|
||||||
#include "llvm/Target/TargetOptions.h"
|
#include "llvm/Target/TargetOptions.h"
|
||||||
|
|
||||||
using namespace llvm;
|
using namespace llvm;
|
||||||
@ -696,3 +697,261 @@ void PPCFrameInfo::getInitialFrameState(std::vector<MachineMove> &Moves) const {
|
|||||||
MachineLocation Src(PPC::R1, 0);
|
MachineLocation Src(PPC::R1, 0);
|
||||||
Moves.push_back(MachineMove(0, Dst, Src));
|
Moves.push_back(MachineMove(0, Dst, Src));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool spillsCR(const MachineFunction &MF) {
|
||||||
|
const PPCFunctionInfo *FuncInfo = MF.getInfo<PPCFunctionInfo>();
|
||||||
|
return FuncInfo->isCRSpilled();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// MustSaveLR - Return true if this function requires that we save the LR
|
||||||
|
/// register onto the stack in the prolog and restore it in the epilog of the
|
||||||
|
/// function.
|
||||||
|
static bool MustSaveLR(const MachineFunction &MF, unsigned LR) {
|
||||||
|
const PPCFunctionInfo *MFI = MF.getInfo<PPCFunctionInfo>();
|
||||||
|
|
||||||
|
// We need a save/restore of LR if there is any def of LR (which is
|
||||||
|
// defined by calls, including the PIC setup sequence), or if there is
|
||||||
|
// some use of the LR stack slot (e.g. for builtin_return_address).
|
||||||
|
// (LR comes in 32 and 64 bit versions.)
|
||||||
|
MachineRegisterInfo::def_iterator RI = MF.getRegInfo().def_begin(LR);
|
||||||
|
return RI !=MF.getRegInfo().def_end() || MFI->isLRStoreRequired();
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
PPCFrameInfo::processFunctionBeforeCalleeSavedScan(MachineFunction &MF,
|
||||||
|
RegScavenger *RS) const {
|
||||||
|
const TargetRegisterInfo *RegInfo = MF.getTarget().getRegisterInfo();
|
||||||
|
|
||||||
|
// Save and clear the LR state.
|
||||||
|
PPCFunctionInfo *FI = MF.getInfo<PPCFunctionInfo>();
|
||||||
|
unsigned LR = RegInfo->getRARegister();
|
||||||
|
FI->setMustSaveLR(MustSaveLR(MF, LR));
|
||||||
|
MF.getRegInfo().setPhysRegUnused(LR);
|
||||||
|
|
||||||
|
// Save R31 if necessary
|
||||||
|
int FPSI = FI->getFramePointerSaveIndex();
|
||||||
|
bool isPPC64 = Subtarget.isPPC64();
|
||||||
|
bool isDarwinABI = Subtarget.isDarwinABI();
|
||||||
|
MachineFrameInfo *MFI = MF.getFrameInfo();
|
||||||
|
|
||||||
|
// If the frame pointer save index hasn't been defined yet.
|
||||||
|
if (!FPSI && hasFP(MF)) {
|
||||||
|
// Find out what the fix offset of the frame pointer save area.
|
||||||
|
int FPOffset = getFramePointerSaveOffset(isPPC64, isDarwinABI);
|
||||||
|
// Allocate the frame index for frame pointer save area.
|
||||||
|
FPSI = MF.getFrameInfo()->CreateFixedObject(isPPC64? 8 : 4, FPOffset, true);
|
||||||
|
// Save the result.
|
||||||
|
FI->setFramePointerSaveIndex(FPSI);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Reserve stack space to move the linkage area to in case of a tail call.
|
||||||
|
int TCSPDelta = 0;
|
||||||
|
if (GuaranteedTailCallOpt && (TCSPDelta = FI->getTailCallSPDelta()) < 0) {
|
||||||
|
MF.getFrameInfo()->CreateFixedObject(-1 * TCSPDelta, TCSPDelta, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Reserve a slot closest to SP or frame pointer if we have a dynalloc or
|
||||||
|
// a large stack, which will require scavenging a register to materialize a
|
||||||
|
// large offset.
|
||||||
|
// FIXME: this doesn't actually check stack size, so is a bit pessimistic
|
||||||
|
// FIXME: doesn't detect whether or not we need to spill vXX, which requires
|
||||||
|
// r0 for now.
|
||||||
|
|
||||||
|
if (RegInfo->requiresRegisterScavenging(MF)) // FIXME (64-bit): Enable.
|
||||||
|
if (hasFP(MF) || spillsCR(MF)) {
|
||||||
|
const TargetRegisterClass *GPRC = &PPC::GPRCRegClass;
|
||||||
|
const TargetRegisterClass *G8RC = &PPC::G8RCRegClass;
|
||||||
|
const TargetRegisterClass *RC = isPPC64 ? G8RC : GPRC;
|
||||||
|
RS->setScavengingFrameIndex(MFI->CreateStackObject(RC->getSize(),
|
||||||
|
RC->getAlignment(),
|
||||||
|
false));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void PPCFrameInfo::processFunctionBeforeFrameFinalized(MachineFunction &MF)
|
||||||
|
const {
|
||||||
|
// Early exit if not using the SVR4 ABI.
|
||||||
|
if (!Subtarget.isSVR4ABI())
|
||||||
|
return;
|
||||||
|
|
||||||
|
// Get callee saved register information.
|
||||||
|
MachineFrameInfo *FFI = MF.getFrameInfo();
|
||||||
|
const std::vector<CalleeSavedInfo> &CSI = FFI->getCalleeSavedInfo();
|
||||||
|
|
||||||
|
// Early exit if no callee saved registers are modified!
|
||||||
|
if (CSI.empty() && !hasFP(MF)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned MinGPR = PPC::R31;
|
||||||
|
unsigned MinG8R = PPC::X31;
|
||||||
|
unsigned MinFPR = PPC::F31;
|
||||||
|
unsigned MinVR = PPC::V31;
|
||||||
|
|
||||||
|
bool HasGPSaveArea = false;
|
||||||
|
bool HasG8SaveArea = false;
|
||||||
|
bool HasFPSaveArea = false;
|
||||||
|
bool HasCRSaveArea = false;
|
||||||
|
bool HasVRSAVESaveArea = false;
|
||||||
|
bool HasVRSaveArea = false;
|
||||||
|
|
||||||
|
SmallVector<CalleeSavedInfo, 18> GPRegs;
|
||||||
|
SmallVector<CalleeSavedInfo, 18> G8Regs;
|
||||||
|
SmallVector<CalleeSavedInfo, 18> FPRegs;
|
||||||
|
SmallVector<CalleeSavedInfo, 18> VRegs;
|
||||||
|
|
||||||
|
for (unsigned i = 0, e = CSI.size(); i != e; ++i) {
|
||||||
|
unsigned Reg = CSI[i].getReg();
|
||||||
|
if (PPC::GPRCRegisterClass->contains(Reg)) {
|
||||||
|
HasGPSaveArea = true;
|
||||||
|
|
||||||
|
GPRegs.push_back(CSI[i]);
|
||||||
|
|
||||||
|
if (Reg < MinGPR) {
|
||||||
|
MinGPR = Reg;
|
||||||
|
}
|
||||||
|
} else if (PPC::G8RCRegisterClass->contains(Reg)) {
|
||||||
|
HasG8SaveArea = true;
|
||||||
|
|
||||||
|
G8Regs.push_back(CSI[i]);
|
||||||
|
|
||||||
|
if (Reg < MinG8R) {
|
||||||
|
MinG8R = Reg;
|
||||||
|
}
|
||||||
|
} else if (PPC::F8RCRegisterClass->contains(Reg)) {
|
||||||
|
HasFPSaveArea = true;
|
||||||
|
|
||||||
|
FPRegs.push_back(CSI[i]);
|
||||||
|
|
||||||
|
if (Reg < MinFPR) {
|
||||||
|
MinFPR = Reg;
|
||||||
|
}
|
||||||
|
// FIXME SVR4: Disable CR save area for now.
|
||||||
|
} else if (PPC::CRBITRCRegisterClass->contains(Reg)
|
||||||
|
|| PPC::CRRCRegisterClass->contains(Reg)) {
|
||||||
|
// HasCRSaveArea = true;
|
||||||
|
} else if (PPC::VRSAVERCRegisterClass->contains(Reg)) {
|
||||||
|
HasVRSAVESaveArea = true;
|
||||||
|
} else if (PPC::VRRCRegisterClass->contains(Reg)) {
|
||||||
|
HasVRSaveArea = true;
|
||||||
|
|
||||||
|
VRegs.push_back(CSI[i]);
|
||||||
|
|
||||||
|
if (Reg < MinVR) {
|
||||||
|
MinVR = Reg;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
llvm_unreachable("Unknown RegisterClass!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
PPCFunctionInfo *PFI = MF.getInfo<PPCFunctionInfo>();
|
||||||
|
|
||||||
|
int64_t LowerBound = 0;
|
||||||
|
|
||||||
|
// Take into account stack space reserved for tail calls.
|
||||||
|
int TCSPDelta = 0;
|
||||||
|
if (GuaranteedTailCallOpt && (TCSPDelta = PFI->getTailCallSPDelta()) < 0) {
|
||||||
|
LowerBound = TCSPDelta;
|
||||||
|
}
|
||||||
|
|
||||||
|
// The Floating-point register save area is right below the back chain word
|
||||||
|
// of the previous stack frame.
|
||||||
|
if (HasFPSaveArea) {
|
||||||
|
for (unsigned i = 0, e = FPRegs.size(); i != e; ++i) {
|
||||||
|
int FI = FPRegs[i].getFrameIdx();
|
||||||
|
|
||||||
|
FFI->setObjectOffset(FI, LowerBound + FFI->getObjectOffset(FI));
|
||||||
|
}
|
||||||
|
|
||||||
|
LowerBound -= (31 - PPCRegisterInfo::getRegisterNumbering(MinFPR) + 1) * 8;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check whether the frame pointer register is allocated. If so, make sure it
|
||||||
|
// is spilled to the correct offset.
|
||||||
|
if (hasFP(MF)) {
|
||||||
|
HasGPSaveArea = true;
|
||||||
|
|
||||||
|
int FI = PFI->getFramePointerSaveIndex();
|
||||||
|
assert(FI && "No Frame Pointer Save Slot!");
|
||||||
|
|
||||||
|
FFI->setObjectOffset(FI, LowerBound + FFI->getObjectOffset(FI));
|
||||||
|
}
|
||||||
|
|
||||||
|
// General register save area starts right below the Floating-point
|
||||||
|
// register save area.
|
||||||
|
if (HasGPSaveArea || HasG8SaveArea) {
|
||||||
|
// Move general register save area spill slots down, taking into account
|
||||||
|
// the size of the Floating-point register save area.
|
||||||
|
for (unsigned i = 0, e = GPRegs.size(); i != e; ++i) {
|
||||||
|
int FI = GPRegs[i].getFrameIdx();
|
||||||
|
|
||||||
|
FFI->setObjectOffset(FI, LowerBound + FFI->getObjectOffset(FI));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Move general register save area spill slots down, taking into account
|
||||||
|
// the size of the Floating-point register save area.
|
||||||
|
for (unsigned i = 0, e = G8Regs.size(); i != e; ++i) {
|
||||||
|
int FI = G8Regs[i].getFrameIdx();
|
||||||
|
|
||||||
|
FFI->setObjectOffset(FI, LowerBound + FFI->getObjectOffset(FI));
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned MinReg =
|
||||||
|
std::min<unsigned>(PPCRegisterInfo::getRegisterNumbering(MinGPR),
|
||||||
|
PPCRegisterInfo::getRegisterNumbering(MinG8R));
|
||||||
|
|
||||||
|
if (Subtarget.isPPC64()) {
|
||||||
|
LowerBound -= (31 - MinReg + 1) * 8;
|
||||||
|
} else {
|
||||||
|
LowerBound -= (31 - MinReg + 1) * 4;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// The CR save area is below the general register save area.
|
||||||
|
if (HasCRSaveArea) {
|
||||||
|
// FIXME SVR4: Is it actually possible to have multiple elements in CSI
|
||||||
|
// which have the CR/CRBIT register class?
|
||||||
|
// Adjust the frame index of the CR spill slot.
|
||||||
|
for (unsigned i = 0, e = CSI.size(); i != e; ++i) {
|
||||||
|
unsigned Reg = CSI[i].getReg();
|
||||||
|
|
||||||
|
if (PPC::CRBITRCRegisterClass->contains(Reg) ||
|
||||||
|
PPC::CRRCRegisterClass->contains(Reg)) {
|
||||||
|
int FI = CSI[i].getFrameIdx();
|
||||||
|
|
||||||
|
FFI->setObjectOffset(FI, LowerBound + FFI->getObjectOffset(FI));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
LowerBound -= 4; // The CR save area is always 4 bytes long.
|
||||||
|
}
|
||||||
|
|
||||||
|
if (HasVRSAVESaveArea) {
|
||||||
|
// FIXME SVR4: Is it actually possible to have multiple elements in CSI
|
||||||
|
// which have the VRSAVE register class?
|
||||||
|
// Adjust the frame index of the VRSAVE spill slot.
|
||||||
|
for (unsigned i = 0, e = CSI.size(); i != e; ++i) {
|
||||||
|
unsigned Reg = CSI[i].getReg();
|
||||||
|
|
||||||
|
if (PPC::VRSAVERCRegisterClass->contains(Reg)) {
|
||||||
|
int FI = CSI[i].getFrameIdx();
|
||||||
|
|
||||||
|
FFI->setObjectOffset(FI, LowerBound + FFI->getObjectOffset(FI));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
LowerBound -= 4; // The VRSAVE save area is always 4 bytes long.
|
||||||
|
}
|
||||||
|
|
||||||
|
if (HasVRSaveArea) {
|
||||||
|
// Insert alignment padding, we need 16-byte alignment.
|
||||||
|
LowerBound = (LowerBound - 15) & ~(15);
|
||||||
|
|
||||||
|
for (unsigned i = 0, e = VRegs.size(); i != e; ++i) {
|
||||||
|
int FI = VRegs[i].getFrameIdx();
|
||||||
|
|
||||||
|
FFI->setObjectOffset(FI, LowerBound + FFI->getObjectOffset(FI));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -40,6 +40,10 @@ public:
|
|||||||
bool hasFP(const MachineFunction &MF) const;
|
bool hasFP(const MachineFunction &MF) const;
|
||||||
void getInitialFrameState(std::vector<MachineMove> &Moves) const;
|
void getInitialFrameState(std::vector<MachineMove> &Moves) const;
|
||||||
|
|
||||||
|
void processFunctionBeforeCalleeSavedScan(MachineFunction &MF,
|
||||||
|
RegScavenger *RS = NULL) const;
|
||||||
|
void processFunctionBeforeFrameFinalized(MachineFunction &MF) const;
|
||||||
|
|
||||||
/// targetHandlesStackFrameRounding - Returns true if the target is
|
/// targetHandlesStackFrameRounding - Returns true if the target is
|
||||||
/// responsible for rounding up the stack frame (probably at emitPrologue
|
/// responsible for rounding up the stack frame (probably at emitPrologue
|
||||||
/// time).
|
/// time).
|
||||||
|
@ -58,14 +58,11 @@ cl::opt<bool> EnablePPC64RS("enable-ppc64-regscavenger",
|
|||||||
|
|
||||||
using namespace llvm;
|
using namespace llvm;
|
||||||
|
|
||||||
#define EnableRegisterScavenging \
|
|
||||||
((EnablePPC32RS && !Subtarget.isPPC64()) || \
|
|
||||||
(EnablePPC64RS && Subtarget.isPPC64()))
|
|
||||||
|
|
||||||
// FIXME (64-bit): Should be inlined.
|
// FIXME (64-bit): Should be inlined.
|
||||||
bool
|
bool
|
||||||
PPCRegisterInfo::requiresRegisterScavenging(const MachineFunction &) const {
|
PPCRegisterInfo::requiresRegisterScavenging(const MachineFunction &) const {
|
||||||
return EnableRegisterScavenging;
|
return ((EnablePPC32RS && !Subtarget.isPPC64()) ||
|
||||||
|
(EnablePPC64RS && Subtarget.isPPC64()));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// getRegisterNumbering - Given the enum value for some register, e.g.
|
/// getRegisterNumbering - Given the enum value for some register, e.g.
|
||||||
@ -259,11 +256,6 @@ PPCRegisterInfo::getCalleeSavedRegs(const MachineFunction *MF) const {
|
|||||||
return Subtarget.isPPC64() ? SVR4_64_CalleeSavedRegs : SVR4_CalleeSavedRegs;
|
return Subtarget.isPPC64() ? SVR4_64_CalleeSavedRegs : SVR4_CalleeSavedRegs;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool spillsCR(const MachineFunction &MF) {
|
|
||||||
const PPCFunctionInfo *FuncInfo = MF.getInfo<PPCFunctionInfo>();
|
|
||||||
return FuncInfo->isCRSpilled();
|
|
||||||
}
|
|
||||||
|
|
||||||
BitVector PPCRegisterInfo::getReservedRegs(const MachineFunction &MF) const {
|
BitVector PPCRegisterInfo::getReservedRegs(const MachineFunction &MF) const {
|
||||||
BitVector Reserved(getNumRegs());
|
BitVector Reserved(getNumRegs());
|
||||||
const TargetFrameInfo *TFI = MF.getTarget().getFrameInfo();
|
const TargetFrameInfo *TFI = MF.getTarget().getFrameInfo();
|
||||||
@ -293,7 +285,7 @@ BitVector PPCRegisterInfo::getReservedRegs(const MachineFunction &MF) const {
|
|||||||
Reserved.set(PPC::R13);
|
Reserved.set(PPC::R13);
|
||||||
Reserved.set(PPC::R31);
|
Reserved.set(PPC::R31);
|
||||||
|
|
||||||
if (!EnableRegisterScavenging)
|
if (!requiresRegisterScavenging(MF))
|
||||||
Reserved.set(PPC::R0); // FIXME (64-bit): Remove
|
Reserved.set(PPC::R0); // FIXME (64-bit): Remove
|
||||||
|
|
||||||
Reserved.set(PPC::X0);
|
Reserved.set(PPC::X0);
|
||||||
@ -323,22 +315,6 @@ BitVector PPCRegisterInfo::getReservedRegs(const MachineFunction &MF) const {
|
|||||||
// Stack Frame Processing methods
|
// Stack Frame Processing methods
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
/// MustSaveLR - Return true if this function requires that we save the LR
|
|
||||||
/// register onto the stack in the prolog and restore it in the epilog of the
|
|
||||||
/// function.
|
|
||||||
static bool MustSaveLR(const MachineFunction &MF, unsigned LR) {
|
|
||||||
const PPCFunctionInfo *MFI = MF.getInfo<PPCFunctionInfo>();
|
|
||||||
|
|
||||||
// We need a save/restore of LR if there is any def of LR (which is
|
|
||||||
// defined by calls, including the PIC setup sequence), or if there is
|
|
||||||
// some use of the LR stack slot (e.g. for builtin_return_address).
|
|
||||||
// (LR comes in 32 and 64 bit versions.)
|
|
||||||
MachineRegisterInfo::def_iterator RI = MF.getRegInfo().def_begin(LR);
|
|
||||||
return RI !=MF.getRegInfo().def_end() || MFI->isLRStoreRequired();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void PPCRegisterInfo::
|
void PPCRegisterInfo::
|
||||||
eliminateCallFramePseudoInstr(MachineFunction &MF, MachineBasicBlock &MBB,
|
eliminateCallFramePseudoInstr(MachineFunction &MF, MachineBasicBlock &MBB,
|
||||||
MachineBasicBlock::iterator I) const {
|
MachineBasicBlock::iterator I) const {
|
||||||
@ -435,7 +411,7 @@ void PPCRegisterInfo::lowerDynamicAlloc(MachineBasicBlock::iterator II,
|
|||||||
|
|
||||||
// FIXME (64-bit): Use "findScratchRegister"
|
// FIXME (64-bit): Use "findScratchRegister"
|
||||||
unsigned Reg;
|
unsigned Reg;
|
||||||
if (EnableRegisterScavenging)
|
if (requiresRegisterScavenging(MF))
|
||||||
Reg = findScratchRegister(II, RS, RC, SPAdj);
|
Reg = findScratchRegister(II, RS, RC, SPAdj);
|
||||||
else
|
else
|
||||||
Reg = PPC::R0;
|
Reg = PPC::R0;
|
||||||
@ -445,7 +421,7 @@ void PPCRegisterInfo::lowerDynamicAlloc(MachineBasicBlock::iterator II,
|
|||||||
.addReg(PPC::R31)
|
.addReg(PPC::R31)
|
||||||
.addImm(FrameSize);
|
.addImm(FrameSize);
|
||||||
} else if (LP64) {
|
} else if (LP64) {
|
||||||
if (EnableRegisterScavenging) // FIXME (64-bit): Use "true" part.
|
if (requiresRegisterScavenging(MF)) // FIXME (64-bit): Use "true" part.
|
||||||
BuildMI(MBB, II, dl, TII.get(PPC::LD), Reg)
|
BuildMI(MBB, II, dl, TII.get(PPC::LD), Reg)
|
||||||
.addImm(0)
|
.addImm(0)
|
||||||
.addReg(PPC::X1);
|
.addReg(PPC::X1);
|
||||||
@ -462,7 +438,7 @@ void PPCRegisterInfo::lowerDynamicAlloc(MachineBasicBlock::iterator II,
|
|||||||
// Grow the stack and update the stack pointer link, then determine the
|
// Grow the stack and update the stack pointer link, then determine the
|
||||||
// address of new allocated space.
|
// address of new allocated space.
|
||||||
if (LP64) {
|
if (LP64) {
|
||||||
if (EnableRegisterScavenging) // FIXME (64-bit): Use "true" part.
|
if (requiresRegisterScavenging(MF)) // FIXME (64-bit): Use "true" part.
|
||||||
BuildMI(MBB, II, dl, TII.get(PPC::STDUX))
|
BuildMI(MBB, II, dl, TII.get(PPC::STDUX))
|
||||||
.addReg(Reg, RegState::Kill)
|
.addReg(Reg, RegState::Kill)
|
||||||
.addReg(PPC::X1)
|
.addReg(PPC::X1)
|
||||||
@ -597,7 +573,7 @@ PPCRegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Special case for pseudo-op SPILL_CR.
|
// Special case for pseudo-op SPILL_CR.
|
||||||
if (EnableRegisterScavenging) // FIXME (64-bit): Enable by default.
|
if (requiresRegisterScavenging(MF)) // FIXME (64-bit): Enable by default.
|
||||||
if (OpC == PPC::SPILL_CR) {
|
if (OpC == PPC::SPILL_CR) {
|
||||||
lowerCRSpilling(II, FrameIndex, SPAdj, RS);
|
lowerCRSpilling(II, FrameIndex, SPAdj, RS);
|
||||||
return;
|
return;
|
||||||
@ -655,7 +631,7 @@ PPCRegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II,
|
|||||||
|
|
||||||
// FIXME (64-bit): Use "findScratchRegister".
|
// FIXME (64-bit): Use "findScratchRegister".
|
||||||
unsigned SReg;
|
unsigned SReg;
|
||||||
if (EnableRegisterScavenging)
|
if (requiresRegisterScavenging(MF))
|
||||||
SReg = findScratchRegister(II, RS, &PPC::GPRCRegClass, SPAdj);
|
SReg = findScratchRegister(II, RS, &PPC::GPRCRegClass, SPAdj);
|
||||||
else
|
else
|
||||||
SReg = PPC::R0;
|
SReg = PPC::R0;
|
||||||
@ -688,248 +664,6 @@ PPCRegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II,
|
|||||||
MI.getOperand(OperandBase + 1).ChangeToRegister(SReg, false);
|
MI.getOperand(OperandBase + 1).ChangeToRegister(SReg, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
|
||||||
PPCRegisterInfo::processFunctionBeforeCalleeSavedScan(MachineFunction &MF,
|
|
||||||
RegScavenger *RS) const {
|
|
||||||
const TargetFrameInfo *TFI = MF.getTarget().getFrameInfo();
|
|
||||||
|
|
||||||
// Save and clear the LR state.
|
|
||||||
PPCFunctionInfo *FI = MF.getInfo<PPCFunctionInfo>();
|
|
||||||
unsigned LR = getRARegister();
|
|
||||||
FI->setMustSaveLR(MustSaveLR(MF, LR));
|
|
||||||
MF.getRegInfo().setPhysRegUnused(LR);
|
|
||||||
|
|
||||||
// Save R31 if necessary
|
|
||||||
int FPSI = FI->getFramePointerSaveIndex();
|
|
||||||
bool isPPC64 = Subtarget.isPPC64();
|
|
||||||
bool isDarwinABI = Subtarget.isDarwinABI();
|
|
||||||
MachineFrameInfo *MFI = MF.getFrameInfo();
|
|
||||||
|
|
||||||
// If the frame pointer save index hasn't been defined yet.
|
|
||||||
if (!FPSI && TFI->hasFP(MF)) {
|
|
||||||
// Find out what the fix offset of the frame pointer save area.
|
|
||||||
int FPOffset = PPCFrameInfo::getFramePointerSaveOffset(isPPC64,
|
|
||||||
isDarwinABI);
|
|
||||||
// Allocate the frame index for frame pointer save area.
|
|
||||||
FPSI = MF.getFrameInfo()->CreateFixedObject(isPPC64? 8 : 4, FPOffset, true);
|
|
||||||
// Save the result.
|
|
||||||
FI->setFramePointerSaveIndex(FPSI);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Reserve stack space to move the linkage area to in case of a tail call.
|
|
||||||
int TCSPDelta = 0;
|
|
||||||
if (GuaranteedTailCallOpt && (TCSPDelta = FI->getTailCallSPDelta()) < 0) {
|
|
||||||
MF.getFrameInfo()->CreateFixedObject(-1 * TCSPDelta, TCSPDelta, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Reserve a slot closest to SP or frame pointer if we have a dynalloc or
|
|
||||||
// a large stack, which will require scavenging a register to materialize a
|
|
||||||
// large offset.
|
|
||||||
// FIXME: this doesn't actually check stack size, so is a bit pessimistic
|
|
||||||
// FIXME: doesn't detect whether or not we need to spill vXX, which requires
|
|
||||||
// r0 for now.
|
|
||||||
|
|
||||||
if (EnableRegisterScavenging) // FIXME (64-bit): Enable.
|
|
||||||
if (TFI->hasFP(MF) || spillsCR(MF)) {
|
|
||||||
const TargetRegisterClass *GPRC = &PPC::GPRCRegClass;
|
|
||||||
const TargetRegisterClass *G8RC = &PPC::G8RCRegClass;
|
|
||||||
const TargetRegisterClass *RC = isPPC64 ? G8RC : GPRC;
|
|
||||||
RS->setScavengingFrameIndex(MFI->CreateStackObject(RC->getSize(),
|
|
||||||
RC->getAlignment(),
|
|
||||||
false));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
PPCRegisterInfo::processFunctionBeforeFrameFinalized(MachineFunction &MF)
|
|
||||||
const {
|
|
||||||
// Early exit if not using the SVR4 ABI.
|
|
||||||
if (!Subtarget.isSVR4ABI()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get callee saved register information.
|
|
||||||
MachineFrameInfo *FFI = MF.getFrameInfo();
|
|
||||||
const std::vector<CalleeSavedInfo> &CSI = FFI->getCalleeSavedInfo();
|
|
||||||
const TargetFrameInfo *TFI = MF.getTarget().getFrameInfo();
|
|
||||||
|
|
||||||
// Early exit if no callee saved registers are modified!
|
|
||||||
if (CSI.empty() && !TFI->hasFP(MF)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned MinGPR = PPC::R31;
|
|
||||||
unsigned MinG8R = PPC::X31;
|
|
||||||
unsigned MinFPR = PPC::F31;
|
|
||||||
unsigned MinVR = PPC::V31;
|
|
||||||
|
|
||||||
bool HasGPSaveArea = false;
|
|
||||||
bool HasG8SaveArea = false;
|
|
||||||
bool HasFPSaveArea = false;
|
|
||||||
bool HasCRSaveArea = false;
|
|
||||||
bool HasVRSAVESaveArea = false;
|
|
||||||
bool HasVRSaveArea = false;
|
|
||||||
|
|
||||||
SmallVector<CalleeSavedInfo, 18> GPRegs;
|
|
||||||
SmallVector<CalleeSavedInfo, 18> G8Regs;
|
|
||||||
SmallVector<CalleeSavedInfo, 18> FPRegs;
|
|
||||||
SmallVector<CalleeSavedInfo, 18> VRegs;
|
|
||||||
|
|
||||||
for (unsigned i = 0, e = CSI.size(); i != e; ++i) {
|
|
||||||
unsigned Reg = CSI[i].getReg();
|
|
||||||
if (PPC::GPRCRegisterClass->contains(Reg)) {
|
|
||||||
HasGPSaveArea = true;
|
|
||||||
|
|
||||||
GPRegs.push_back(CSI[i]);
|
|
||||||
|
|
||||||
if (Reg < MinGPR) {
|
|
||||||
MinGPR = Reg;
|
|
||||||
}
|
|
||||||
} else if (PPC::G8RCRegisterClass->contains(Reg)) {
|
|
||||||
HasG8SaveArea = true;
|
|
||||||
|
|
||||||
G8Regs.push_back(CSI[i]);
|
|
||||||
|
|
||||||
if (Reg < MinG8R) {
|
|
||||||
MinG8R = Reg;
|
|
||||||
}
|
|
||||||
} else if (PPC::F8RCRegisterClass->contains(Reg)) {
|
|
||||||
HasFPSaveArea = true;
|
|
||||||
|
|
||||||
FPRegs.push_back(CSI[i]);
|
|
||||||
|
|
||||||
if (Reg < MinFPR) {
|
|
||||||
MinFPR = Reg;
|
|
||||||
}
|
|
||||||
// FIXME SVR4: Disable CR save area for now.
|
|
||||||
} else if (PPC::CRBITRCRegisterClass->contains(Reg)
|
|
||||||
|| PPC::CRRCRegisterClass->contains(Reg)) {
|
|
||||||
// HasCRSaveArea = true;
|
|
||||||
} else if (PPC::VRSAVERCRegisterClass->contains(Reg)) {
|
|
||||||
HasVRSAVESaveArea = true;
|
|
||||||
} else if (PPC::VRRCRegisterClass->contains(Reg)) {
|
|
||||||
HasVRSaveArea = true;
|
|
||||||
|
|
||||||
VRegs.push_back(CSI[i]);
|
|
||||||
|
|
||||||
if (Reg < MinVR) {
|
|
||||||
MinVR = Reg;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
llvm_unreachable("Unknown RegisterClass!");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
PPCFunctionInfo *PFI = MF.getInfo<PPCFunctionInfo>();
|
|
||||||
|
|
||||||
int64_t LowerBound = 0;
|
|
||||||
|
|
||||||
// Take into account stack space reserved for tail calls.
|
|
||||||
int TCSPDelta = 0;
|
|
||||||
if (GuaranteedTailCallOpt && (TCSPDelta = PFI->getTailCallSPDelta()) < 0) {
|
|
||||||
LowerBound = TCSPDelta;
|
|
||||||
}
|
|
||||||
|
|
||||||
// The Floating-point register save area is right below the back chain word
|
|
||||||
// of the previous stack frame.
|
|
||||||
if (HasFPSaveArea) {
|
|
||||||
for (unsigned i = 0, e = FPRegs.size(); i != e; ++i) {
|
|
||||||
int FI = FPRegs[i].getFrameIdx();
|
|
||||||
|
|
||||||
FFI->setObjectOffset(FI, LowerBound + FFI->getObjectOffset(FI));
|
|
||||||
}
|
|
||||||
|
|
||||||
LowerBound -= (31 - getRegisterNumbering(MinFPR) + 1) * 8;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check whether the frame pointer register is allocated. If so, make sure it
|
|
||||||
// is spilled to the correct offset.
|
|
||||||
if (TFI->hasFP(MF)) {
|
|
||||||
HasGPSaveArea = true;
|
|
||||||
|
|
||||||
int FI = PFI->getFramePointerSaveIndex();
|
|
||||||
assert(FI && "No Frame Pointer Save Slot!");
|
|
||||||
|
|
||||||
FFI->setObjectOffset(FI, LowerBound + FFI->getObjectOffset(FI));
|
|
||||||
}
|
|
||||||
|
|
||||||
// General register save area starts right below the Floating-point
|
|
||||||
// register save area.
|
|
||||||
if (HasGPSaveArea || HasG8SaveArea) {
|
|
||||||
// Move general register save area spill slots down, taking into account
|
|
||||||
// the size of the Floating-point register save area.
|
|
||||||
for (unsigned i = 0, e = GPRegs.size(); i != e; ++i) {
|
|
||||||
int FI = GPRegs[i].getFrameIdx();
|
|
||||||
|
|
||||||
FFI->setObjectOffset(FI, LowerBound + FFI->getObjectOffset(FI));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Move general register save area spill slots down, taking into account
|
|
||||||
// the size of the Floating-point register save area.
|
|
||||||
for (unsigned i = 0, e = G8Regs.size(); i != e; ++i) {
|
|
||||||
int FI = G8Regs[i].getFrameIdx();
|
|
||||||
|
|
||||||
FFI->setObjectOffset(FI, LowerBound + FFI->getObjectOffset(FI));
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned MinReg = std::min<unsigned>(getRegisterNumbering(MinGPR),
|
|
||||||
getRegisterNumbering(MinG8R));
|
|
||||||
|
|
||||||
if (Subtarget.isPPC64()) {
|
|
||||||
LowerBound -= (31 - MinReg + 1) * 8;
|
|
||||||
} else {
|
|
||||||
LowerBound -= (31 - MinReg + 1) * 4;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// The CR save area is below the general register save area.
|
|
||||||
if (HasCRSaveArea) {
|
|
||||||
// FIXME SVR4: Is it actually possible to have multiple elements in CSI
|
|
||||||
// which have the CR/CRBIT register class?
|
|
||||||
// Adjust the frame index of the CR spill slot.
|
|
||||||
for (unsigned i = 0, e = CSI.size(); i != e; ++i) {
|
|
||||||
unsigned Reg = CSI[i].getReg();
|
|
||||||
|
|
||||||
if (PPC::CRBITRCRegisterClass->contains(Reg) ||
|
|
||||||
PPC::CRRCRegisterClass->contains(Reg)) {
|
|
||||||
int FI = CSI[i].getFrameIdx();
|
|
||||||
|
|
||||||
FFI->setObjectOffset(FI, LowerBound + FFI->getObjectOffset(FI));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
LowerBound -= 4; // The CR save area is always 4 bytes long.
|
|
||||||
}
|
|
||||||
|
|
||||||
if (HasVRSAVESaveArea) {
|
|
||||||
// FIXME SVR4: Is it actually possible to have multiple elements in CSI
|
|
||||||
// which have the VRSAVE register class?
|
|
||||||
// Adjust the frame index of the VRSAVE spill slot.
|
|
||||||
for (unsigned i = 0, e = CSI.size(); i != e; ++i) {
|
|
||||||
unsigned Reg = CSI[i].getReg();
|
|
||||||
|
|
||||||
if (PPC::VRSAVERCRegisterClass->contains(Reg)) {
|
|
||||||
int FI = CSI[i].getFrameIdx();
|
|
||||||
|
|
||||||
FFI->setObjectOffset(FI, LowerBound + FFI->getObjectOffset(FI));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
LowerBound -= 4; // The VRSAVE save area is always 4 bytes long.
|
|
||||||
}
|
|
||||||
|
|
||||||
if (HasVRSaveArea) {
|
|
||||||
// Insert alignment padding, we need 16-byte alignment.
|
|
||||||
LowerBound = (LowerBound - 15) & ~(15);
|
|
||||||
|
|
||||||
for (unsigned i = 0, e = VRegs.size(); i != e; ++i) {
|
|
||||||
int FI = VRegs[i].getFrameIdx();
|
|
||||||
|
|
||||||
FFI->setObjectOffset(FI, LowerBound + FFI->getObjectOffset(FI));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned PPCRegisterInfo::getRARegister() const {
|
unsigned PPCRegisterInfo::getRARegister() const {
|
||||||
return !Subtarget.isPPC64() ? PPC::LR : PPC::LR8;
|
return !Subtarget.isPPC64() ? PPC::LR : PPC::LR8;
|
||||||
}
|
}
|
||||||
|
@ -59,10 +59,6 @@ public:
|
|||||||
void eliminateFrameIndex(MachineBasicBlock::iterator II,
|
void eliminateFrameIndex(MachineBasicBlock::iterator II,
|
||||||
int SPAdj, RegScavenger *RS = NULL) const;
|
int SPAdj, RegScavenger *RS = NULL) const;
|
||||||
|
|
||||||
void processFunctionBeforeCalleeSavedScan(MachineFunction &MF,
|
|
||||||
RegScavenger *RS = NULL) const;
|
|
||||||
void processFunctionBeforeFrameFinalized(MachineFunction &MF) const;
|
|
||||||
|
|
||||||
// Debug information queries.
|
// Debug information queries.
|
||||||
unsigned getRARegister() const;
|
unsigned getRARegister() const;
|
||||||
unsigned getFrameRegister(const MachineFunction &MF) const;
|
unsigned getFrameRegister(const MachineFunction &MF) const;
|
||||||
|
@ -351,3 +351,38 @@ SystemZFrameInfo::restoreCalleeSavedRegisters(MachineBasicBlock &MBB,
|
|||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
SystemZFrameInfo::processFunctionBeforeCalleeSavedScan(MachineFunction &MF,
|
||||||
|
RegScavenger *RS) const {
|
||||||
|
// Determine whether R15/R14 will ever be clobbered inside the function. And
|
||||||
|
// if yes - mark it as 'callee' saved.
|
||||||
|
MachineFrameInfo *FFI = MF.getFrameInfo();
|
||||||
|
MachineRegisterInfo &MRI = MF.getRegInfo();
|
||||||
|
|
||||||
|
// Check whether high FPRs are ever used, if yes - we need to save R15 as
|
||||||
|
// well.
|
||||||
|
static const unsigned HighFPRs[] = {
|
||||||
|
SystemZ::F8L, SystemZ::F9L, SystemZ::F10L, SystemZ::F11L,
|
||||||
|
SystemZ::F12L, SystemZ::F13L, SystemZ::F14L, SystemZ::F15L,
|
||||||
|
SystemZ::F8S, SystemZ::F9S, SystemZ::F10S, SystemZ::F11S,
|
||||||
|
SystemZ::F12S, SystemZ::F13S, SystemZ::F14S, SystemZ::F15S,
|
||||||
|
};
|
||||||
|
|
||||||
|
bool HighFPRsUsed = false;
|
||||||
|
for (unsigned i = 0, e = array_lengthof(HighFPRs); i != e; ++i)
|
||||||
|
HighFPRsUsed |= MRI.isPhysRegUsed(HighFPRs[i]);
|
||||||
|
|
||||||
|
if (FFI->hasCalls())
|
||||||
|
/* FIXME: function is varargs */
|
||||||
|
/* FIXME: function grabs RA */
|
||||||
|
/* FIXME: function calls eh_return */
|
||||||
|
MRI.setPhysRegUsed(SystemZ::R14D);
|
||||||
|
|
||||||
|
if (HighFPRsUsed ||
|
||||||
|
FFI->hasCalls() ||
|
||||||
|
FFI->getObjectIndexEnd() != 0 || // Contains automatic variables
|
||||||
|
FFI->hasVarSizedObjects() // Function calls dynamic alloca's
|
||||||
|
/* FIXME: function is varargs */)
|
||||||
|
MRI.setPhysRegUsed(SystemZ::R15D);
|
||||||
|
}
|
||||||
|
@ -44,6 +44,9 @@ public:
|
|||||||
const std::vector<CalleeSavedInfo> &CSI,
|
const std::vector<CalleeSavedInfo> &CSI,
|
||||||
const TargetRegisterInfo *TRI) const;
|
const TargetRegisterInfo *TRI) const;
|
||||||
|
|
||||||
|
void processFunctionBeforeCalleeSavedScan(MachineFunction &MF,
|
||||||
|
RegScavenger *RS) const;
|
||||||
|
|
||||||
bool hasReservedCallFrame(const MachineFunction &MF) const { return true; }
|
bool hasReservedCallFrame(const MachineFunction &MF) const { return true; }
|
||||||
bool hasFP(const MachineFunction &MF) const;
|
bool hasFP(const MachineFunction &MF) const;
|
||||||
int getFrameIndexOffset(const MachineFunction &MF, int FI) const;
|
int getFrameIndexOffset(const MachineFunction &MF, int FI) const;
|
||||||
|
@ -99,41 +99,6 @@ SystemZRegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II,
|
|||||||
MI.getOperand(i+1).ChangeToImmediate(Offset);
|
MI.getOperand(i+1).ChangeToImmediate(Offset);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
|
||||||
SystemZRegisterInfo::processFunctionBeforeCalleeSavedScan(MachineFunction &MF,
|
|
||||||
RegScavenger *RS) const {
|
|
||||||
// Determine whether R15/R14 will ever be clobbered inside the function. And
|
|
||||||
// if yes - mark it as 'callee' saved.
|
|
||||||
MachineFrameInfo *FFI = MF.getFrameInfo();
|
|
||||||
MachineRegisterInfo &MRI = MF.getRegInfo();
|
|
||||||
|
|
||||||
// Check whether high FPRs are ever used, if yes - we need to save R15 as
|
|
||||||
// well.
|
|
||||||
static const unsigned HighFPRs[] = {
|
|
||||||
SystemZ::F8L, SystemZ::F9L, SystemZ::F10L, SystemZ::F11L,
|
|
||||||
SystemZ::F12L, SystemZ::F13L, SystemZ::F14L, SystemZ::F15L,
|
|
||||||
SystemZ::F8S, SystemZ::F9S, SystemZ::F10S, SystemZ::F11S,
|
|
||||||
SystemZ::F12S, SystemZ::F13S, SystemZ::F14S, SystemZ::F15S,
|
|
||||||
};
|
|
||||||
|
|
||||||
bool HighFPRsUsed = false;
|
|
||||||
for (unsigned i = 0, e = array_lengthof(HighFPRs); i != e; ++i)
|
|
||||||
HighFPRsUsed |= MRI.isPhysRegUsed(HighFPRs[i]);
|
|
||||||
|
|
||||||
if (FFI->hasCalls())
|
|
||||||
/* FIXME: function is varargs */
|
|
||||||
/* FIXME: function grabs RA */
|
|
||||||
/* FIXME: function calls eh_return */
|
|
||||||
MRI.setPhysRegUsed(SystemZ::R14D);
|
|
||||||
|
|
||||||
if (HighFPRsUsed ||
|
|
||||||
FFI->hasCalls() ||
|
|
||||||
FFI->getObjectIndexEnd() != 0 || // Contains automatic variables
|
|
||||||
FFI->hasVarSizedObjects() // Function calls dynamic alloca's
|
|
||||||
/* FIXME: function is varargs */)
|
|
||||||
MRI.setPhysRegUsed(SystemZ::R15D);
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned SystemZRegisterInfo::getRARegister() const {
|
unsigned SystemZRegisterInfo::getRARegister() const {
|
||||||
assert(0 && "What is the return address register");
|
assert(0 && "What is the return address register");
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -41,10 +41,6 @@ struct SystemZRegisterInfo : public SystemZGenRegisterInfo {
|
|||||||
void eliminateFrameIndex(MachineBasicBlock::iterator II,
|
void eliminateFrameIndex(MachineBasicBlock::iterator II,
|
||||||
int SPAdj, RegScavenger *RS = NULL) const;
|
int SPAdj, RegScavenger *RS = NULL) const;
|
||||||
|
|
||||||
|
|
||||||
void processFunctionBeforeCalleeSavedScan(MachineFunction &MF,
|
|
||||||
RegScavenger *RS) const;
|
|
||||||
|
|
||||||
// Debug information queries.
|
// Debug information queries.
|
||||||
unsigned getRARegister() const;
|
unsigned getRARegister() const;
|
||||||
unsigned getFrameRegister(const MachineFunction &MF) const;
|
unsigned getFrameRegister(const MachineFunction &MF) const;
|
||||||
|
@ -870,3 +870,44 @@ bool X86FrameInfo::restoreCalleeSavedRegisters(MachineBasicBlock &MBB,
|
|||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
X86FrameInfo::processFunctionBeforeCalleeSavedScan(MachineFunction &MF,
|
||||||
|
RegScavenger *RS) const {
|
||||||
|
MachineFrameInfo *MFI = MF.getFrameInfo();
|
||||||
|
const X86RegisterInfo *RegInfo = TM.getRegisterInfo();
|
||||||
|
unsigned SlotSize = RegInfo->getSlotSize();
|
||||||
|
|
||||||
|
X86MachineFunctionInfo *X86FI = MF.getInfo<X86MachineFunctionInfo>();
|
||||||
|
int32_t TailCallReturnAddrDelta = X86FI->getTCReturnAddrDelta();
|
||||||
|
|
||||||
|
if (TailCallReturnAddrDelta < 0) {
|
||||||
|
// create RETURNADDR area
|
||||||
|
// arg
|
||||||
|
// arg
|
||||||
|
// RETADDR
|
||||||
|
// { ...
|
||||||
|
// RETADDR area
|
||||||
|
// ...
|
||||||
|
// }
|
||||||
|
// [EBP]
|
||||||
|
MFI->CreateFixedObject(-TailCallReturnAddrDelta,
|
||||||
|
(-1U*SlotSize)+TailCallReturnAddrDelta, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (hasFP(MF)) {
|
||||||
|
assert((TailCallReturnAddrDelta <= 0) &&
|
||||||
|
"The Delta should always be zero or negative");
|
||||||
|
const TargetFrameInfo &TFI = *MF.getTarget().getFrameInfo();
|
||||||
|
|
||||||
|
// Create a frame entry for the EBP register that must be saved.
|
||||||
|
int FrameIdx = MFI->CreateFixedObject(SlotSize,
|
||||||
|
-(int)SlotSize +
|
||||||
|
TFI.getOffsetOfLocalArea() +
|
||||||
|
TailCallReturnAddrDelta,
|
||||||
|
true);
|
||||||
|
assert(FrameIdx == MFI->getObjectIndexBegin() &&
|
||||||
|
"Slot for EBP register must be last in order to be found!");
|
||||||
|
FrameIdx = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -40,15 +40,18 @@ public:
|
|||||||
void emitPrologue(MachineFunction &MF) const;
|
void emitPrologue(MachineFunction &MF) const;
|
||||||
void emitEpilogue(MachineFunction &MF, MachineBasicBlock &MBB) const;
|
void emitEpilogue(MachineFunction &MF, MachineBasicBlock &MBB) const;
|
||||||
|
|
||||||
|
void processFunctionBeforeCalleeSavedScan(MachineFunction &MF,
|
||||||
|
RegScavenger *RS = NULL) const;
|
||||||
|
|
||||||
bool spillCalleeSavedRegisters(MachineBasicBlock &MBB,
|
bool spillCalleeSavedRegisters(MachineBasicBlock &MBB,
|
||||||
MachineBasicBlock::iterator MI,
|
MachineBasicBlock::iterator MI,
|
||||||
const std::vector<CalleeSavedInfo> &CSI,
|
const std::vector<CalleeSavedInfo> &CSI,
|
||||||
const TargetRegisterInfo *TRI) const;
|
const TargetRegisterInfo *TRI) const;
|
||||||
|
|
||||||
bool restoreCalleeSavedRegisters(MachineBasicBlock &MBB,
|
bool restoreCalleeSavedRegisters(MachineBasicBlock &MBB,
|
||||||
MachineBasicBlock::iterator MI,
|
MachineBasicBlock::iterator MI,
|
||||||
const std::vector<CalleeSavedInfo> &CSI,
|
const std::vector<CalleeSavedInfo> &CSI,
|
||||||
const TargetRegisterInfo *TRI) const;
|
const TargetRegisterInfo *TRI) const;
|
||||||
|
|
||||||
bool hasFP(const MachineFunction &MF) const;
|
bool hasFP(const MachineFunction &MF) const;
|
||||||
bool hasReservedCallFrame(const MachineFunction &MF) const;
|
bool hasReservedCallFrame(const MachineFunction &MF) const;
|
||||||
|
@ -609,46 +609,6 @@ X86RegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
|
||||||
X86RegisterInfo::processFunctionBeforeCalleeSavedScan(MachineFunction &MF,
|
|
||||||
RegScavenger *RS) const {
|
|
||||||
MachineFrameInfo *MFI = MF.getFrameInfo();
|
|
||||||
const TargetFrameInfo *TFI = MF.getTarget().getFrameInfo();
|
|
||||||
|
|
||||||
X86MachineFunctionInfo *X86FI = MF.getInfo<X86MachineFunctionInfo>();
|
|
||||||
int32_t TailCallReturnAddrDelta = X86FI->getTCReturnAddrDelta();
|
|
||||||
|
|
||||||
if (TailCallReturnAddrDelta < 0) {
|
|
||||||
// create RETURNADDR area
|
|
||||||
// arg
|
|
||||||
// arg
|
|
||||||
// RETADDR
|
|
||||||
// { ...
|
|
||||||
// RETADDR area
|
|
||||||
// ...
|
|
||||||
// }
|
|
||||||
// [EBP]
|
|
||||||
MFI->CreateFixedObject(-TailCallReturnAddrDelta,
|
|
||||||
(-1U*SlotSize)+TailCallReturnAddrDelta, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (TFI->hasFP(MF)) {
|
|
||||||
assert((TailCallReturnAddrDelta <= 0) &&
|
|
||||||
"The Delta should always be zero or negative");
|
|
||||||
const TargetFrameInfo &TFI = *MF.getTarget().getFrameInfo();
|
|
||||||
|
|
||||||
// Create a frame entry for the EBP register that must be saved.
|
|
||||||
int FrameIdx = MFI->CreateFixedObject(SlotSize,
|
|
||||||
-(int)SlotSize +
|
|
||||||
TFI.getOffsetOfLocalArea() +
|
|
||||||
TailCallReturnAddrDelta,
|
|
||||||
true);
|
|
||||||
assert(FrameIdx == MFI->getObjectIndexBegin() &&
|
|
||||||
"Slot for EBP register must be last in order to be found!");
|
|
||||||
FrameIdx = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned X86RegisterInfo::getRARegister() const {
|
unsigned X86RegisterInfo::getRARegister() const {
|
||||||
return Is64Bit ? X86::RIP // Should have dwarf #16.
|
return Is64Bit ? X86::RIP // Should have dwarf #16.
|
||||||
: X86::EIP; // Should have dwarf #8.
|
: X86::EIP; // Should have dwarf #8.
|
||||||
|
@ -125,9 +125,6 @@ public:
|
|||||||
void eliminateFrameIndex(MachineBasicBlock::iterator MI,
|
void eliminateFrameIndex(MachineBasicBlock::iterator MI,
|
||||||
int SPAdj, RegScavenger *RS = NULL) const;
|
int SPAdj, RegScavenger *RS = NULL) const;
|
||||||
|
|
||||||
void processFunctionBeforeCalleeSavedScan(MachineFunction &MF,
|
|
||||||
RegScavenger *RS = NULL) const;
|
|
||||||
|
|
||||||
// Debug information queries.
|
// Debug information queries.
|
||||||
unsigned getRARegister() const;
|
unsigned getRARegister() const;
|
||||||
unsigned getFrameRegister(const MachineFunction &MF) const;
|
unsigned getFrameRegister(const MachineFunction &MF) const;
|
||||||
|
@ -22,6 +22,7 @@
|
|||||||
#include "llvm/CodeGen/MachineInstrBuilder.h"
|
#include "llvm/CodeGen/MachineInstrBuilder.h"
|
||||||
#include "llvm/CodeGen/MachineModuleInfo.h"
|
#include "llvm/CodeGen/MachineModuleInfo.h"
|
||||||
#include "llvm/CodeGen/MachineRegisterInfo.h"
|
#include "llvm/CodeGen/MachineRegisterInfo.h"
|
||||||
|
#include "llvm/CodeGen/RegisterScavenging.h"
|
||||||
#include "llvm/Target/TargetData.h"
|
#include "llvm/Target/TargetData.h"
|
||||||
#include "llvm/Target/TargetOptions.h"
|
#include "llvm/Target/TargetOptions.h"
|
||||||
#include "llvm/Support/ErrorHandling.h"
|
#include "llvm/Support/ErrorHandling.h"
|
||||||
@ -336,3 +337,46 @@ bool XCoreFrameInfo::restoreCalleeSavedRegisters(MachineBasicBlock &MBB,
|
|||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
XCoreFrameInfo::processFunctionBeforeCalleeSavedScan(MachineFunction &MF,
|
||||||
|
RegScavenger *RS) const {
|
||||||
|
MachineFrameInfo *MFI = MF.getFrameInfo();
|
||||||
|
const TargetRegisterInfo *RegInfo = MF.getTarget().getRegisterInfo();
|
||||||
|
bool LRUsed = MF.getRegInfo().isPhysRegUsed(XCore::LR);
|
||||||
|
const TargetRegisterClass *RC = XCore::GRRegsRegisterClass;
|
||||||
|
XCoreFunctionInfo *XFI = MF.getInfo<XCoreFunctionInfo>();
|
||||||
|
if (LRUsed) {
|
||||||
|
MF.getRegInfo().setPhysRegUnused(XCore::LR);
|
||||||
|
|
||||||
|
bool isVarArg = MF.getFunction()->isVarArg();
|
||||||
|
int FrameIdx;
|
||||||
|
if (! isVarArg) {
|
||||||
|
// A fixed offset of 0 allows us to save / restore LR using entsp / retsp.
|
||||||
|
FrameIdx = MFI->CreateFixedObject(RC->getSize(), 0, true);
|
||||||
|
} else {
|
||||||
|
FrameIdx = MFI->CreateStackObject(RC->getSize(), RC->getAlignment(),
|
||||||
|
false);
|
||||||
|
}
|
||||||
|
XFI->setUsesLR(FrameIdx);
|
||||||
|
XFI->setLRSpillSlot(FrameIdx);
|
||||||
|
}
|
||||||
|
if (RegInfo->requiresRegisterScavenging(MF)) {
|
||||||
|
// Reserve a slot close to SP or frame pointer.
|
||||||
|
RS->setScavengingFrameIndex(MFI->CreateStackObject(RC->getSize(),
|
||||||
|
RC->getAlignment(),
|
||||||
|
false));
|
||||||
|
}
|
||||||
|
if (hasFP(MF)) {
|
||||||
|
// A callee save register is used to hold the FP.
|
||||||
|
// This needs saving / restoring in the epilogue / prologue.
|
||||||
|
XFI->setFPSpillSlot(MFI->CreateStackObject(RC->getSize(),
|
||||||
|
RC->getAlignment(),
|
||||||
|
false));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void XCoreFrameInfo::
|
||||||
|
processFunctionBeforeFrameFinalized(MachineFunction &MF) const {
|
||||||
|
|
||||||
|
}
|
||||||
|
@ -44,6 +44,11 @@ namespace llvm {
|
|||||||
|
|
||||||
void getInitialFrameState(std::vector<MachineMove> &Moves) const;
|
void getInitialFrameState(std::vector<MachineMove> &Moves) const;
|
||||||
|
|
||||||
|
void processFunctionBeforeCalleeSavedScan(MachineFunction &MF,
|
||||||
|
RegScavenger *RS = NULL) const;
|
||||||
|
|
||||||
|
void processFunctionBeforeFrameFinalized(MachineFunction &MF) const;
|
||||||
|
|
||||||
//! Stack slot size (4 bytes)
|
//! Stack slot size (4 bytes)
|
||||||
static int stackSlotSize() {
|
static int stackSlotSize() {
|
||||||
return 4;
|
return 4;
|
||||||
|
@ -295,49 +295,6 @@ XCoreRegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II,
|
|||||||
MBB.erase(II);
|
MBB.erase(II);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
|
||||||
XCoreRegisterInfo::processFunctionBeforeCalleeSavedScan(MachineFunction &MF,
|
|
||||||
RegScavenger *RS) const {
|
|
||||||
MachineFrameInfo *MFI = MF.getFrameInfo();
|
|
||||||
const TargetFrameInfo *TFI = MF.getTarget().getFrameInfo();
|
|
||||||
bool LRUsed = MF.getRegInfo().isPhysRegUsed(XCore::LR);
|
|
||||||
const TargetRegisterClass *RC = XCore::GRRegsRegisterClass;
|
|
||||||
XCoreFunctionInfo *XFI = MF.getInfo<XCoreFunctionInfo>();
|
|
||||||
if (LRUsed) {
|
|
||||||
MF.getRegInfo().setPhysRegUnused(XCore::LR);
|
|
||||||
|
|
||||||
bool isVarArg = MF.getFunction()->isVarArg();
|
|
||||||
int FrameIdx;
|
|
||||||
if (! isVarArg) {
|
|
||||||
// A fixed offset of 0 allows us to save / restore LR using entsp / retsp.
|
|
||||||
FrameIdx = MFI->CreateFixedObject(RC->getSize(), 0, true);
|
|
||||||
} else {
|
|
||||||
FrameIdx = MFI->CreateStackObject(RC->getSize(), RC->getAlignment(),
|
|
||||||
false);
|
|
||||||
}
|
|
||||||
XFI->setUsesLR(FrameIdx);
|
|
||||||
XFI->setLRSpillSlot(FrameIdx);
|
|
||||||
}
|
|
||||||
if (requiresRegisterScavenging(MF)) {
|
|
||||||
// Reserve a slot close to SP or frame pointer.
|
|
||||||
RS->setScavengingFrameIndex(MFI->CreateStackObject(RC->getSize(),
|
|
||||||
RC->getAlignment(),
|
|
||||||
false));
|
|
||||||
}
|
|
||||||
if (TFI->hasFP(MF)) {
|
|
||||||
// A callee save register is used to hold the FP.
|
|
||||||
// This needs saving / restoring in the epilogue / prologue.
|
|
||||||
XFI->setFPSpillSlot(MFI->CreateStackObject(RC->getSize(),
|
|
||||||
RC->getAlignment(),
|
|
||||||
false));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void XCoreRegisterInfo::
|
|
||||||
processFunctionBeforeFrameFinalized(MachineFunction &MF) const {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
void XCoreRegisterInfo::
|
void XCoreRegisterInfo::
|
||||||
loadConstant(MachineBasicBlock &MBB, MachineBasicBlock::iterator I,
|
loadConstant(MachineBasicBlock &MBB, MachineBasicBlock::iterator I,
|
||||||
unsigned DstReg, int64_t Value, DebugLoc dl) const {
|
unsigned DstReg, int64_t Value, DebugLoc dl) const {
|
||||||
|
@ -55,11 +55,6 @@ public:
|
|||||||
void eliminateFrameIndex(MachineBasicBlock::iterator II,
|
void eliminateFrameIndex(MachineBasicBlock::iterator II,
|
||||||
int SPAdj, RegScavenger *RS = NULL) const;
|
int SPAdj, RegScavenger *RS = NULL) const;
|
||||||
|
|
||||||
void processFunctionBeforeCalleeSavedScan(MachineFunction &MF,
|
|
||||||
RegScavenger *RS = NULL) const;
|
|
||||||
|
|
||||||
void processFunctionBeforeFrameFinalized(MachineFunction &MF) const;
|
|
||||||
|
|
||||||
// Debug information queries.
|
// Debug information queries.
|
||||||
unsigned getRARegister() const;
|
unsigned getRARegister() const;
|
||||||
unsigned getFrameRegister(const MachineFunction &MF) const;
|
unsigned getFrameRegister(const MachineFunction &MF) const;
|
||||||
|
Reference in New Issue
Block a user