PPCFrameLowering.cpp [plain text]
#include "PPCFrameLowering.h"
#include "PPCInstrBuilder.h"
#include "PPCInstrInfo.h"
#include "PPCMachineFunctionInfo.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/IR/Function.h"
#include "llvm/Target/TargetOptions.h"
using namespace llvm;
static const uint16_t VRRegNo[] = {
PPC::V0 , PPC::V1 , PPC::V2 , PPC::V3 , PPC::V4 , PPC::V5 , PPC::V6 , PPC::V7 ,
PPC::V8 , PPC::V9 , PPC::V10, PPC::V11, PPC::V12, PPC::V13, PPC::V14, PPC::V15,
PPC::V16, PPC::V17, PPC::V18, PPC::V19, PPC::V20, PPC::V21, PPC::V22, PPC::V23,
PPC::V24, PPC::V25, PPC::V26, PPC::V27, PPC::V28, PPC::V29, PPC::V30, PPC::V31
};
static void RemoveVRSaveCode(MachineInstr *MI) {
MachineBasicBlock *Entry = MI->getParent();
MachineFunction *MF = Entry->getParent();
MachineBasicBlock::iterator MBBI = MI;
++MBBI;
assert(MBBI != Entry->end() && MBBI->getOpcode() == PPC::MTVRSAVE);
MBBI->eraseFromParent();
bool RemovedAllMTVRSAVEs = true;
for (MachineFunction::iterator I = MF->begin(), E = MF->end(); I != E; ++I) {
if (!I->empty() && I->back().isReturn()) {
bool FoundIt = false;
for (MBBI = I->end(); MBBI != I->begin(); ) {
--MBBI;
if (MBBI->getOpcode() == PPC::MTVRSAVE) {
MBBI->eraseFromParent(); FoundIt = true;
break;
}
}
RemovedAllMTVRSAVEs &= FoundIt;
}
}
if (RemovedAllMTVRSAVEs) {
MBBI = MI;
assert(MBBI != Entry->begin() && "UPDATE_VRSAVE is first instr in block?");
--MBBI;
assert(MBBI->getOpcode() == PPC::MFVRSAVE && "VRSAVE instrs wandered?");
MBBI->eraseFromParent();
}
MI->eraseFromParent();
}
static void HandleVRSaveUpdate(MachineInstr *MI, const TargetInstrInfo &TII) {
MachineFunction *MF = MI->getParent()->getParent();
const TargetRegisterInfo *TRI = MF->getTarget().getRegisterInfo();
DebugLoc dl = MI->getDebugLoc();
unsigned UsedRegMask = 0;
for (unsigned i = 0; i != 32; ++i)
if (MF->getRegInfo().isPhysRegUsed(VRRegNo[i]))
UsedRegMask |= 1 << (31-i);
for (MachineRegisterInfo::livein_iterator
I = MF->getRegInfo().livein_begin(),
E = MF->getRegInfo().livein_end(); I != E; ++I) {
unsigned RegNo = TRI->getEncodingValue(I->first);
if (VRRegNo[RegNo] == I->first) UsedRegMask &= ~(1 << (31-RegNo)); }
for (MachineFunction::const_iterator BI = MF->begin(), BE = MF->end();
UsedRegMask != 0 && BI != BE; ++BI) {
const MachineBasicBlock &MBB = *BI;
if (MBB.empty() || !MBB.back().isReturn())
continue;
const MachineInstr &Ret = MBB.back();
for (unsigned I = 0, E = Ret.getNumOperands(); I != E; ++I) {
const MachineOperand &MO = Ret.getOperand(I);
if (!MO.isReg() || !PPC::VRRCRegClass.contains(MO.getReg()))
continue;
unsigned RegNo = TRI->getEncodingValue(MO.getReg());
UsedRegMask &= ~(1 << (31-RegNo));
}
}
if (UsedRegMask == 0) {
RemoveVRSaveCode(MI);
return;
}
unsigned SrcReg = MI->getOperand(1).getReg();
unsigned DstReg = MI->getOperand(0).getReg();
if ((UsedRegMask & 0xFFFF) == UsedRegMask) {
if (DstReg != SrcReg)
BuildMI(*MI->getParent(), MI, dl, TII.get(PPC::ORI), DstReg)
.addReg(SrcReg)
.addImm(UsedRegMask);
else
BuildMI(*MI->getParent(), MI, dl, TII.get(PPC::ORI), DstReg)
.addReg(SrcReg, RegState::Kill)
.addImm(UsedRegMask);
} else if ((UsedRegMask & 0xFFFF0000) == UsedRegMask) {
if (DstReg != SrcReg)
BuildMI(*MI->getParent(), MI, dl, TII.get(PPC::ORIS), DstReg)
.addReg(SrcReg)
.addImm(UsedRegMask >> 16);
else
BuildMI(*MI->getParent(), MI, dl, TII.get(PPC::ORIS), DstReg)
.addReg(SrcReg, RegState::Kill)
.addImm(UsedRegMask >> 16);
} else {
if (DstReg != SrcReg)
BuildMI(*MI->getParent(), MI, dl, TII.get(PPC::ORIS), DstReg)
.addReg(SrcReg)
.addImm(UsedRegMask >> 16);
else
BuildMI(*MI->getParent(), MI, dl, TII.get(PPC::ORIS), DstReg)
.addReg(SrcReg, RegState::Kill)
.addImm(UsedRegMask >> 16);
BuildMI(*MI->getParent(), MI, dl, TII.get(PPC::ORI), DstReg)
.addReg(DstReg, RegState::Kill)
.addImm(UsedRegMask & 0xFFFF);
}
MI->eraseFromParent();
}
static bool spillsCR(const MachineFunction &MF) {
const PPCFunctionInfo *FuncInfo = MF.getInfo<PPCFunctionInfo>();
return FuncInfo->isCRSpilled();
}
static bool spillsVRSAVE(const MachineFunction &MF) {
const PPCFunctionInfo *FuncInfo = MF.getInfo<PPCFunctionInfo>();
return FuncInfo->isVRSAVESpilled();
}
static bool hasSpills(const MachineFunction &MF) {
const PPCFunctionInfo *FuncInfo = MF.getInfo<PPCFunctionInfo>();
return FuncInfo->hasSpills();
}
static bool hasNonRISpills(const MachineFunction &MF) {
const PPCFunctionInfo *FuncInfo = MF.getInfo<PPCFunctionInfo>();
return FuncInfo->hasNonRISpills();
}
unsigned PPCFrameLowering::determineFrameLayout(MachineFunction &MF,
bool UpdateMF,
bool UseEstimate) const {
MachineFrameInfo *MFI = MF.getFrameInfo();
unsigned FrameSize =
UseEstimate ? MFI->estimateStackSize(MF) : MFI->getStackSize();
unsigned TargetAlign = getStackAlignment(); unsigned MaxAlign = MFI->getMaxAlignment(); unsigned AlignMask = std::max(MaxAlign, TargetAlign) - 1;
const PPCRegisterInfo *RegInfo =
static_cast<const PPCRegisterInfo*>(MF.getTarget().getRegisterInfo());
bool DisableRedZone = MF.getFunction()->getAttributes().
hasAttribute(AttributeSet::FunctionIndex, Attribute::NoRedZone);
if (!DisableRedZone &&
(Subtarget.isPPC64() || !Subtarget.isSVR4ABI() || FrameSize == 0) &&
FrameSize <= 224 && !MFI->hasVarSizedObjects() && !MFI->adjustsStack() && !RegInfo->hasBasePointer(MF)) { if (UpdateMF)
MFI->setStackSize(0);
return 0;
}
unsigned maxCallFrameSize = MFI->getMaxCallFrameSize();
unsigned minCallFrameSize = getMinCallFrameSize(Subtarget.isPPC64(),
Subtarget.isDarwinABI());
maxCallFrameSize = std::max(maxCallFrameSize, minCallFrameSize);
if (MFI->hasVarSizedObjects())
maxCallFrameSize = (maxCallFrameSize + AlignMask) & ~AlignMask;
if (UpdateMF)
MFI->setMaxCallFrameSize(maxCallFrameSize);
FrameSize += maxCallFrameSize;
FrameSize = (FrameSize + AlignMask) & ~AlignMask;
if (UpdateMF)
MFI->setStackSize(FrameSize);
return FrameSize;
}
bool PPCFrameLowering::hasFP(const MachineFunction &MF) const {
const MachineFrameInfo *MFI = MF.getFrameInfo();
return (MFI->getStackSize()) && needsFP(MF);
}
bool PPCFrameLowering::needsFP(const MachineFunction &MF) const {
const MachineFrameInfo *MFI = MF.getFrameInfo();
if (MF.getFunction()->getAttributes().hasAttribute(AttributeSet::FunctionIndex,
Attribute::Naked))
return false;
return MF.getTarget().Options.DisableFramePointerElim(MF) ||
MFI->hasVarSizedObjects() ||
(MF.getTarget().Options.GuaranteedTailCallOpt &&
MF.getInfo<PPCFunctionInfo>()->hasFastCall());
}
void PPCFrameLowering::replaceFPWithRealFP(MachineFunction &MF) const {
bool is31 = needsFP(MF);
unsigned FPReg = is31 ? PPC::R31 : PPC::R1;
unsigned FP8Reg = is31 ? PPC::X31 : PPC::X1;
const PPCRegisterInfo *RegInfo =
static_cast<const PPCRegisterInfo*>(MF.getTarget().getRegisterInfo());
bool HasBP = RegInfo->hasBasePointer(MF);
unsigned BPReg = HasBP ? (unsigned) PPC::R30 : FPReg;
unsigned BP8Reg = HasBP ? (unsigned) PPC::X30 : FPReg;
for (MachineFunction::iterator BI = MF.begin(), BE = MF.end();
BI != BE; ++BI)
for (MachineBasicBlock::iterator MBBI = BI->end(); MBBI != BI->begin(); ) {
--MBBI;
for (unsigned I = 0, E = MBBI->getNumOperands(); I != E; ++I) {
MachineOperand &MO = MBBI->getOperand(I);
if (!MO.isReg())
continue;
switch (MO.getReg()) {
case PPC::FP:
MO.setReg(FPReg);
break;
case PPC::FP8:
MO.setReg(FP8Reg);
break;
case PPC::BP:
MO.setReg(BPReg);
break;
case PPC::BP8:
MO.setReg(BP8Reg);
break;
}
}
}
}
void PPCFrameLowering::emitPrologue(MachineFunction &MF) const {
MachineBasicBlock &MBB = MF.front(); MachineBasicBlock::iterator MBBI = MBB.begin();
MachineFrameInfo *MFI = MF.getFrameInfo();
const PPCInstrInfo &TII =
*static_cast<const PPCInstrInfo*>(MF.getTarget().getInstrInfo());
const PPCRegisterInfo *RegInfo =
static_cast<const PPCRegisterInfo*>(MF.getTarget().getRegisterInfo());
MachineModuleInfo &MMI = MF.getMMI();
const MCRegisterInfo *MRI = MMI.getContext().getRegisterInfo();
DebugLoc dl;
bool needsFrameMoves = MMI.hasDebugInfo() ||
MF.getFunction()->needsUnwindTableEntry();
bool isPPC64 = Subtarget.isPPC64();
bool isDarwinABI = Subtarget.isDarwinABI();
bool isSVR4ABI = Subtarget.isSVR4ABI();
assert((isDarwinABI || isSVR4ABI) &&
"Currently only Darwin and SVR4 ABIs are supported for PowerPC.");
MCSymbol *FrameLabel = 0;
if (!isSVR4ABI)
for (unsigned i = 0; MBBI != MBB.end(); ++i, ++MBBI) {
if (MBBI->getOpcode() == PPC::UPDATE_VRSAVE) {
HandleVRSaveUpdate(MBBI, TII);
break;
}
}
MBBI = MBB.begin();
unsigned FrameSize = determineFrameLayout(MF);
int NegFrameSize = -FrameSize;
if (!isInt<32>(NegFrameSize))
llvm_unreachable("Unhandled stack size!");
if (MFI->isFrameAddressTaken())
replaceFPWithRealFP(MF);
PPCFunctionInfo *FI = MF.getInfo<PPCFunctionInfo>();
bool MustSaveLR = FI->mustSaveLR();
const SmallVectorImpl<unsigned> &MustSaveCRs = FI->getMustSaveCRs();
bool HasFP = hasFP(MF);
bool HasBP = RegInfo->hasBasePointer(MF);
unsigned SPReg = isPPC64 ? PPC::X1 : PPC::R1;
unsigned BPReg = isPPC64 ? PPC::X30 : PPC::R30;
unsigned FPReg = isPPC64 ? PPC::X31 : PPC::R31;
unsigned LRReg = isPPC64 ? PPC::LR8 : PPC::LR;
unsigned ScratchReg = isPPC64 ? PPC::X0 : PPC::R0;
unsigned TempReg = isPPC64 ? PPC::X12 : PPC::R12; const MCInstrDesc& MFLRInst = TII.get(isPPC64 ? PPC::MFLR8
: PPC::MFLR );
const MCInstrDesc& StoreInst = TII.get(isPPC64 ? PPC::STD
: PPC::STW );
const MCInstrDesc& StoreUpdtInst = TII.get(isPPC64 ? PPC::STDU
: PPC::STWU );
const MCInstrDesc& StoreUpdtIdxInst = TII.get(isPPC64 ? PPC::STDUX
: PPC::STWUX);
const MCInstrDesc& LoadImmShiftedInst = TII.get(isPPC64 ? PPC::LIS8
: PPC::LIS );
const MCInstrDesc& OrImmInst = TII.get(isPPC64 ? PPC::ORI8
: PPC::ORI );
const MCInstrDesc& OrInst = TII.get(isPPC64 ? PPC::OR8
: PPC::OR );
const MCInstrDesc& SubtractCarryingInst = TII.get(isPPC64 ? PPC::SUBFC8
: PPC::SUBFC);
const MCInstrDesc& SubtractImmCarryingInst = TII.get(isPPC64 ? PPC::SUBFIC8
: PPC::SUBFIC);
assert((isPPC64 || !isSVR4ABI || !(!FrameSize && (MustSaveLR || HasFP))) &&
"FrameSize must be >0 to save/restore the FP or LR for 32-bit SVR4.");
int LROffset = PPCFrameLowering::getReturnSaveOffset(isPPC64, isDarwinABI);
int FPOffset = 0;
if (HasFP) {
if (isSVR4ABI) {
MachineFrameInfo *FFI = MF.getFrameInfo();
int FPIndex = FI->getFramePointerSaveIndex();
assert(FPIndex && "No Frame Pointer Save Slot!");
FPOffset = FFI->getObjectOffset(FPIndex);
} else {
FPOffset = PPCFrameLowering::getFramePointerSaveOffset(isPPC64, isDarwinABI);
}
}
int BPOffset = 0;
if (HasBP) {
if (isSVR4ABI) {
MachineFrameInfo *FFI = MF.getFrameInfo();
int BPIndex = FI->getBasePointerSaveIndex();
assert(BPIndex && "No Base Pointer Save Slot!");
BPOffset = FFI->getObjectOffset(BPIndex);
} else {
BPOffset =
PPCFrameLowering::getBasePointerSaveOffset(isPPC64, isDarwinABI);
}
}
unsigned MaxAlign = MFI->getMaxAlignment();
if (HasBP && MaxAlign > 1)
assert(isPowerOf2_32(MaxAlign) && isInt<16>(MaxAlign) &&
"Invalid alignment!");
bool isLargeFrame = !isInt<16>(NegFrameSize);
if (MustSaveLR)
BuildMI(MBB, MBBI, dl, MFLRInst, ScratchReg);
assert((isPPC64 || MustSaveCRs.empty()) &&
"Prologue CR saving supported only in 64-bit mode");
if (!MustSaveCRs.empty()) { MachineInstrBuilder MIB =
BuildMI(MBB, MBBI, dl, TII.get(PPC::MFCR8), TempReg);
for (unsigned i = 0, e = MustSaveCRs.size(); i != e; ++i)
MIB.addReg(MustSaveCRs[i], RegState::ImplicitKill);
}
if (HasFP)
BuildMI(MBB, MBBI, dl, StoreInst)
.addReg(FPReg)
.addImm(FPOffset)
.addReg(SPReg);
if (HasBP)
BuildMI(MBB, MBBI, dl, StoreInst)
.addReg(BPReg)
.addImm(BPOffset)
.addReg(SPReg);
if (MustSaveLR)
BuildMI(MBB, MBBI, dl, StoreInst)
.addReg(ScratchReg)
.addImm(LROffset)
.addReg(SPReg);
if (!MustSaveCRs.empty()) BuildMI(MBB, MBBI, dl, TII.get(PPC::STW8))
.addReg(TempReg, getKillRegState(true))
.addImm(8)
.addReg(SPReg);
if (!FrameSize) return;
if (HasBP) {
BuildMI(MBB, MBBI, dl, OrInst, BPReg)
.addReg(SPReg)
.addReg(SPReg);
}
if (HasBP && MaxAlign > 1) {
if (isPPC64)
BuildMI(MBB, MBBI, dl, TII.get(PPC::RLDICL), ScratchReg)
.addReg(SPReg)
.addImm(0)
.addImm(64 - Log2_32(MaxAlign));
else BuildMI(MBB, MBBI, dl, TII.get(PPC::RLWINM), ScratchReg)
.addReg(SPReg)
.addImm(0)
.addImm(32 - Log2_32(MaxAlign))
.addImm(31);
if (!isLargeFrame) {
BuildMI(MBB, MBBI, dl, SubtractImmCarryingInst, ScratchReg)
.addReg(ScratchReg, RegState::Kill)
.addImm(NegFrameSize);
} else {
BuildMI(MBB, MBBI, dl, LoadImmShiftedInst, TempReg)
.addImm(NegFrameSize >> 16);
BuildMI(MBB, MBBI, dl, OrImmInst, TempReg)
.addReg(TempReg, RegState::Kill)
.addImm(NegFrameSize & 0xFFFF);
BuildMI(MBB, MBBI, dl, SubtractCarryingInst, ScratchReg)
.addReg(ScratchReg, RegState::Kill)
.addReg(TempReg, RegState::Kill);
}
BuildMI(MBB, MBBI, dl, StoreUpdtIdxInst, SPReg)
.addReg(SPReg, RegState::Kill)
.addReg(SPReg)
.addReg(ScratchReg);
} else if (!isLargeFrame) {
BuildMI(MBB, MBBI, dl, StoreUpdtInst, SPReg)
.addReg(SPReg)
.addImm(NegFrameSize)
.addReg(SPReg);
} else {
BuildMI(MBB, MBBI, dl, LoadImmShiftedInst, ScratchReg)
.addImm(NegFrameSize >> 16);
BuildMI(MBB, MBBI, dl, OrImmInst, ScratchReg)
.addReg(ScratchReg, RegState::Kill)
.addImm(NegFrameSize & 0xFFFF);
BuildMI(MBB, MBBI, dl, StoreUpdtIdxInst, SPReg)
.addReg(SPReg, RegState::Kill)
.addReg(SPReg)
.addReg(ScratchReg);
}
if (needsFrameMoves) {
FrameLabel = MMI.getContext().CreateTempSymbol();
BuildMI(MBB, MBBI, dl, TII.get(PPC::PROLOG_LABEL)).addSym(FrameLabel);
assert(NegFrameSize);
MMI.addFrameInst(
MCCFIInstruction::createDefCfaOffset(FrameLabel, NegFrameSize));
if (HasFP) {
unsigned Reg = MRI->getDwarfRegNum(FPReg, true);
MMI.addFrameInst(
MCCFIInstruction::createOffset(FrameLabel, Reg, FPOffset));
}
if (HasBP) {
unsigned Reg = MRI->getDwarfRegNum(BPReg, true);
MMI.addFrameInst(
MCCFIInstruction::createOffset(FrameLabel, Reg, BPOffset));
}
if (MustSaveLR) {
unsigned Reg = MRI->getDwarfRegNum(LRReg, true);
MMI.addFrameInst(
MCCFIInstruction::createOffset(FrameLabel, Reg, LROffset));
}
}
MCSymbol *ReadyLabel = 0;
if (HasFP) {
BuildMI(MBB, MBBI, dl, OrInst, FPReg)
.addReg(SPReg)
.addReg(SPReg);
if (needsFrameMoves) {
ReadyLabel = MMI.getContext().CreateTempSymbol();
BuildMI(MBB, MBBI, dl, TII.get(PPC::PROLOG_LABEL)).addSym(ReadyLabel);
unsigned Reg = MRI->getDwarfRegNum(FPReg, true);
MMI.addFrameInst(MCCFIInstruction::createDefCfaRegister(ReadyLabel, Reg));
}
}
if (needsFrameMoves) {
MCSymbol *Label = HasFP ? ReadyLabel : FrameLabel;
const std::vector<CalleeSavedInfo> &CSI = MFI->getCalleeSavedInfo();
for (unsigned I = 0, E = CSI.size(); I != E; ++I) {
unsigned Reg = CSI[I].getReg();
if (Reg == PPC::LR || Reg == PPC::LR8 || Reg == PPC::RM) continue;
if (PPC::CRBITRCRegClass.contains(Reg))
continue;
if (isSVR4ABI && (PPC::CR2 <= Reg && Reg <= PPC::CR4)
&& MustSaveCRs.empty())
continue;
if (isSVR4ABI && isPPC64 && (PPC::CR2 <= Reg && Reg <= PPC::CR4)) {
MMI.addFrameInst(MCCFIInstruction::createOffset(
Label, MRI->getDwarfRegNum(PPC::CR2, true), 8));
continue;
}
int Offset = MFI->getObjectOffset(CSI[I].getFrameIdx());
MMI.addFrameInst(MCCFIInstruction::createOffset(
Label, MRI->getDwarfRegNum(Reg, true), Offset));
}
}
}
void PPCFrameLowering::emitEpilogue(MachineFunction &MF,
MachineBasicBlock &MBB) const {
MachineBasicBlock::iterator MBBI = MBB.getLastNonDebugInstr();
assert(MBBI != MBB.end() && "Returning block has no terminator");
const PPCInstrInfo &TII =
*static_cast<const PPCInstrInfo*>(MF.getTarget().getInstrInfo());
const PPCRegisterInfo *RegInfo =
static_cast<const PPCRegisterInfo*>(MF.getTarget().getRegisterInfo());
unsigned RetOpcode = MBBI->getOpcode();
DebugLoc dl;
assert((RetOpcode == PPC::BLR ||
RetOpcode == PPC::TCRETURNri ||
RetOpcode == PPC::TCRETURNdi ||
RetOpcode == PPC::TCRETURNai ||
RetOpcode == PPC::TCRETURNri8 ||
RetOpcode == PPC::TCRETURNdi8 ||
RetOpcode == PPC::TCRETURNai8) &&
"Can only insert epilog into returning blocks");
const MachineFrameInfo *MFI = MF.getFrameInfo();
int FrameSize = MFI->getStackSize();
bool isPPC64 = Subtarget.isPPC64();
bool isDarwinABI = Subtarget.isDarwinABI();
bool isSVR4ABI = Subtarget.isSVR4ABI();
PPCFunctionInfo *FI = MF.getInfo<PPCFunctionInfo>();
bool MustSaveLR = FI->mustSaveLR();
const SmallVectorImpl<unsigned> &MustSaveCRs = FI->getMustSaveCRs();
bool HasFP = hasFP(MF);
bool HasBP = RegInfo->hasBasePointer(MF);
unsigned SPReg = isPPC64 ? PPC::X1 : PPC::R1;
unsigned BPReg = isPPC64 ? PPC::X30 : PPC::R30;
unsigned FPReg = isPPC64 ? PPC::X31 : PPC::R31;
unsigned ScratchReg = isPPC64 ? PPC::X0 : PPC::R0;
unsigned TempReg = isPPC64 ? PPC::X12 : PPC::R12; const MCInstrDesc& MTLRInst = TII.get( isPPC64 ? PPC::MTLR8
: PPC::MTLR );
const MCInstrDesc& LoadInst = TII.get( isPPC64 ? PPC::LD
: PPC::LWZ );
const MCInstrDesc& LoadImmShiftedInst = TII.get( isPPC64 ? PPC::LIS8
: PPC::LIS );
const MCInstrDesc& OrImmInst = TII.get( isPPC64 ? PPC::ORI8
: PPC::ORI );
const MCInstrDesc& AddImmInst = TII.get( isPPC64 ? PPC::ADDI8
: PPC::ADDI );
const MCInstrDesc& AddInst = TII.get( isPPC64 ? PPC::ADD8
: PPC::ADD4 );
int LROffset = PPCFrameLowering::getReturnSaveOffset(isPPC64, isDarwinABI);
int FPOffset = 0;
if (HasFP) {
if (isSVR4ABI) {
MachineFrameInfo *FFI = MF.getFrameInfo();
int FPIndex = FI->getFramePointerSaveIndex();
assert(FPIndex && "No Frame Pointer Save Slot!");
FPOffset = FFI->getObjectOffset(FPIndex);
} else {
FPOffset = PPCFrameLowering::getFramePointerSaveOffset(isPPC64, isDarwinABI);
}
}
int BPOffset = 0;
if (HasBP) {
if (isSVR4ABI) {
MachineFrameInfo *FFI = MF.getFrameInfo();
int BPIndex = FI->getBasePointerSaveIndex();
assert(BPIndex && "No Base Pointer Save Slot!");
BPOffset = FFI->getObjectOffset(BPIndex);
} else {
BPOffset =
PPCFrameLowering::getBasePointerSaveOffset(isPPC64, isDarwinABI);
}
}
bool UsesTCRet = RetOpcode == PPC::TCRETURNri ||
RetOpcode == PPC::TCRETURNdi ||
RetOpcode == PPC::TCRETURNai ||
RetOpcode == PPC::TCRETURNri8 ||
RetOpcode == PPC::TCRETURNdi8 ||
RetOpcode == PPC::TCRETURNai8;
if (UsesTCRet) {
int MaxTCRetDelta = FI->getTailCallSPDelta();
MachineOperand &StackAdjust = MBBI->getOperand(1);
assert(StackAdjust.isImm() && "Expecting immediate value.");
int StackAdj = StackAdjust.getImm();
int Delta = StackAdj - MaxTCRetDelta;
assert((Delta >= 0) && "Delta must be positive");
if (MaxTCRetDelta>0)
FrameSize += (StackAdj +Delta);
else
FrameSize += StackAdj;
}
bool isLargeFrame = !isInt<16>(FrameSize);
if (FrameSize) {
if (FI->hasFastCall()) {
assert(HasFP && "Expecting a valid frame pointer.");
if (!isLargeFrame) {
BuildMI(MBB, MBBI, dl, AddImmInst, SPReg)
.addReg(FPReg).addImm(FrameSize);
} else {
BuildMI(MBB, MBBI, dl, LoadImmShiftedInst, ScratchReg)
.addImm(FrameSize >> 16);
BuildMI(MBB, MBBI, dl, OrImmInst, ScratchReg)
.addReg(ScratchReg, RegState::Kill)
.addImm(FrameSize & 0xFFFF);
BuildMI(MBB, MBBI, dl, AddInst)
.addReg(SPReg)
.addReg(FPReg)
.addReg(ScratchReg);
}
} else if (!isLargeFrame && !HasBP && !MFI->hasVarSizedObjects()) {
BuildMI(MBB, MBBI, dl, AddImmInst, SPReg)
.addReg(SPReg)
.addImm(FrameSize);
} else {
BuildMI(MBB, MBBI, dl, LoadInst, SPReg)
.addImm(0)
.addReg(SPReg);
}
}
if (MustSaveLR)
BuildMI(MBB, MBBI, dl, LoadInst, ScratchReg)
.addImm(LROffset)
.addReg(SPReg);
assert((isPPC64 || MustSaveCRs.empty()) &&
"Epilogue CR restoring supported only in 64-bit mode");
if (!MustSaveCRs.empty()) BuildMI(MBB, MBBI, dl, TII.get(PPC::LWZ8), TempReg)
.addImm(8)
.addReg(SPReg);
if (HasFP)
BuildMI(MBB, MBBI, dl, LoadInst, FPReg)
.addImm(FPOffset)
.addReg(SPReg);
if (HasBP)
BuildMI(MBB, MBBI, dl, LoadInst, BPReg)
.addImm(BPOffset)
.addReg(SPReg);
if (!MustSaveCRs.empty()) for (unsigned i = 0, e = MustSaveCRs.size(); i != e; ++i)
BuildMI(MBB, MBBI, dl, TII.get(PPC::MTOCRF8), MustSaveCRs[i])
.addReg(TempReg, getKillRegState(i == e-1));
if (MustSaveLR)
BuildMI(MBB, MBBI, dl, MTLRInst).addReg(ScratchReg);
if (MF.getTarget().Options.GuaranteedTailCallOpt && RetOpcode == PPC::BLR &&
MF.getFunction()->getCallingConv() == CallingConv::Fast) {
PPCFunctionInfo *FI = MF.getInfo<PPCFunctionInfo>();
unsigned CallerAllocatedAmt = FI->getMinReservedArea();
if (CallerAllocatedAmt && isInt<16>(CallerAllocatedAmt)) {
BuildMI(MBB, MBBI, dl, AddImmInst, SPReg)
.addReg(SPReg).addImm(CallerAllocatedAmt);
} else {
BuildMI(MBB, MBBI, dl, LoadImmShiftedInst, ScratchReg)
.addImm(CallerAllocatedAmt >> 16);
BuildMI(MBB, MBBI, dl, OrImmInst, ScratchReg)
.addReg(ScratchReg, RegState::Kill)
.addImm(CallerAllocatedAmt & 0xFFFF);
BuildMI(MBB, MBBI, dl, AddInst)
.addReg(SPReg)
.addReg(FPReg)
.addReg(ScratchReg);
}
} else if (RetOpcode == PPC::TCRETURNdi) {
MBBI = MBB.getLastNonDebugInstr();
MachineOperand &JumpTarget = MBBI->getOperand(0);
BuildMI(MBB, MBBI, dl, TII.get(PPC::TAILB)).
addGlobalAddress(JumpTarget.getGlobal(), JumpTarget.getOffset());
} else if (RetOpcode == PPC::TCRETURNri) {
MBBI = MBB.getLastNonDebugInstr();
assert(MBBI->getOperand(0).isReg() && "Expecting register operand.");
BuildMI(MBB, MBBI, dl, TII.get(PPC::TAILBCTR));
} else if (RetOpcode == PPC::TCRETURNai) {
MBBI = MBB.getLastNonDebugInstr();
MachineOperand &JumpTarget = MBBI->getOperand(0);
BuildMI(MBB, MBBI, dl, TII.get(PPC::TAILBA)).addImm(JumpTarget.getImm());
} else if (RetOpcode == PPC::TCRETURNdi8) {
MBBI = MBB.getLastNonDebugInstr();
MachineOperand &JumpTarget = MBBI->getOperand(0);
BuildMI(MBB, MBBI, dl, TII.get(PPC::TAILB8)).
addGlobalAddress(JumpTarget.getGlobal(), JumpTarget.getOffset());
} else if (RetOpcode == PPC::TCRETURNri8) {
MBBI = MBB.getLastNonDebugInstr();
assert(MBBI->getOperand(0).isReg() && "Expecting register operand.");
BuildMI(MBB, MBBI, dl, TII.get(PPC::TAILBCTR8));
} else if (RetOpcode == PPC::TCRETURNai8) {
MBBI = MBB.getLastNonDebugInstr();
MachineOperand &JumpTarget = MBBI->getOperand(0);
BuildMI(MBB, MBBI, dl, TII.get(PPC::TAILBA8)).addImm(JumpTarget.getImm());
}
}
static bool MustSaveLR(const MachineFunction &MF, unsigned LR) {
const PPCFunctionInfo *MFI = MF.getInfo<PPCFunctionInfo>();
MachineRegisterInfo::def_iterator RI = MF.getRegInfo().def_begin(LR);
return RI !=MF.getRegInfo().def_end() || MFI->isLRStoreRequired();
}
void
PPCFrameLowering::processFunctionBeforeCalleeSavedScan(MachineFunction &MF,
RegScavenger *) const {
const PPCRegisterInfo *RegInfo =
static_cast<const PPCRegisterInfo*>(MF.getTarget().getRegisterInfo());
PPCFunctionInfo *FI = MF.getInfo<PPCFunctionInfo>();
unsigned LR = RegInfo->getRARegister();
FI->setMustSaveLR(MustSaveLR(MF, LR));
MachineRegisterInfo &MRI = MF.getRegInfo();
MRI.setPhysRegUnused(LR);
int FPSI = FI->getFramePointerSaveIndex();
bool isPPC64 = Subtarget.isPPC64();
bool isDarwinABI = Subtarget.isDarwinABI();
MachineFrameInfo *MFI = MF.getFrameInfo();
if (!FPSI && needsFP(MF)) {
int FPOffset = getFramePointerSaveOffset(isPPC64, isDarwinABI);
FPSI = MFI->CreateFixedObject(isPPC64? 8 : 4, FPOffset, true);
FI->setFramePointerSaveIndex(FPSI);
}
int BPSI = FI->getBasePointerSaveIndex();
if (!BPSI && RegInfo->hasBasePointer(MF)) {
int BPOffset = getBasePointerSaveOffset(isPPC64, isDarwinABI);
BPSI = MFI->CreateFixedObject(isPPC64? 8 : 4, BPOffset, true);
FI->setBasePointerSaveIndex(BPSI);
}
int TCSPDelta = 0;
if (MF.getTarget().Options.GuaranteedTailCallOpt &&
(TCSPDelta = FI->getTailCallSPDelta()) < 0) {
MFI->CreateFixedObject(-1 * TCSPDelta, TCSPDelta, true);
}
if (!isPPC64 && !isDarwinABI &&
(MRI.isPhysRegUsed(PPC::CR2) ||
MRI.isPhysRegUsed(PPC::CR3) ||
MRI.isPhysRegUsed(PPC::CR4))) {
int FrameIdx = MFI->CreateFixedObject((uint64_t)4, (int64_t)-4, true);
FI->setCRSpillFrameIndex(FrameIdx);
}
}
void PPCFrameLowering::processFunctionBeforeFrameFinalized(MachineFunction &MF,
RegScavenger *RS) const {
if (!Subtarget.isSVR4ABI()) {
addScavengingSpillSlot(MF, RS);
return;
}
MachineFrameInfo *FFI = MF.getFrameInfo();
const std::vector<CalleeSavedInfo> &CSI = FFI->getCalleeSavedInfo();
if (CSI.empty() && !needsFP(MF)) {
addScavengingSpillSlot(MF, RS);
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 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::GPRCRegClass.contains(Reg)) {
HasGPSaveArea = true;
GPRegs.push_back(CSI[i]);
if (Reg < MinGPR) {
MinGPR = Reg;
}
} else if (PPC::G8RCRegClass.contains(Reg)) {
HasG8SaveArea = true;
G8Regs.push_back(CSI[i]);
if (Reg < MinG8R) {
MinG8R = Reg;
}
} else if (PPC::F8RCRegClass.contains(Reg)) {
HasFPSaveArea = true;
FPRegs.push_back(CSI[i]);
if (Reg < MinFPR) {
MinFPR = Reg;
}
} else if (PPC::CRBITRCRegClass.contains(Reg) ||
PPC::CRRCRegClass.contains(Reg)) {
; } else if (PPC::VRSAVERCRegClass.contains(Reg)) {
HasVRSAVESaveArea = true;
} else if (PPC::VRRCRegClass.contains(Reg)) {
HasVRSaveArea = true;
VRegs.push_back(CSI[i]);
if (Reg < MinVR) {
MinVR = Reg;
}
} else {
llvm_unreachable("Unknown RegisterClass!");
}
}
PPCFunctionInfo *PFI = MF.getInfo<PPCFunctionInfo>();
const TargetRegisterInfo *TRI = MF.getTarget().getRegisterInfo();
int64_t LowerBound = 0;
int TCSPDelta = 0;
if (MF.getTarget().Options.GuaranteedTailCallOpt &&
(TCSPDelta = PFI->getTailCallSPDelta()) < 0) {
LowerBound = TCSPDelta;
}
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 - TRI->getEncodingValue(MinFPR) + 1) * 8;
}
if (needsFP(MF)) {
HasGPSaveArea = true;
int FI = PFI->getFramePointerSaveIndex();
assert(FI && "No Frame Pointer Save Slot!");
FFI->setObjectOffset(FI, LowerBound + FFI->getObjectOffset(FI));
}
const PPCRegisterInfo *RegInfo =
static_cast<const PPCRegisterInfo*>(MF.getTarget().getRegisterInfo());
if (RegInfo->hasBasePointer(MF)) {
HasGPSaveArea = true;
int FI = PFI->getBasePointerSaveIndex();
assert(FI && "No Base Pointer Save Slot!");
FFI->setObjectOffset(FI, LowerBound + FFI->getObjectOffset(FI));
}
if (HasGPSaveArea || HasG8SaveArea) {
for (unsigned i = 0, e = GPRegs.size(); i != e; ++i) {
int FI = GPRegs[i].getFrameIdx();
FFI->setObjectOffset(FI, LowerBound + FFI->getObjectOffset(FI));
}
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>(TRI->getEncodingValue(MinGPR),
TRI->getEncodingValue(MinG8R));
if (Subtarget.isPPC64()) {
LowerBound -= (31 - MinReg + 1) * 8;
} else {
LowerBound -= (31 - MinReg + 1) * 4;
}
}
if (spillsCR(MF) && !(Subtarget.isPPC64() && Subtarget.isSVR4ABI())) {
for (unsigned i = 0, e = CSI.size(); i != e; ++i) {
unsigned Reg = CSI[i].getReg();
if ((Subtarget.isSVR4ABI() && Reg == PPC::CR2)
|| (!Subtarget.isSVR4ABI() &&
(PPC::CRBITRCRegClass.contains(Reg) ||
PPC::CRRCRegClass.contains(Reg)))) {
int FI = CSI[i].getFrameIdx();
FFI->setObjectOffset(FI, LowerBound + FFI->getObjectOffset(FI));
}
}
LowerBound -= 4; }
if (HasVRSAVESaveArea) {
for (unsigned i = 0, e = CSI.size(); i != e; ++i) {
unsigned Reg = CSI[i].getReg();
if (PPC::VRSAVERCRegClass.contains(Reg)) {
int FI = CSI[i].getFrameIdx();
FFI->setObjectOffset(FI, LowerBound + FFI->getObjectOffset(FI));
}
}
LowerBound -= 4; }
if (HasVRSaveArea) {
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));
}
}
addScavengingSpillSlot(MF, RS);
}
void
PPCFrameLowering::addScavengingSpillSlot(MachineFunction &MF,
RegScavenger *RS) const {
unsigned StackSize = determineFrameLayout(MF, false, true);
MachineFrameInfo *MFI = MF.getFrameInfo();
if (MFI->hasVarSizedObjects() || spillsCR(MF) || spillsVRSAVE(MF) ||
hasNonRISpills(MF) || (hasSpills(MF) && !isInt<16>(StackSize))) {
const TargetRegisterClass *GPRC = &PPC::GPRCRegClass;
const TargetRegisterClass *G8RC = &PPC::G8RCRegClass;
const TargetRegisterClass *RC = Subtarget.isPPC64() ? G8RC : GPRC;
RS->addScavengingFrameIndex(MFI->CreateStackObject(RC->getSize(),
RC->getAlignment(),
false));
bool HasAlVars = MFI->hasVarSizedObjects() &&
MFI->getMaxAlignment() > getStackAlignment();
if (spillsCR(MF) || spillsVRSAVE(MF) || HasAlVars)
RS->addScavengingFrameIndex(MFI->CreateStackObject(RC->getSize(),
RC->getAlignment(),
false));
}
}
bool
PPCFrameLowering::spillCalleeSavedRegisters(MachineBasicBlock &MBB,
MachineBasicBlock::iterator MI,
const std::vector<CalleeSavedInfo> &CSI,
const TargetRegisterInfo *TRI) const {
if (!Subtarget.isSVR4ABI())
return false;
MachineFunction *MF = MBB.getParent();
const PPCInstrInfo &TII =
*static_cast<const PPCInstrInfo*>(MF->getTarget().getInstrInfo());
DebugLoc DL;
bool CRSpilled = false;
MachineInstrBuilder CRMIB;
for (unsigned i = 0, e = CSI.size(); i != e; ++i) {
unsigned Reg = CSI[i].getReg();
if (Reg == PPC::VRSAVE && !Subtarget.isDarwinABI())
continue;
bool IsCRField = PPC::CR2 <= Reg && Reg <= PPC::CR4;
MBB.addLiveIn(Reg);
if (CRSpilled && IsCRField) {
CRMIB.addReg(Reg, RegState::ImplicitKill);
continue;
}
if (IsCRField) {
PPCFunctionInfo *FuncInfo = MF->getInfo<PPCFunctionInfo>();
if (Subtarget.isPPC64()) {
FuncInfo->addMustSaveCR(Reg);
} else {
CRSpilled = true;
FuncInfo->setSpillsCR();
CRMIB = BuildMI(*MF, DL, TII.get(PPC::MFCR), PPC::R12)
.addReg(Reg, RegState::ImplicitKill);
MBB.insert(MI, CRMIB);
MBB.insert(MI, addFrameReference(BuildMI(*MF, DL, TII.get(PPC::STW))
.addReg(PPC::R12,
getKillRegState(true)),
CSI[i].getFrameIdx()));
}
} else {
const TargetRegisterClass *RC = TRI->getMinimalPhysRegClass(Reg);
TII.storeRegToStackSlot(MBB, MI, Reg, true,
CSI[i].getFrameIdx(), RC, TRI);
}
}
return true;
}
static void
restoreCRs(bool isPPC64, bool is31,
bool CR2Spilled, bool CR3Spilled, bool CR4Spilled,
MachineBasicBlock &MBB, MachineBasicBlock::iterator MI,
const std::vector<CalleeSavedInfo> &CSI, unsigned CSIIndex) {
MachineFunction *MF = MBB.getParent();
const PPCInstrInfo &TII =
*static_cast<const PPCInstrInfo*>(MF->getTarget().getInstrInfo());
DebugLoc DL;
unsigned RestoreOp, MoveReg;
if (isPPC64)
return;
else {
MBB.insert(MI, addFrameReference(BuildMI(*MF, DL, TII.get(PPC::LWZ),
PPC::R12),
CSI[CSIIndex].getFrameIdx()));
RestoreOp = PPC::MTOCRF;
MoveReg = PPC::R12;
}
if (CR2Spilled)
MBB.insert(MI, BuildMI(*MF, DL, TII.get(RestoreOp), PPC::CR2)
.addReg(MoveReg, getKillRegState(!CR3Spilled && !CR4Spilled)));
if (CR3Spilled)
MBB.insert(MI, BuildMI(*MF, DL, TII.get(RestoreOp), PPC::CR3)
.addReg(MoveReg, getKillRegState(!CR4Spilled)));
if (CR4Spilled)
MBB.insert(MI, BuildMI(*MF, DL, TII.get(RestoreOp), PPC::CR4)
.addReg(MoveReg, getKillRegState(true)));
}
void PPCFrameLowering::
eliminateCallFramePseudoInstr(MachineFunction &MF, MachineBasicBlock &MBB,
MachineBasicBlock::iterator I) const {
const PPCInstrInfo &TII =
*static_cast<const PPCInstrInfo*>(MF.getTarget().getInstrInfo());
if (MF.getTarget().Options.GuaranteedTailCallOpt &&
I->getOpcode() == PPC::ADJCALLSTACKUP) {
if (int CalleeAmt = I->getOperand(1).getImm()) {
bool is64Bit = Subtarget.isPPC64();
CalleeAmt *= -1;
unsigned StackReg = is64Bit ? PPC::X1 : PPC::R1;
unsigned TmpReg = is64Bit ? PPC::X0 : PPC::R0;
unsigned ADDIInstr = is64Bit ? PPC::ADDI8 : PPC::ADDI;
unsigned ADDInstr = is64Bit ? PPC::ADD8 : PPC::ADD4;
unsigned LISInstr = is64Bit ? PPC::LIS8 : PPC::LIS;
unsigned ORIInstr = is64Bit ? PPC::ORI8 : PPC::ORI;
MachineInstr *MI = I;
DebugLoc dl = MI->getDebugLoc();
if (isInt<16>(CalleeAmt)) {
BuildMI(MBB, I, dl, TII.get(ADDIInstr), StackReg)
.addReg(StackReg, RegState::Kill)
.addImm(CalleeAmt);
} else {
MachineBasicBlock::iterator MBBI = I;
BuildMI(MBB, MBBI, dl, TII.get(LISInstr), TmpReg)
.addImm(CalleeAmt >> 16);
BuildMI(MBB, MBBI, dl, TII.get(ORIInstr), TmpReg)
.addReg(TmpReg, RegState::Kill)
.addImm(CalleeAmt & 0xFFFF);
BuildMI(MBB, MBBI, dl, TII.get(ADDInstr), StackReg)
.addReg(StackReg, RegState::Kill)
.addReg(TmpReg);
}
}
}
MBB.erase(I);
}
bool
PPCFrameLowering::restoreCalleeSavedRegisters(MachineBasicBlock &MBB,
MachineBasicBlock::iterator MI,
const std::vector<CalleeSavedInfo> &CSI,
const TargetRegisterInfo *TRI) const {
if (!Subtarget.isSVR4ABI())
return false;
MachineFunction *MF = MBB.getParent();
const PPCInstrInfo &TII =
*static_cast<const PPCInstrInfo*>(MF->getTarget().getInstrInfo());
bool CR2Spilled = false;
bool CR3Spilled = false;
bool CR4Spilled = false;
unsigned CSIIndex = 0;
MachineBasicBlock::iterator I = MI, BeforeI = I;
bool AtStart = I == MBB.begin();
if (!AtStart)
--BeforeI;
for (unsigned i = 0, e = CSI.size(); i != e; ++i) {
unsigned Reg = CSI[i].getReg();
if (Reg == PPC::VRSAVE && !Subtarget.isDarwinABI())
continue;
if (Reg == PPC::CR2) {
CR2Spilled = true;
CSIIndex = i;
continue;
} else if (Reg == PPC::CR3) {
CR3Spilled = true;
continue;
} else if (Reg == PPC::CR4) {
CR4Spilled = true;
continue;
} else {
if ((CR2Spilled || CR3Spilled || CR4Spilled)
&& !(PPC::CR2 <= Reg && Reg <= PPC::CR4)) {
bool is31 = needsFP(*MF);
restoreCRs(Subtarget.isPPC64(), is31,
CR2Spilled, CR3Spilled, CR4Spilled,
MBB, I, CSI, CSIIndex);
CR2Spilled = CR3Spilled = CR4Spilled = false;
}
const TargetRegisterClass *RC = TRI->getMinimalPhysRegClass(Reg);
TII.loadRegFromStackSlot(MBB, I, Reg, CSI[i].getFrameIdx(),
RC, TRI);
assert(I != MBB.begin() &&
"loadRegFromStackSlot didn't insert any code!");
}
if (AtStart)
I = MBB.begin();
else {
I = BeforeI;
++I;
}
}
if (CR2Spilled || CR3Spilled || CR4Spilled) {
bool is31 = needsFP(*MF);
restoreCRs(Subtarget.isPPC64(), is31, CR2Spilled, CR3Spilled, CR4Spilled,
MBB, I, CSI, CSIIndex);
}
return true;
}