[PowerPC] Make r2 allocatable on PPC64/ELF for some leaf functions

The TOC base pointer is passed in r2, and we normally reserve this register so
that we can depend on it being there. However, for leaf functions, and
specifically those leaf functions that don't do any TOC access of their own
(which is generally due to accessing the constant pool, using TLS, etc.),
we can treat r2 as an ordinary callee-saved register (it must be callee-saved
because, for local direct calls, the linker will not insert any save/restore
code).

The allocation order has been changed slightly for PPC64/ELF systems to put r2
at the end of the list (while leaving it near the beginning for Darwin systems
to prevent unnecessary output changes). While r2 is allocatable, using it still
requires spill/restore traffic, and thus comes at the end of the list.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@227745 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Hal Finkel
2015-02-01 15:03:28 +00:00
parent 8931c49efa
commit 8f5c829c1e
9 changed files with 183 additions and 19 deletions

View File

@@ -224,9 +224,12 @@ def CSR_SVR464 : CalleeSavedRegs<(add X14, X15, X16, X17, X18, X19, X20,
F27, F28, F29, F30, F31, CR2, CR3, CR4 F27, F28, F29, F30, F31, CR2, CR3, CR4
)>; )>;
def CSR_SVR464_Altivec : CalleeSavedRegs<(add CSR_SVR464, CSR_Altivec)>; def CSR_SVR464_Altivec : CalleeSavedRegs<(add CSR_SVR464, CSR_Altivec)>;
def CSR_SVR464_R2 : CalleeSavedRegs<(add CSR_SVR464, X2)>;
def CSR_SVR464_R2_Altivec : CalleeSavedRegs<(add CSR_SVR464_Altivec, X2)>;
def CSR_NoRegs : CalleeSavedRegs<(add)>; def CSR_NoRegs : CalleeSavedRegs<(add)>;
def CSR_64_AllRegs: CalleeSavedRegs<(add X0, (sequence "X%u", 3, 10), def CSR_64_AllRegs: CalleeSavedRegs<(add X0, (sequence "X%u", 3, 10),

View File

@@ -17,6 +17,7 @@
#include "MCTargetDesc/PPCPredicates.h" #include "MCTargetDesc/PPCPredicates.h"
#include "PPCCallingConv.h" #include "PPCCallingConv.h"
#include "PPCISelLowering.h" #include "PPCISelLowering.h"
#include "PPCMachineFunctionInfo.h"
#include "PPCSubtarget.h" #include "PPCSubtarget.h"
#include "PPCTargetMachine.h" #include "PPCTargetMachine.h"
#include "llvm/ADT/Optional.h" #include "llvm/ADT/Optional.h"
@@ -86,6 +87,7 @@ class PPCFastISel final : public FastISel {
const TargetMachine &TM; const TargetMachine &TM;
const PPCSubtarget *PPCSubTarget; const PPCSubtarget *PPCSubTarget;
PPCFunctionInfo *PPCFuncInfo;
const TargetInstrInfo &TII; const TargetInstrInfo &TII;
const TargetLowering &TLI; const TargetLowering &TLI;
LLVMContext *Context; LLVMContext *Context;
@@ -95,6 +97,7 @@ class PPCFastISel final : public FastISel {
const TargetLibraryInfo *LibInfo) const TargetLibraryInfo *LibInfo)
: FastISel(FuncInfo, LibInfo), TM(FuncInfo.MF->getTarget()), : FastISel(FuncInfo, LibInfo), TM(FuncInfo.MF->getTarget()),
PPCSubTarget(&FuncInfo.MF->getSubtarget<PPCSubtarget>()), PPCSubTarget(&FuncInfo.MF->getSubtarget<PPCSubtarget>()),
PPCFuncInfo(FuncInfo.MF->getInfo<PPCFunctionInfo>()),
TII(*PPCSubTarget->getInstrInfo()), TII(*PPCSubTarget->getInstrInfo()),
TLI(*PPCSubTarget->getTargetLowering()), TLI(*PPCSubTarget->getTargetLowering()),
Context(&FuncInfo.Fn->getContext()) {} Context(&FuncInfo.Fn->getContext()) {}
@@ -1526,6 +1529,7 @@ bool PPCFastISel::fastLowerCall(CallLoweringInfo &CLI) {
// Direct calls, in both the ELF V1 and V2 ABIs, need the TOC register live // Direct calls, in both the ELF V1 and V2 ABIs, need the TOC register live
// into the call. // into the call.
PPCFuncInfo->setUsesTOCBasePtr();
MIB.addReg(PPC::X2, RegState::Implicit); MIB.addReg(PPC::X2, RegState::Implicit);
// Add a register mask with the call-preserved registers. Proper // Add a register mask with the call-preserved registers. Proper
@@ -1864,6 +1868,7 @@ unsigned PPCFastISel::PPCMaterializeFP(const ConstantFP *CFP, MVT VT) {
unsigned Opc = (VT == MVT::f32) ? PPC::LFS : PPC::LFD; unsigned Opc = (VT == MVT::f32) ? PPC::LFS : PPC::LFD;
unsigned TmpReg = createResultReg(&PPC::G8RC_and_G8RC_NOX0RegClass); unsigned TmpReg = createResultReg(&PPC::G8RC_and_G8RC_NOX0RegClass);
PPCFuncInfo->setUsesTOCBasePtr();
// For small code model, generate a LF[SD](0, LDtocCPT(Idx, X2)). // For small code model, generate a LF[SD](0, LDtocCPT(Idx, X2)).
if (CModel == CodeModel::Small || CModel == CodeModel::JITDefault) { if (CModel == CodeModel::Small || CModel == CodeModel::JITDefault) {
BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(PPC::LDtocCPT), BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(PPC::LDtocCPT),
@@ -1913,6 +1918,7 @@ unsigned PPCFastISel::PPCMaterializeGV(const GlobalValue *GV, MVT VT) {
if (GV->isThreadLocal()) if (GV->isThreadLocal())
return 0; return 0;
PPCFuncInfo->setUsesTOCBasePtr();
// For small code model, generate a simple TOC load. // For small code model, generate a simple TOC load.
if (CModel == CodeModel::Small || CModel == CodeModel::JITDefault) if (CModel == CodeModel::Small || CModel == CodeModel::JITDefault)
BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(PPC::LDtoc), BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(PPC::LDtoc),

View File

@@ -1590,6 +1590,15 @@ static SDValue LowerLabelRef(SDValue HiPart, SDValue LoPart, bool isPIC,
return DAG.getNode(ISD::ADD, DL, PtrVT, Hi, Lo); return DAG.getNode(ISD::ADD, DL, PtrVT, Hi, Lo);
} }
static void setUsesTOCBasePtr(MachineFunction &MF) {
PPCFunctionInfo *FuncInfo = MF.getInfo<PPCFunctionInfo>();
FuncInfo->setUsesTOCBasePtr();
}
static void setUsesTOCBasePtr(SelectionDAG &DAG) {
setUsesTOCBasePtr(DAG.getMachineFunction());
}
SDValue PPCTargetLowering::LowerConstantPool(SDValue Op, SDValue PPCTargetLowering::LowerConstantPool(SDValue Op,
SelectionDAG &DAG) const { SelectionDAG &DAG) const {
EVT PtrVT = Op.getValueType(); EVT PtrVT = Op.getValueType();
@@ -1599,6 +1608,7 @@ SDValue PPCTargetLowering::LowerConstantPool(SDValue Op,
// 64-bit SVR4 ABI code is always position-independent. // 64-bit SVR4 ABI code is always position-independent.
// The actual address of the GlobalValue is stored in the TOC. // The actual address of the GlobalValue is stored in the TOC.
if (Subtarget.isSVR4ABI() && Subtarget.isPPC64()) { if (Subtarget.isSVR4ABI() && Subtarget.isPPC64()) {
setUsesTOCBasePtr(DAG);
SDValue GA = DAG.getTargetConstantPool(C, PtrVT, CP->getAlignment(), 0); SDValue GA = DAG.getTargetConstantPool(C, PtrVT, CP->getAlignment(), 0);
return DAG.getNode(PPCISD::TOC_ENTRY, SDLoc(CP), MVT::i64, GA, return DAG.getNode(PPCISD::TOC_ENTRY, SDLoc(CP), MVT::i64, GA,
DAG.getRegister(PPC::X2, MVT::i64)); DAG.getRegister(PPC::X2, MVT::i64));
@@ -1630,6 +1640,7 @@ SDValue PPCTargetLowering::LowerJumpTable(SDValue Op, SelectionDAG &DAG) const {
// 64-bit SVR4 ABI code is always position-independent. // 64-bit SVR4 ABI code is always position-independent.
// The actual address of the GlobalValue is stored in the TOC. // The actual address of the GlobalValue is stored in the TOC.
if (Subtarget.isSVR4ABI() && Subtarget.isPPC64()) { if (Subtarget.isSVR4ABI() && Subtarget.isPPC64()) {
setUsesTOCBasePtr(DAG);
SDValue GA = DAG.getTargetJumpTable(JT->getIndex(), PtrVT); SDValue GA = DAG.getTargetJumpTable(JT->getIndex(), PtrVT);
return DAG.getNode(PPCISD::TOC_ENTRY, SDLoc(JT), MVT::i64, GA, return DAG.getNode(PPCISD::TOC_ENTRY, SDLoc(JT), MVT::i64, GA,
DAG.getRegister(PPC::X2, MVT::i64)); DAG.getRegister(PPC::X2, MVT::i64));
@@ -1661,6 +1672,7 @@ SDValue PPCTargetLowering::LowerBlockAddress(SDValue Op,
// 64-bit SVR4 ABI code is always position-independent. // 64-bit SVR4 ABI code is always position-independent.
// The actual BlockAddress is stored in the TOC. // The actual BlockAddress is stored in the TOC.
if (Subtarget.isSVR4ABI() && Subtarget.isPPC64()) { if (Subtarget.isSVR4ABI() && Subtarget.isPPC64()) {
setUsesTOCBasePtr(DAG);
SDValue GA = DAG.getTargetBlockAddress(BA, PtrVT, BASDN->getOffset()); SDValue GA = DAG.getTargetBlockAddress(BA, PtrVT, BASDN->getOffset());
return DAG.getNode(PPCISD::TOC_ENTRY, SDLoc(BASDN), MVT::i64, GA, return DAG.getNode(PPCISD::TOC_ENTRY, SDLoc(BASDN), MVT::i64, GA,
DAG.getRegister(PPC::X2, MVT::i64)); DAG.getRegister(PPC::X2, MVT::i64));
@@ -1729,6 +1741,7 @@ SDValue PPCTargetLowering::LowerGlobalTLSAddress(SDValue Op,
PPCII::MO_TLS); PPCII::MO_TLS);
SDValue GOTPtr; SDValue GOTPtr;
if (is64bit) { if (is64bit) {
setUsesTOCBasePtr(DAG);
SDValue GOTReg = DAG.getRegister(PPC::X2, MVT::i64); SDValue GOTReg = DAG.getRegister(PPC::X2, MVT::i64);
GOTPtr = DAG.getNode(PPCISD::ADDIS_GOT_TPREL_HA, dl, GOTPtr = DAG.getNode(PPCISD::ADDIS_GOT_TPREL_HA, dl,
PtrVT, GOTReg, TGA); PtrVT, GOTReg, TGA);
@@ -1744,6 +1757,7 @@ SDValue PPCTargetLowering::LowerGlobalTLSAddress(SDValue Op,
PPCII::MO_TLSGD); PPCII::MO_TLSGD);
SDValue GOTPtr; SDValue GOTPtr;
if (is64bit) { if (is64bit) {
setUsesTOCBasePtr(DAG);
SDValue GOTReg = DAG.getRegister(PPC::X2, MVT::i64); SDValue GOTReg = DAG.getRegister(PPC::X2, MVT::i64);
GOTPtr = DAG.getNode(PPCISD::ADDIS_TLSGD_HA, dl, PtrVT, GOTPtr = DAG.getNode(PPCISD::ADDIS_TLSGD_HA, dl, PtrVT,
GOTReg, TGA); GOTReg, TGA);
@@ -1764,6 +1778,7 @@ SDValue PPCTargetLowering::LowerGlobalTLSAddress(SDValue Op,
PPCII::MO_TLSLD); PPCII::MO_TLSLD);
SDValue GOTPtr; SDValue GOTPtr;
if (is64bit) { if (is64bit) {
setUsesTOCBasePtr(DAG);
SDValue GOTReg = DAG.getRegister(PPC::X2, MVT::i64); SDValue GOTReg = DAG.getRegister(PPC::X2, MVT::i64);
GOTPtr = DAG.getNode(PPCISD::ADDIS_TLSLD_HA, dl, PtrVT, GOTPtr = DAG.getNode(PPCISD::ADDIS_TLSLD_HA, dl, PtrVT,
GOTReg, TGA); GOTReg, TGA);
@@ -1796,6 +1811,7 @@ SDValue PPCTargetLowering::LowerGlobalAddress(SDValue Op,
// 64-bit SVR4 ABI code is always position-independent. // 64-bit SVR4 ABI code is always position-independent.
// The actual address of the GlobalValue is stored in the TOC. // The actual address of the GlobalValue is stored in the TOC.
if (Subtarget.isSVR4ABI() && Subtarget.isPPC64()) { if (Subtarget.isSVR4ABI() && Subtarget.isPPC64()) {
setUsesTOCBasePtr(DAG);
SDValue GA = DAG.getTargetGlobalAddress(GV, DL, PtrVT, GSDN->getOffset()); SDValue GA = DAG.getTargetGlobalAddress(GV, DL, PtrVT, GSDN->getOffset());
return DAG.getNode(PPCISD::TOC_ENTRY, DL, MVT::i64, GA, return DAG.getNode(PPCISD::TOC_ENTRY, DL, MVT::i64, GA,
DAG.getRegister(PPC::X2, MVT::i64)); DAG.getRegister(PPC::X2, MVT::i64));
@@ -3763,6 +3779,7 @@ unsigned PrepareCall(SelectionDAG &DAG, SDValue &Callee, SDValue &InFlag,
MPI.getWithOffset(8), false, false, MPI.getWithOffset(8), false, false,
LoadsInv, 8); LoadsInv, 8);
setUsesTOCBasePtr(DAG);
SDValue TOCVal = DAG.getCopyToReg(Chain, dl, PPC::X2, TOCPtr, SDValue TOCVal = DAG.getCopyToReg(Chain, dl, PPC::X2, TOCPtr,
InFlag); InFlag);
Chain = TOCVal.getValue(0); Chain = TOCVal.getValue(0);
@@ -3831,8 +3848,10 @@ unsigned PrepareCall(SelectionDAG &DAG, SDValue &Callee, SDValue &InFlag,
// All calls, in both the ELF V1 and V2 ABIs, need the TOC register live // All calls, in both the ELF V1 and V2 ABIs, need the TOC register live
// into the call. // into the call.
if (isSVR4ABI && isPPC64 && !IsPatchPoint) if (isSVR4ABI && isPPC64 && !IsPatchPoint) {
setUsesTOCBasePtr(DAG);
Ops.push_back(DAG.getRegister(PPC::X2, PtrVT)); Ops.push_back(DAG.getRegister(PPC::X2, PtrVT));
}
return CallOpc; return CallOpc;
} }
@@ -4794,6 +4813,7 @@ PPCTargetLowering::LowerCall_64SVR4(SDValue Chain, SDValue Callee,
!isFunctionGlobalAddress(Callee) && !isFunctionGlobalAddress(Callee) &&
!isa<ExternalSymbolSDNode>(Callee)) { !isa<ExternalSymbolSDNode>(Callee)) {
// Load r2 into a virtual register and store it to the TOC save area. // Load r2 into a virtual register and store it to the TOC save area.
setUsesTOCBasePtr(DAG);
SDValue Val = DAG.getCopyFromReg(Chain, dl, PPC::X2, MVT::i64); SDValue Val = DAG.getCopyFromReg(Chain, dl, PPC::X2, MVT::i64);
// TOC save area offset. // TOC save area offset.
unsigned TOCSaveOffset = PPCFrameLowering::getTOCSaveOffset(isELFv2ABI); unsigned TOCSaveOffset = PPCFrameLowering::getTOCSaveOffset(isELFv2ABI);
@@ -7190,6 +7210,7 @@ PPCTargetLowering::emitEHSjLjSetJmp(MachineInstr *MI,
unsigned BufReg = MI->getOperand(1).getReg(); unsigned BufReg = MI->getOperand(1).getReg();
if (Subtarget.isPPC64() && Subtarget.isSVR4ABI()) { if (Subtarget.isPPC64() && Subtarget.isSVR4ABI()) {
setUsesTOCBasePtr(*MBB->getParent());
MIB = BuildMI(*thisMBB, MI, DL, TII->get(PPC::STD)) MIB = BuildMI(*thisMBB, MI, DL, TII->get(PPC::STD))
.addReg(PPC::X2) .addReg(PPC::X2)
.addImm(TOCOffset) .addImm(TOCOffset)
@@ -7353,6 +7374,7 @@ PPCTargetLowering::emitEHSjLjLongJmp(MachineInstr *MI,
// Reload TOC // Reload TOC
if (PVT == MVT::i64 && Subtarget.isSVR4ABI()) { if (PVT == MVT::i64 && Subtarget.isSVR4ABI()) {
setUsesTOCBasePtr(*MBB->getParent());
MIB = BuildMI(*MBB, MI, DL, TII->get(PPC::LD), PPC::X2) MIB = BuildMI(*MBB, MI, DL, TII->get(PPC::LD), PPC::X2)
.addImm(TOCOffset) .addImm(TOCOffset)
.addReg(BufReg); .addReg(BufReg);
@@ -7381,6 +7403,7 @@ PPCTargetLowering::EmitInstrWithCustomInserter(MachineInstr *MI,
// way to mark the dependence as implicit there, and so the stackmap code // way to mark the dependence as implicit there, and so the stackmap code
// will confuse it with a regular operand. Instead, add the dependence // will confuse it with a regular operand. Instead, add the dependence
// here. // here.
setUsesTOCBasePtr(*BB->getParent());
MI->addOperand(MachineOperand::CreateReg(PPC::X2, false, true)); MI->addOperand(MachineOperand::CreateReg(PPC::X2, false, true));
} }
@@ -9769,7 +9792,7 @@ unsigned PPCTargetLowering::getRegisterByName(const char* RegName,
bool is64Bit = isPPC64 && VT == MVT::i64; bool is64Bit = isPPC64 && VT == MVT::i64;
unsigned Reg = StringSwitch<unsigned>(RegName) unsigned Reg = StringSwitch<unsigned>(RegName)
.Case("r1", is64Bit ? PPC::X1 : PPC::R1) .Case("r1", is64Bit ? PPC::X1 : PPC::R1)
.Case("r2", isDarwinABI ? 0 : (is64Bit ? PPC::X2 : PPC::R2)) .Case("r2", (isDarwinABI || isPPC64) ? 0 : PPC::R2)
.Case("r13", (!isPPC64 && isDarwinABI) ? 0 : .Case("r13", (!isPPC64 && isDarwinABI) ? 0 :
(is64Bit ? PPC::X13 : PPC::R13)) (is64Bit ? PPC::X13 : PPC::R13))
.Default(0); .Default(0);

View File

@@ -62,6 +62,9 @@ class PPCFunctionInfo : public MachineFunctionInfo {
/// entry, even though LR may otherwise apparently not be used. /// entry, even though LR may otherwise apparently not be used.
bool LRStoreRequired; bool LRStoreRequired;
/// This function makes use of the PPC64 ELF TOC base pointer (register r2).
bool UsesTOCBasePtr;
/// MinReservedArea - This is the frame size that is at least reserved in a /// MinReservedArea - This is the frame size that is at least reserved in a
/// potential caller (parameter+linkage area). /// potential caller (parameter+linkage area).
unsigned MinReservedArea; unsigned MinReservedArea;
@@ -112,6 +115,7 @@ public:
SpillsCR(false), SpillsCR(false),
SpillsVRSAVE(false), SpillsVRSAVE(false),
LRStoreRequired(false), LRStoreRequired(false),
UsesTOCBasePtr(false),
MinReservedArea(0), MinReservedArea(0),
TailCallSPDelta(0), TailCallSPDelta(0),
HasFastCall(false), HasFastCall(false),
@@ -164,6 +168,9 @@ public:
void setLRStoreRequired() { LRStoreRequired = true; } void setLRStoreRequired() { LRStoreRequired = true; }
bool isLRStoreRequired() const { return LRStoreRequired; } bool isLRStoreRequired() const { return LRStoreRequired; }
void setUsesTOCBasePtr() { UsesTOCBasePtr = true; }
bool usesTOCBasePtr() const { return UsesTOCBasePtr; }
void setHasFastCall() { HasFastCall = true; } void setHasFastCall() { HasFastCall = true; }
bool hasFastCall() const { return HasFastCall;} bool hasFastCall() const { return HasFastCall;}

View File

@@ -115,9 +115,14 @@ PPCRegisterInfo::getCalleeSavedRegs(const MachineFunction *MF) const {
CSR_Darwin32_Altivec_SaveList : CSR_Darwin32_Altivec_SaveList :
CSR_Darwin32_SaveList); CSR_Darwin32_SaveList);
// On PPC64, we might need to save r2 (but only if it is not reserved).
bool SaveR2 = MF->getRegInfo().isAllocatable(PPC::X2);
return Subtarget.isPPC64() ? (Subtarget.hasAltivec() ? return Subtarget.isPPC64() ? (Subtarget.hasAltivec() ?
CSR_SVR464_Altivec_SaveList : (SaveR2 ? CSR_SVR464_R2_Altivec_SaveList :
CSR_SVR464_SaveList) : CSR_SVR464_Altivec_SaveList) :
(SaveR2 ? CSR_SVR464_R2_SaveList :
CSR_SVR464_SaveList)) :
(Subtarget.hasAltivec() ? (Subtarget.hasAltivec() ?
CSR_SVR432_Altivec_SaveList : CSR_SVR432_Altivec_SaveList :
CSR_SVR432_SaveList); CSR_SVR432_SaveList);
@@ -216,7 +221,16 @@ BitVector PPCRegisterInfo::getReservedRegs(const MachineFunction &MF) const {
// The 64-bit SVR4 ABI reserves r2 for the TOC pointer. // The 64-bit SVR4 ABI reserves r2 for the TOC pointer.
if (Subtarget.isSVR4ABI()) { if (Subtarget.isSVR4ABI()) {
Reserved.set(PPC::X2); // We only reserve r2 if we need to use the TOC pointer. If we have no
// explicit uses of the TOC pointer (meaning we're a leaf function with
// no constant-pool loads, etc.) and we have no potential uses inside an
// inline asm block, then we can treat r2 has an ordinary callee-saved
// register.
const PPCFunctionInfo *FuncInfo = MF.getInfo<PPCFunctionInfo>();
if (FuncInfo->usesTOCBasePtr() || MF.hasInlineAsm())
Reserved.set(PPC::X2);
else
Reserved.reset(PPC::R2);
} }
} }

View File

@@ -219,17 +219,50 @@ def RM: PPCReg<"**ROUNDING MODE**">;
// then nonvolatiles in reverse order since stmw/lmw save from rN to r31 // then nonvolatiles in reverse order since stmw/lmw save from rN to r31
def GPRC : RegisterClass<"PPC", [i32], 32, (add (sequence "R%u", 2, 12), def GPRC : RegisterClass<"PPC", [i32], 32, (add (sequence "R%u", 2, 12),
(sequence "R%u", 30, 13), (sequence "R%u", 30, 13),
R31, R0, R1, FP, BP)>; R31, R0, R1, FP, BP)> {
// On non-Darwin PPC64 systems, R2 can be allocated, but must be restored, so
// put it at the end of the list.
let AltOrders = [(add (sub GPRC, R2), R2)];
let AltOrderSelect = [{
const PPCSubtarget &S = MF.getTarget().getSubtarget<PPCSubtarget>();
return S.isPPC64() && S.isSVR4ABI();
}];
}
def G8RC : RegisterClass<"PPC", [i64], 64, (add (sequence "X%u", 2, 12), def G8RC : RegisterClass<"PPC", [i64], 64, (add (sequence "X%u", 2, 12),
(sequence "X%u", 30, 14), (sequence "X%u", 30, 14),
X31, X13, X0, X1, FP8, BP8)>; X31, X13, X0, X1, FP8, BP8)> {
// On non-Darwin PPC64 systems, R2 can be allocated, but must be restored, so
// put it at the end of the list.
let AltOrders = [(add (sub G8RC, X2), X2)];
let AltOrderSelect = [{
const PPCSubtarget &S = MF.getTarget().getSubtarget<PPCSubtarget>();
return S.isPPC64() && S.isSVR4ABI();
}];
}
// For some instructions r0 is special (representing the value 0 instead of // For some instructions r0 is special (representing the value 0 instead of
// the value in the r0 register), and we use these register subclasses to // the value in the r0 register), and we use these register subclasses to
// prevent r0 from being allocated for use by those instructions. // prevent r0 from being allocated for use by those instructions.
def GPRC_NOR0 : RegisterClass<"PPC", [i32], 32, (add (sub GPRC, R0), ZERO)>; def GPRC_NOR0 : RegisterClass<"PPC", [i32], 32, (add (sub GPRC, R0), ZERO)> {
def G8RC_NOX0 : RegisterClass<"PPC", [i64], 64, (add (sub G8RC, X0), ZERO8)>; // On non-Darwin PPC64 systems, R2 can be allocated, but must be restored, so
// put it at the end of the list.
let AltOrders = [(add (sub GPRC_NOR0, R2), R2)];
let AltOrderSelect = [{
const PPCSubtarget &S = MF.getTarget().getSubtarget<PPCSubtarget>();
return S.isPPC64() && S.isSVR4ABI();
}];
}
def G8RC_NOX0 : RegisterClass<"PPC", [i64], 64, (add (sub G8RC, X0), ZERO8)> {
// On non-Darwin PPC64 systems, R2 can be allocated, but must be restored, so
// put it at the end of the list.
let AltOrders = [(add (sub G8RC_NOX0, X2), X2)];
let AltOrderSelect = [{
const PPCSubtarget &S = MF.getTarget().getSubtarget<PPCSubtarget>();
return S.isPPC64() && S.isSVR4ABI();
}];
}
// Allocate volatiles first, then non-volatiles in reverse order. With the SVR4 // Allocate volatiles first, then non-volatiles in reverse order. With the SVR4
// ABI the size of the Floating-point register save area is determined by the // ABI the size of the Floating-point register save area is determined by the

View File

@@ -1,15 +1,12 @@
; RUN: not llc < %s -mtriple=powerpc64-apple-darwin 2>&1 | FileCheck %s --check-prefix=CHECK-DARWIN ; RUN: not llc < %s -mtriple=powerpc64-apple-darwin 2>&1 | FileCheck %s
; RUN: llc < %s -mtriple=powerpc64-unknown-linux-gnu 2>&1 | FileCheck %s ; RUN: not llc < %s -mtriple=powerpc64-unknown-linux-gnu 2>&1 | FileCheck %s
define i64 @get_reg() nounwind { define i64 @get_reg() nounwind {
entry: entry:
; FIXME: Include an allocatable-specific error message ; FIXME: Include an allocatable-specific error message
; CHECK-DARWIN: Invalid register name global variable ; CHECK: Invalid register name global variable
%reg = call i64 @llvm.read_register.i64(metadata !0) %reg = call i64 @llvm.read_register.i64(metadata !0)
ret i64 %reg ret i64 %reg
; CHECK-LABEL: @get_reg
; CHECK: mr 3, 2
} }
declare i64 @llvm.read_register.i64(metadata) nounwind declare i64 @llvm.read_register.i64(metadata) nounwind

View File

@@ -1,11 +1,11 @@
; RUN: not llc < %s -mtriple=powerpc-apple-darwin 2>&1 | FileCheck %s --check-prefix=CHECK-DARWIN ; RUN: not llc < %s -mtriple=powerpc-apple-darwin 2>&1 | FileCheck %s --check-prefix=CHECK-NOTPPC32
; RUN: llc < %s -mtriple=powerpc-unknown-linux-gnu 2>&1 | FileCheck %s ; RUN: llc < %s -mtriple=powerpc-unknown-linux-gnu 2>&1 | FileCheck %s
; RUN: llc < %s -mtriple=powerpc64-unknown-linux-gnu 2>&1 | FileCheck %s ; RUN: not llc < %s -mtriple=powerpc64-unknown-linux-gnu 2>&1 | FileCheck %s --check-prefix=CHECK-NOTPPC32
define i32 @get_reg() nounwind { define i32 @get_reg() nounwind {
entry: entry:
; FIXME: Include an allocatable-specific error message ; FIXME: Include an allocatable-specific error message
; CHECK-DARWIN: Invalid register name global variable ; CHECK-NOTPPC32: Invalid register name global variable
%reg = call i32 @llvm.read_register.i32(metadata !0) %reg = call i32 @llvm.read_register.i32(metadata !0)
ret i32 %reg ret i32 %reg

View File

@@ -0,0 +1,81 @@
; RUN: llc -mcpu=pwr7 < %s | FileCheck %s
target datalayout = "E-m:e-i64:64-n32:64"
target triple = "powerpc64-unknown-linux-gnu"
define signext i32 @foo(i32 signext %a, i32 signext %d) #0 {
entry:
%div = sdiv i32 %a, %d
%div1 = sdiv i32 %div, %d
%div2 = sdiv i32 %div1, %d
%div3 = sdiv i32 %div2, %d
%div4 = sdiv i32 %div3, %d
%div5 = sdiv i32 %div4, %d
%div6 = sdiv i32 %div5, %d
%div7 = sdiv i32 %div6, %d
%div8 = sdiv i32 %div7, %d
%div9 = sdiv i32 %div8, %d
%div10 = sdiv i32 %div9, %d
%div11 = sdiv i32 %div10, %d
%div12 = sdiv i32 %div11, %d
%div13 = sdiv i32 %div12, %d
%div14 = sdiv i32 %div13, %d
%div15 = sdiv i32 %div14, %d
%div16 = sdiv i32 %div15, %d
%div17 = sdiv i32 %div16, %d
%div18 = sdiv i32 %div17, %d
%div19 = sdiv i32 %div18, %d
%div20 = sdiv i32 %div19, %d
%div21 = sdiv i32 %div20, %d
%div22 = sdiv i32 %div21, %d
%div23 = sdiv i32 %div22, %d
%div24 = sdiv i32 %div23, %d
%div25 = sdiv i32 %div24, %d
%div26 = sdiv i32 %div25, %d
%div27 = sdiv i32 %div26, %d
%div28 = sdiv i32 %div27, %d
%div29 = sdiv i32 %div28, %d
%div30 = sdiv i32 %div29, %d
%div31 = sdiv i32 %div30, %d
%div32 = sdiv i32 %div31, %d
%div33 = sdiv i32 %div32, %div31
%div34 = sdiv i32 %div33, %div30
%div35 = sdiv i32 %div34, %div29
%div36 = sdiv i32 %div35, %div28
%div37 = sdiv i32 %div36, %div27
%div38 = sdiv i32 %div37, %div26
%div39 = sdiv i32 %div38, %div25
%div40 = sdiv i32 %div39, %div24
%div41 = sdiv i32 %div40, %div23
%div42 = sdiv i32 %div41, %div22
%div43 = sdiv i32 %div42, %div21
%div44 = sdiv i32 %div43, %div20
%div45 = sdiv i32 %div44, %div19
%div46 = sdiv i32 %div45, %div18
%div47 = sdiv i32 %div46, %div17
%div48 = sdiv i32 %div47, %div16
%div49 = sdiv i32 %div48, %div15
%div50 = sdiv i32 %div49, %div14
%div51 = sdiv i32 %div50, %div13
%div52 = sdiv i32 %div51, %div12
%div53 = sdiv i32 %div52, %div11
%div54 = sdiv i32 %div53, %div10
%div55 = sdiv i32 %div54, %div9
%div56 = sdiv i32 %div55, %div8
%div57 = sdiv i32 %div56, %div7
%div58 = sdiv i32 %div57, %div6
%div59 = sdiv i32 %div58, %div5
%div60 = sdiv i32 %div59, %div4
%div61 = sdiv i32 %div60, %div3
%div62 = sdiv i32 %div61, %div2
%div63 = sdiv i32 %div62, %div1
%div64 = sdiv i32 %div63, %div
ret i32 %div64
}
; This function will need to use all non-reserved GPRs (and then some), make
; sure that r2 is among them.
; CHECK-LABEL: @foo
; CHECK: std 2,
; CHECK: ld 2,
; CHECK: blr