PPCRegisterInfo.cpp [plain text]
#define DEBUG_TYPE "reginfo"
#include "PPC.h"
#include "PPCInstrBuilder.h"
#include "PPCMachineFunctionInfo.h"
#include "PPCRegisterInfo.h"
#include "PPCFrameLowering.h"
#include "PPCSubtarget.h"
#include "llvm/CallingConv.h"
#include "llvm/Constants.h"
#include "llvm/Function.h"
#include "llvm/Type.h"
#include "llvm/CodeGen/ValueTypes.h"
#include "llvm/CodeGen/MachineInstrBuilder.h"
#include "llvm/CodeGen/MachineModuleInfo.h"
#include "llvm/CodeGen/MachineFunction.h"
#include "llvm/CodeGen/MachineFrameInfo.h"
#include "llvm/CodeGen/MachineRegisterInfo.h"
#include "llvm/CodeGen/RegisterScavenging.h"
#include "llvm/Target/TargetFrameLowering.h"
#include "llvm/Target/TargetInstrInfo.h"
#include "llvm/Target/TargetMachine.h"
#include "llvm/Target/TargetOptions.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/MathExtras.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/ADT/BitVector.h"
#include "llvm/ADT/STLExtras.h"
#include <cstdlib>
#define GET_REGINFO_TARGET_DESC
#include "PPCGenRegisterInfo.inc"
namespace llvm {
cl::opt<bool> DisablePPC32RS("disable-ppc32-regscavenger",
cl::init(false),
cl::desc("Disable PPC32 register scavenger"),
cl::Hidden);
cl::opt<bool> DisablePPC64RS("disable-ppc64-regscavenger",
cl::init(false),
cl::desc("Disable PPC64 register scavenger"),
cl::Hidden);
}
using namespace llvm;
bool
PPCRegisterInfo::requiresRegisterScavenging(const MachineFunction &) const {
return ((!DisablePPC32RS && !Subtarget.isPPC64()) ||
(!DisablePPC64RS && Subtarget.isPPC64()));
}
PPCRegisterInfo::PPCRegisterInfo(const PPCSubtarget &ST,
const TargetInstrInfo &tii)
: PPCGenRegisterInfo(ST.isPPC64() ? PPC::LR8 : PPC::LR,
ST.isPPC64() ? 0 : 1,
ST.isPPC64() ? 0 : 1),
Subtarget(ST), TII(tii) {
ImmToIdxMap[PPC::LD] = PPC::LDX; ImmToIdxMap[PPC::STD] = PPC::STDX;
ImmToIdxMap[PPC::LBZ] = PPC::LBZX; ImmToIdxMap[PPC::STB] = PPC::STBX;
ImmToIdxMap[PPC::LHZ] = PPC::LHZX; ImmToIdxMap[PPC::LHA] = PPC::LHAX;
ImmToIdxMap[PPC::LWZ] = PPC::LWZX; ImmToIdxMap[PPC::LWA] = PPC::LWAX;
ImmToIdxMap[PPC::LFS] = PPC::LFSX; ImmToIdxMap[PPC::LFD] = PPC::LFDX;
ImmToIdxMap[PPC::STH] = PPC::STHX; ImmToIdxMap[PPC::STW] = PPC::STWX;
ImmToIdxMap[PPC::STFS] = PPC::STFSX; ImmToIdxMap[PPC::STFD] = PPC::STFDX;
ImmToIdxMap[PPC::ADDI] = PPC::ADD4;
ImmToIdxMap[PPC::LHA8] = PPC::LHAX8; ImmToIdxMap[PPC::LBZ8] = PPC::LBZX8;
ImmToIdxMap[PPC::LHZ8] = PPC::LHZX8; ImmToIdxMap[PPC::LWZ8] = PPC::LWZX8;
ImmToIdxMap[PPC::STB8] = PPC::STBX8; ImmToIdxMap[PPC::STH8] = PPC::STHX8;
ImmToIdxMap[PPC::STW8] = PPC::STWX8; ImmToIdxMap[PPC::STDU] = PPC::STDUX;
ImmToIdxMap[PPC::ADDI8] = PPC::ADD8; ImmToIdxMap[PPC::STD_32] = PPC::STDX_32;
}
const TargetRegisterClass *
PPCRegisterInfo::getPointerRegClass(unsigned Kind) const {
if (Subtarget.isPPC64())
return &PPC::G8RCRegClass;
return &PPC::GPRCRegClass;
}
const unsigned*
PPCRegisterInfo::getCalleeSavedRegs(const MachineFunction *MF) const {
static const unsigned Darwin32_CalleeSavedRegs[] = {
PPC::R13, PPC::R14, PPC::R15,
PPC::R16, PPC::R17, PPC::R18, PPC::R19,
PPC::R20, PPC::R21, PPC::R22, PPC::R23,
PPC::R24, PPC::R25, PPC::R26, PPC::R27,
PPC::R28, PPC::R29, PPC::R30, PPC::R31,
PPC::F14, PPC::F15, PPC::F16, PPC::F17,
PPC::F18, PPC::F19, PPC::F20, PPC::F21,
PPC::F22, PPC::F23, PPC::F24, PPC::F25,
PPC::F26, PPC::F27, PPC::F28, PPC::F29,
PPC::F30, PPC::F31,
PPC::CR2, PPC::CR3, PPC::CR4,
PPC::V20, PPC::V21, PPC::V22, PPC::V23,
PPC::V24, PPC::V25, PPC::V26, PPC::V27,
PPC::V28, PPC::V29, PPC::V30, PPC::V31,
PPC::LR, 0
};
static const unsigned SVR4_CalleeSavedRegs[] = {
PPC::R14, PPC::R15,
PPC::R16, PPC::R17, PPC::R18, PPC::R19,
PPC::R20, PPC::R21, PPC::R22, PPC::R23,
PPC::R24, PPC::R25, PPC::R26, PPC::R27,
PPC::R28, PPC::R29, PPC::R30, PPC::R31,
PPC::F14, PPC::F15, PPC::F16, PPC::F17,
PPC::F18, PPC::F19, PPC::F20, PPC::F21,
PPC::F22, PPC::F23, PPC::F24, PPC::F25,
PPC::F26, PPC::F27, PPC::F28, PPC::F29,
PPC::F30, PPC::F31,
PPC::CR2, PPC::CR3, PPC::CR4,
PPC::VRSAVE,
PPC::V20, PPC::V21, PPC::V22, PPC::V23,
PPC::V24, PPC::V25, PPC::V26, PPC::V27,
PPC::V28, PPC::V29, PPC::V30, PPC::V31,
0
};
static const unsigned Darwin64_CalleeSavedRegs[] = {
PPC::X14, PPC::X15,
PPC::X16, PPC::X17, PPC::X18, PPC::X19,
PPC::X20, PPC::X21, PPC::X22, PPC::X23,
PPC::X24, PPC::X25, PPC::X26, PPC::X27,
PPC::X28, PPC::X29, PPC::X30, PPC::X31,
PPC::F14, PPC::F15, PPC::F16, PPC::F17,
PPC::F18, PPC::F19, PPC::F20, PPC::F21,
PPC::F22, PPC::F23, PPC::F24, PPC::F25,
PPC::F26, PPC::F27, PPC::F28, PPC::F29,
PPC::F30, PPC::F31,
PPC::CR2, PPC::CR3, PPC::CR4,
PPC::V20, PPC::V21, PPC::V22, PPC::V23,
PPC::V24, PPC::V25, PPC::V26, PPC::V27,
PPC::V28, PPC::V29, PPC::V30, PPC::V31,
PPC::LR8, 0
};
static const unsigned SVR4_64_CalleeSavedRegs[] = {
PPC::X14, PPC::X15,
PPC::X16, PPC::X17, PPC::X18, PPC::X19,
PPC::X20, PPC::X21, PPC::X22, PPC::X23,
PPC::X24, PPC::X25, PPC::X26, PPC::X27,
PPC::X28, PPC::X29, PPC::X30, PPC::X31,
PPC::F14, PPC::F15, PPC::F16, PPC::F17,
PPC::F18, PPC::F19, PPC::F20, PPC::F21,
PPC::F22, PPC::F23, PPC::F24, PPC::F25,
PPC::F26, PPC::F27, PPC::F28, PPC::F29,
PPC::F30, PPC::F31,
PPC::CR2, PPC::CR3, PPC::CR4,
PPC::VRSAVE,
PPC::V20, PPC::V21, PPC::V22, PPC::V23,
PPC::V24, PPC::V25, PPC::V26, PPC::V27,
PPC::V28, PPC::V29, PPC::V30, PPC::V31,
0
};
if (Subtarget.isDarwinABI())
return Subtarget.isPPC64() ? Darwin64_CalleeSavedRegs :
Darwin32_CalleeSavedRegs;
return Subtarget.isPPC64() ? SVR4_64_CalleeSavedRegs : SVR4_CalleeSavedRegs;
}
BitVector PPCRegisterInfo::getReservedRegs(const MachineFunction &MF) const {
BitVector Reserved(getNumRegs());
const PPCFrameLowering *PPCFI =
static_cast<const PPCFrameLowering*>(MF.getTarget().getFrameLowering());
Reserved.set(PPC::R0);
Reserved.set(PPC::R1);
Reserved.set(PPC::LR);
Reserved.set(PPC::LR8);
Reserved.set(PPC::RM);
if (Subtarget.isSVR4ABI()) {
Reserved.set(PPC::R2); Reserved.set(PPC::R13); }
if (Subtarget.isDarwinABI()) {
Reserved.set(PPC::R2);
}
if (Subtarget.isPPC64()) {
Reserved.set(PPC::R13);
Reserved.set(PPC::R31);
Reserved.set(PPC::X0);
Reserved.set(PPC::X1);
Reserved.set(PPC::X13);
Reserved.set(PPC::X31);
if (Subtarget.isSVR4ABI()) {
Reserved.set(PPC::X2);
}
if (Subtarget.isDarwinABI()) {
Reserved.set(PPC::X2);
}
}
if (PPCFI->needsFP(MF))
Reserved.set(PPC::R31);
return Reserved;
}
unsigned
PPCRegisterInfo::getRegPressureLimit(const TargetRegisterClass *RC,
MachineFunction &MF) const {
const TargetFrameLowering *TFI = MF.getTarget().getFrameLowering();
const unsigned DefaultSafety = 1;
switch (RC->getID()) {
default:
return 0;
case PPC::G8RCRegClassID:
case PPC::GPRCRegClassID: {
unsigned FP = TFI->hasFP(MF) ? 1 : 0;
return 32 - FP - DefaultSafety;
}
case PPC::F8RCRegClassID:
case PPC::F4RCRegClassID:
case PPC::VRRCRegClassID:
return 32 - DefaultSafety;
case PPC::CRRCRegClassID:
return 8 - DefaultSafety;
}
}
void PPCRegisterInfo::
eliminateCallFramePseudoInstr(MachineFunction &MF, MachineBasicBlock &MBB,
MachineBasicBlock::iterator I) const {
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);
}
static
unsigned findScratchRegister(MachineBasicBlock::iterator II, RegScavenger *RS,
const TargetRegisterClass *RC, int SPAdj) {
assert(RS && "Register scavenging must be on");
unsigned Reg = RS->FindUnusedReg(RC);
if (Reg == 0)
Reg = RS->scavengeRegister(RC, II, SPAdj);
return Reg;
}
void PPCRegisterInfo::lowerDynamicAlloc(MachineBasicBlock::iterator II,
int SPAdj, RegScavenger *RS) const {
MachineInstr &MI = *II;
MachineBasicBlock &MBB = *MI.getParent();
MachineFunction &MF = *MBB.getParent();
MachineFrameInfo *MFI = MF.getFrameInfo();
bool LP64 = Subtarget.isPPC64();
DebugLoc dl = MI.getDebugLoc();
unsigned maxCallFrameSize = MFI->getMaxCallFrameSize();
unsigned FrameSize = MFI->getStackSize();
unsigned TargetAlign = MF.getTarget().getFrameLowering()->getStackAlignment();
unsigned MaxAlign = MFI->getMaxAlignment();
if (MaxAlign > TargetAlign)
report_fatal_error("Dynamic alloca with large aligns not supported");
const TargetRegisterClass *G8RC = &PPC::G8RCRegClass;
const TargetRegisterClass *GPRC = &PPC::GPRCRegClass;
const TargetRegisterClass *RC = LP64 ? G8RC : GPRC;
unsigned Reg;
if (requiresRegisterScavenging(MF))
Reg = findScratchRegister(II, RS, RC, SPAdj);
else
Reg = PPC::R0;
if (MaxAlign < TargetAlign && isInt<16>(FrameSize)) {
BuildMI(MBB, II, dl, TII.get(PPC::ADDI), Reg)
.addReg(PPC::R31)
.addImm(FrameSize);
} else if (LP64) {
if (requiresRegisterScavenging(MF)) BuildMI(MBB, II, dl, TII.get(PPC::LD), Reg)
.addImm(0)
.addReg(PPC::X1);
else
BuildMI(MBB, II, dl, TII.get(PPC::LD), PPC::X0)
.addImm(0)
.addReg(PPC::X1);
} else {
BuildMI(MBB, II, dl, TII.get(PPC::LWZ), Reg)
.addImm(0)
.addReg(PPC::R1);
}
if (LP64) {
if (requiresRegisterScavenging(MF)) BuildMI(MBB, II, dl, TII.get(PPC::STDUX))
.addReg(Reg, RegState::Kill)
.addReg(PPC::X1, RegState::Define)
.addReg(MI.getOperand(1).getReg());
else
BuildMI(MBB, II, dl, TII.get(PPC::STDUX))
.addReg(PPC::X0, RegState::Kill)
.addReg(PPC::X1, RegState::Define)
.addReg(MI.getOperand(1).getReg());
if (!MI.getOperand(1).isKill())
BuildMI(MBB, II, dl, TII.get(PPC::ADDI8), MI.getOperand(0).getReg())
.addReg(PPC::X1)
.addImm(maxCallFrameSize);
else
BuildMI(MBB, II, dl, TII.get(PPC::ADDI8), MI.getOperand(0).getReg())
.addReg(PPC::X1)
.addImm(maxCallFrameSize)
.addReg(MI.getOperand(1).getReg(), RegState::ImplicitKill);
} else {
BuildMI(MBB, II, dl, TII.get(PPC::STWUX))
.addReg(Reg, RegState::Kill)
.addReg(PPC::R1, RegState::Define)
.addReg(MI.getOperand(1).getReg());
if (!MI.getOperand(1).isKill())
BuildMI(MBB, II, dl, TII.get(PPC::ADDI), MI.getOperand(0).getReg())
.addReg(PPC::R1)
.addImm(maxCallFrameSize);
else
BuildMI(MBB, II, dl, TII.get(PPC::ADDI), MI.getOperand(0).getReg())
.addReg(PPC::R1)
.addImm(maxCallFrameSize)
.addReg(MI.getOperand(1).getReg(), RegState::ImplicitKill);
}
MBB.erase(II);
}
void PPCRegisterInfo::lowerCRSpilling(MachineBasicBlock::iterator II,
unsigned FrameIndex, int SPAdj,
RegScavenger *RS) const {
MachineInstr &MI = *II; MachineBasicBlock &MBB = *MI.getParent();
DebugLoc dl = MI.getDebugLoc();
(void) SPAdj;
(void) RS;
bool LP64 = Subtarget.isPPC64();
unsigned Reg = Subtarget.isDarwinABI() ? (LP64 ? PPC::X2 : PPC::R2) :
(LP64 ? PPC::X0 : PPC::R0);
unsigned SrcReg = MI.getOperand(0).getReg();
BuildMI(MBB, II, dl, TII.get(LP64 ? PPC::MFCR8pseud : PPC::MFCRpseud), Reg)
.addReg(SrcReg, getKillRegState(MI.getOperand(0).isKill()));
if (SrcReg != PPC::CR0)
BuildMI(MBB, II, dl, TII.get(LP64 ? PPC::RLWINM8 : PPC::RLWINM), Reg)
.addReg(Reg, RegState::Kill)
.addImm(getPPCRegisterNumbering(SrcReg) * 4)
.addImm(0)
.addImm(31);
addFrameReference(BuildMI(MBB, II, dl, TII.get(LP64 ? PPC::STW8 : PPC::STW))
.addReg(Reg, getKillRegState(MI.getOperand(1).getImm())),
FrameIndex);
MBB.erase(II);
}
void PPCRegisterInfo::lowerCRRestore(MachineBasicBlock::iterator II,
unsigned FrameIndex, int SPAdj,
RegScavenger *RS) const {
MachineInstr &MI = *II; MachineBasicBlock &MBB = *MI.getParent();
DebugLoc dl = MI.getDebugLoc();
(void) SPAdj;
(void) RS;
bool LP64 = Subtarget.isPPC64();
unsigned Reg = Subtarget.isDarwinABI() ? (LP64 ? PPC::X2 : PPC::R2) :
(LP64 ? PPC::X0 : PPC::R0);
unsigned DestReg = MI.getOperand(0).getReg();
assert(MI.definesRegister(DestReg) &&
"RESTORE_CR does not define its destination");
addFrameReference(BuildMI(MBB, II, dl, TII.get(LP64 ? PPC::LWZ8 : PPC::LWZ),
Reg), FrameIndex);
if (DestReg != PPC::CR0) {
unsigned ShiftBits = getPPCRegisterNumbering(DestReg)*4;
BuildMI(MBB, II, dl, TII.get(LP64 ? PPC::RLWINM8 : PPC::RLWINM), Reg)
.addReg(Reg).addImm(32-ShiftBits).addImm(0)
.addImm(31);
}
BuildMI(MBB, II, dl, TII.get(LP64 ? PPC::MTCRF8 : PPC::MTCRF), DestReg)
.addReg(Reg);
MBB.erase(II);
}
void
PPCRegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II,
int SPAdj, RegScavenger *RS) const {
assert(SPAdj == 0 && "Unexpected");
MachineInstr &MI = *II;
MachineBasicBlock &MBB = *MI.getParent();
MachineFunction &MF = *MBB.getParent();
MachineFrameInfo *MFI = MF.getFrameInfo();
const TargetFrameLowering *TFI = MF.getTarget().getFrameLowering();
DebugLoc dl = MI.getDebugLoc();
unsigned FIOperandNo = 0;
while (!MI.getOperand(FIOperandNo).isFI()) {
++FIOperandNo;
assert(FIOperandNo != MI.getNumOperands() &&
"Instr doesn't have FrameIndex operand!");
}
unsigned OffsetOperandNo = (FIOperandNo == 2) ? 1 : 2;
if (MI.isInlineAsm())
OffsetOperandNo = FIOperandNo-1;
int FrameIndex = MI.getOperand(FIOperandNo).getIndex();
PPCFunctionInfo *FI = MF.getInfo<PPCFunctionInfo>();
int FPSI = FI->getFramePointerSaveIndex();
unsigned OpC = MI.getOpcode();
if (FPSI && FrameIndex == FPSI &&
(OpC == PPC::DYNALLOC || OpC == PPC::DYNALLOC8)) {
lowerDynamicAlloc(II, SPAdj, RS);
return;
}
if (requiresRegisterScavenging(MF)) {
if (OpC == PPC::SPILL_CR) {
lowerCRSpilling(II, FrameIndex, SPAdj, RS);
return;
} else if (OpC == PPC::RESTORE_CR) {
lowerCRRestore(II, FrameIndex, SPAdj, RS);
return;
}
}
bool is64Bit = Subtarget.isPPC64();
MI.getOperand(FIOperandNo).ChangeToRegister(TFI->hasFP(MF) ?
(is64Bit ? PPC::X31 : PPC::R31) :
(is64Bit ? PPC::X1 : PPC::R1),
false);
bool isIXAddr = false;
switch (OpC) {
case PPC::LWA:
case PPC::LD:
case PPC::STD:
case PPC::STD_32:
isIXAddr = true;
break;
}
int Offset = MFI->getObjectOffset(FrameIndex);
if (!isIXAddr)
Offset += MI.getOperand(OffsetOperandNo).getImm();
else
Offset += MI.getOperand(OffsetOperandNo).getImm() << 2;
if (!MF.getFunction()->hasFnAttr(Attribute::Naked))
Offset += MFI->getStackSize();
if (isInt<16>(Offset) && (!isIXAddr || (Offset & 3) == 0)) {
if (isIXAddr)
Offset >>= 2; MI.getOperand(OffsetOperandNo).ChangeToImmediate(Offset);
return;
}
unsigned SReg;
if (requiresRegisterScavenging(MF)) {
const TargetRegisterClass *G8RC = &PPC::G8RCRegClass;
const TargetRegisterClass *GPRC = &PPC::GPRCRegClass;
SReg = findScratchRegister(II, RS, is64Bit ? G8RC : GPRC, SPAdj);
} else
SReg = is64Bit ? PPC::X0 : PPC::R0;
BuildMI(MBB, II, dl, TII.get(is64Bit ? PPC::LIS8 : PPC::LIS), SReg)
.addImm(Offset >> 16);
BuildMI(MBB, II, dl, TII.get(is64Bit ? PPC::ORI8 : PPC::ORI), SReg)
.addReg(SReg, RegState::Kill)
.addImm(Offset);
unsigned OperandBase;
if (OpC != TargetOpcode::INLINEASM) {
assert(ImmToIdxMap.count(OpC) &&
"No indexed form of load or store available!");
unsigned NewOpcode = ImmToIdxMap.find(OpC)->second;
MI.setDesc(TII.get(NewOpcode));
OperandBase = 1;
} else {
OperandBase = OffsetOperandNo;
}
unsigned StackReg = MI.getOperand(FIOperandNo).getReg();
MI.getOperand(OperandBase).ChangeToRegister(StackReg, false);
MI.getOperand(OperandBase + 1).ChangeToRegister(SReg, false, false, true);
}
unsigned PPCRegisterInfo::getFrameRegister(const MachineFunction &MF) const {
const TargetFrameLowering *TFI = MF.getTarget().getFrameLowering();
if (!Subtarget.isPPC64())
return TFI->hasFP(MF) ? PPC::R31 : PPC::R1;
else
return TFI->hasFP(MF) ? PPC::X31 : PPC::X1;
}
unsigned PPCRegisterInfo::getEHExceptionRegister() const {
return !Subtarget.isPPC64() ? PPC::R3 : PPC::X3;
}
unsigned PPCRegisterInfo::getEHHandlerRegister() const {
return !Subtarget.isPPC64() ? PPC::R4 : PPC::X4;
}