SPUFrameLowering.cpp [plain text]
#include "SPUFrameLowering.h"
#include "SPU.h"
#include "SPUInstrBuilder.h"
#include "SPUInstrInfo.h"
#include "llvm/Function.h"
#include "llvm/CodeGen/MachineFrameInfo.h"
#include "llvm/CodeGen/MachineFunction.h"
#include "llvm/CodeGen/MachineInstrBuilder.h"
#include "llvm/CodeGen/MachineModuleInfo.h"
#include "llvm/CodeGen/MachineRegisterInfo.h"
#include "llvm/CodeGen/RegisterScavenging.h"
#include "llvm/Target/TargetData.h"
#include "llvm/Target/TargetOptions.h"
#include "llvm/Support/CommandLine.h"
using namespace llvm;
SPUFrameLowering::SPUFrameLowering(const SPUSubtarget &sti)
: TargetFrameLowering(TargetFrameLowering::StackGrowsDown, 16, 0),
Subtarget(sti) {
LR[0].first = SPU::R0;
LR[0].second = 16;
}
bool SPUFrameLowering::hasFP(const MachineFunction &MF) const {
const MachineFrameInfo *MFI = MF.getFrameInfo();
return MFI->getStackSize() &&
(MF.getTarget().Options.DisableFramePointerElim(MF) ||
MFI->hasVarSizedObjects());
}
void SPUFrameLowering::determineFrameLayout(MachineFunction &MF) const {
MachineFrameInfo *MFI = MF.getFrameInfo();
unsigned FrameSize = MFI->getStackSize();
unsigned TargetAlign = getStackAlignment();
unsigned Align = std::max(TargetAlign, MFI->getMaxAlignment());
assert(isPowerOf2_32(Align) && "Alignment is not power of 2");
unsigned AlignMask = Align - 1;
unsigned maxCallFrameSize = MFI->getMaxCallFrameSize();
if (MFI->hasVarSizedObjects())
maxCallFrameSize = (maxCallFrameSize + AlignMask) & ~AlignMask;
MFI->setMaxCallFrameSize(maxCallFrameSize);
FrameSize += maxCallFrameSize;
FrameSize = (FrameSize + AlignMask) & ~AlignMask;
MFI->setStackSize(FrameSize);
}
void SPUFrameLowering::emitPrologue(MachineFunction &MF) const {
MachineBasicBlock &MBB = MF.front(); MachineBasicBlock::iterator MBBI = MBB.begin();
MachineFrameInfo *MFI = MF.getFrameInfo();
const SPUInstrInfo &TII =
*static_cast<const SPUInstrInfo*>(MF.getTarget().getInstrInfo());
MachineModuleInfo &MMI = MF.getMMI();
DebugLoc dl = MBBI != MBB.end() ? MBBI->getDebugLoc() : DebugLoc();
bool hasDebugInfo = MMI.hasDebugInfo();
MCSymbol *FrameLabel = 0;
MBBI = MBB.begin();
determineFrameLayout(MF);
int FrameSize = MFI->getStackSize();
assert((FrameSize & 0xf) == 0
&& "SPURegisterInfo::emitPrologue: FrameSize not aligned");
if (FrameSize > 16 || MFI->adjustsStack()) {
FrameSize = -(FrameSize + SPUFrameLowering::minStackSize());
if (hasDebugInfo) {
FrameLabel = MMI.getContext().CreateTempSymbol();
BuildMI(MBB, MBBI, dl, TII.get(SPU::PROLOG_LABEL)).addSym(FrameLabel);
}
BuildMI(MBB, MBBI, dl, TII.get(SPU::STQDr32), SPU::R0).addImm(16)
.addReg(SPU::R1);
if (isInt<10>(FrameSize)) {
BuildMI(MBB, MBBI, dl, TII.get(SPU::STQDr32), SPU::R1).addImm(FrameSize)
.addReg(SPU::R1);
BuildMI(MBB, MBBI, dl, TII.get(SPU::AIr32), SPU::R1).addReg(SPU::R1)
.addImm(FrameSize);
} else if (isInt<16>(FrameSize)) {
BuildMI(MBB, MBBI, dl, TII.get(SPU::STQDr128), SPU::R2)
.addImm(-16)
.addReg(SPU::R1);
BuildMI(MBB, MBBI, dl, TII.get(SPU::ILr32), SPU::R2)
.addImm(FrameSize);
BuildMI(MBB, MBBI, dl, TII.get(SPU::STQXr32), SPU::R1)
.addReg(SPU::R2)
.addReg(SPU::R1);
BuildMI(MBB, MBBI, dl, TII.get(SPU::Ar32), SPU::R1)
.addReg(SPU::R1)
.addReg(SPU::R2);
BuildMI(MBB, MBBI, dl, TII.get(SPU::SFIr32), SPU::R2)
.addReg(SPU::R2)
.addImm(16);
BuildMI(MBB, MBBI, dl, TII.get(SPU::LQXr128), SPU::R2)
.addReg(SPU::R2)
.addReg(SPU::R1);
} else {
report_fatal_error("Unhandled frame size: " + Twine(FrameSize));
}
if (hasDebugInfo) {
std::vector<MachineMove> &Moves = MMI.getFrameMoves();
MachineLocation SPDst(MachineLocation::VirtualFP);
MachineLocation SPSrc(MachineLocation::VirtualFP, -FrameSize);
Moves.push_back(MachineMove(FrameLabel, SPDst, SPSrc));
const std::vector<CalleeSavedInfo> &CSI = MFI->getCalleeSavedInfo();
for (unsigned I = 0, E = CSI.size(); I != E; ++I) {
int Offset = MFI->getObjectOffset(CSI[I].getFrameIdx());
unsigned Reg = CSI[I].getReg();
if (Reg == SPU::R0) continue;
MachineLocation CSDst(MachineLocation::VirtualFP, Offset);
MachineLocation CSSrc(Reg);
Moves.push_back(MachineMove(FrameLabel, CSDst, CSSrc));
}
MCSymbol *ReadyLabel = MMI.getContext().CreateTempSymbol();
BuildMI(MBB, MBBI, dl, TII.get(SPU::PROLOG_LABEL)).addSym(ReadyLabel);
MachineLocation FPDst(SPU::R1);
MachineLocation FPSrc(MachineLocation::VirtualFP);
Moves.push_back(MachineMove(ReadyLabel, FPDst, FPSrc));
}
}
}
void SPUFrameLowering::emitEpilogue(MachineFunction &MF,
MachineBasicBlock &MBB) const {
MachineBasicBlock::iterator MBBI = MBB.getLastNonDebugInstr();
const SPUInstrInfo &TII =
*static_cast<const SPUInstrInfo*>(MF.getTarget().getInstrInfo());
const MachineFrameInfo *MFI = MF.getFrameInfo();
int FrameSize = MFI->getStackSize();
int LinkSlotOffset = SPUFrameLowering::stackSlotSize();
DebugLoc dl = MBBI->getDebugLoc();
assert(MBBI->getOpcode() == SPU::RET &&
"Can only insert epilog into returning blocks");
assert((FrameSize & 0xf) == 0 && "FrameSize not aligned");
if (FrameSize > 16 || MFI->adjustsStack()) {
FrameSize = FrameSize + SPUFrameLowering::minStackSize();
if (isInt<10>(FrameSize + LinkSlotOffset)) {
BuildMI(MBB, MBBI, dl, TII.get(SPU::LQDr128), SPU::R0)
.addImm(FrameSize + LinkSlotOffset)
.addReg(SPU::R1);
BuildMI(MBB, MBBI, dl, TII.get(SPU::AIr32), SPU::R1)
.addReg(SPU::R1)
.addImm(FrameSize);
} else if (FrameSize <= (1 << 16) - 1 && FrameSize >= -(1 << 16)) {
BuildMI(MBB, MBBI, dl, TII.get(SPU::STQDr128), SPU::R2)
.addImm(16)
.addReg(SPU::R1);
BuildMI(MBB, MBBI, dl, TII.get(SPU::ILr32), SPU::R2)
.addImm(FrameSize);
BuildMI(MBB, MBBI, dl, TII.get(SPU::Ar32), SPU::R1)
.addReg(SPU::R1)
.addReg(SPU::R2);
BuildMI(MBB, MBBI, dl, TII.get(SPU::LQDr128), SPU::R0)
.addImm(16)
.addReg(SPU::R1);
BuildMI(MBB, MBBI, dl, TII.get(SPU::SFIr32), SPU::R2).
addReg(SPU::R2)
.addImm(16);
BuildMI(MBB, MBBI, dl, TII.get(SPU::LQXr128), SPU::R2)
.addReg(SPU::R2)
.addReg(SPU::R1);
} else {
report_fatal_error("Unhandled frame size: " + Twine(FrameSize));
}
}
}
void SPUFrameLowering::processFunctionBeforeCalleeSavedScan(MachineFunction &MF,
RegScavenger *RS) const{
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));
}