diff --git a/lib/Target/PowerPC/PPCCallingConv.td b/lib/Target/PowerPC/PPCCallingConv.td index 56176f14533..3eaec6ba54d 100644 --- a/lib/Target/PowerPC/PPCCallingConv.td +++ b/lib/Target/PowerPC/PPCCallingConv.td @@ -224,9 +224,12 @@ def CSR_SVR464 : CalleeSavedRegs<(add X14, X15, X16, X17, X18, X19, X20, F27, F28, F29, F30, F31, CR2, CR3, CR4 )>; - 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_64_AllRegs: CalleeSavedRegs<(add X0, (sequence "X%u", 3, 10), diff --git a/lib/Target/PowerPC/PPCFastISel.cpp b/lib/Target/PowerPC/PPCFastISel.cpp index 44a3924f479..a929efa42cb 100644 --- a/lib/Target/PowerPC/PPCFastISel.cpp +++ b/lib/Target/PowerPC/PPCFastISel.cpp @@ -17,6 +17,7 @@ #include "MCTargetDesc/PPCPredicates.h" #include "PPCCallingConv.h" #include "PPCISelLowering.h" +#include "PPCMachineFunctionInfo.h" #include "PPCSubtarget.h" #include "PPCTargetMachine.h" #include "llvm/ADT/Optional.h" @@ -86,6 +87,7 @@ class PPCFastISel final : public FastISel { const TargetMachine &TM; const PPCSubtarget *PPCSubTarget; + PPCFunctionInfo *PPCFuncInfo; const TargetInstrInfo &TII; const TargetLowering &TLI; LLVMContext *Context; @@ -95,6 +97,7 @@ class PPCFastISel final : public FastISel { const TargetLibraryInfo *LibInfo) : FastISel(FuncInfo, LibInfo), TM(FuncInfo.MF->getTarget()), PPCSubTarget(&FuncInfo.MF->getSubtarget()), + PPCFuncInfo(FuncInfo.MF->getInfo()), TII(*PPCSubTarget->getInstrInfo()), TLI(*PPCSubTarget->getTargetLowering()), 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 // into the call. + PPCFuncInfo->setUsesTOCBasePtr(); MIB.addReg(PPC::X2, RegState::Implicit); // 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 TmpReg = createResultReg(&PPC::G8RC_and_G8RC_NOX0RegClass); + PPCFuncInfo->setUsesTOCBasePtr(); // For small code model, generate a LF[SD](0, LDtocCPT(Idx, X2)). if (CModel == CodeModel::Small || CModel == CodeModel::JITDefault) { 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()) return 0; + PPCFuncInfo->setUsesTOCBasePtr(); // For small code model, generate a simple TOC load. if (CModel == CodeModel::Small || CModel == CodeModel::JITDefault) BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(PPC::LDtoc), diff --git a/lib/Target/PowerPC/PPCISelLowering.cpp b/lib/Target/PowerPC/PPCISelLowering.cpp index df2437c0211..b4416148571 100644 --- a/lib/Target/PowerPC/PPCISelLowering.cpp +++ b/lib/Target/PowerPC/PPCISelLowering.cpp @@ -1590,6 +1590,15 @@ static SDValue LowerLabelRef(SDValue HiPart, SDValue LoPart, bool isPIC, return DAG.getNode(ISD::ADD, DL, PtrVT, Hi, Lo); } +static void setUsesTOCBasePtr(MachineFunction &MF) { + PPCFunctionInfo *FuncInfo = MF.getInfo(); + FuncInfo->setUsesTOCBasePtr(); +} + +static void setUsesTOCBasePtr(SelectionDAG &DAG) { + setUsesTOCBasePtr(DAG.getMachineFunction()); +} + SDValue PPCTargetLowering::LowerConstantPool(SDValue Op, SelectionDAG &DAG) const { EVT PtrVT = Op.getValueType(); @@ -1599,6 +1608,7 @@ SDValue PPCTargetLowering::LowerConstantPool(SDValue Op, // 64-bit SVR4 ABI code is always position-independent. // The actual address of the GlobalValue is stored in the TOC. if (Subtarget.isSVR4ABI() && Subtarget.isPPC64()) { + setUsesTOCBasePtr(DAG); SDValue GA = DAG.getTargetConstantPool(C, PtrVT, CP->getAlignment(), 0); return DAG.getNode(PPCISD::TOC_ENTRY, SDLoc(CP), MVT::i64, GA, 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. // The actual address of the GlobalValue is stored in the TOC. if (Subtarget.isSVR4ABI() && Subtarget.isPPC64()) { + setUsesTOCBasePtr(DAG); SDValue GA = DAG.getTargetJumpTable(JT->getIndex(), PtrVT); return DAG.getNode(PPCISD::TOC_ENTRY, SDLoc(JT), MVT::i64, GA, DAG.getRegister(PPC::X2, MVT::i64)); @@ -1661,6 +1672,7 @@ SDValue PPCTargetLowering::LowerBlockAddress(SDValue Op, // 64-bit SVR4 ABI code is always position-independent. // The actual BlockAddress is stored in the TOC. if (Subtarget.isSVR4ABI() && Subtarget.isPPC64()) { + setUsesTOCBasePtr(DAG); SDValue GA = DAG.getTargetBlockAddress(BA, PtrVT, BASDN->getOffset()); return DAG.getNode(PPCISD::TOC_ENTRY, SDLoc(BASDN), MVT::i64, GA, DAG.getRegister(PPC::X2, MVT::i64)); @@ -1729,6 +1741,7 @@ SDValue PPCTargetLowering::LowerGlobalTLSAddress(SDValue Op, PPCII::MO_TLS); SDValue GOTPtr; if (is64bit) { + setUsesTOCBasePtr(DAG); SDValue GOTReg = DAG.getRegister(PPC::X2, MVT::i64); GOTPtr = DAG.getNode(PPCISD::ADDIS_GOT_TPREL_HA, dl, PtrVT, GOTReg, TGA); @@ -1744,6 +1757,7 @@ SDValue PPCTargetLowering::LowerGlobalTLSAddress(SDValue Op, PPCII::MO_TLSGD); SDValue GOTPtr; if (is64bit) { + setUsesTOCBasePtr(DAG); SDValue GOTReg = DAG.getRegister(PPC::X2, MVT::i64); GOTPtr = DAG.getNode(PPCISD::ADDIS_TLSGD_HA, dl, PtrVT, GOTReg, TGA); @@ -1764,6 +1778,7 @@ SDValue PPCTargetLowering::LowerGlobalTLSAddress(SDValue Op, PPCII::MO_TLSLD); SDValue GOTPtr; if (is64bit) { + setUsesTOCBasePtr(DAG); SDValue GOTReg = DAG.getRegister(PPC::X2, MVT::i64); GOTPtr = DAG.getNode(PPCISD::ADDIS_TLSLD_HA, dl, PtrVT, GOTReg, TGA); @@ -1796,6 +1811,7 @@ SDValue PPCTargetLowering::LowerGlobalAddress(SDValue Op, // 64-bit SVR4 ABI code is always position-independent. // The actual address of the GlobalValue is stored in the TOC. if (Subtarget.isSVR4ABI() && Subtarget.isPPC64()) { + setUsesTOCBasePtr(DAG); SDValue GA = DAG.getTargetGlobalAddress(GV, DL, PtrVT, GSDN->getOffset()); return DAG.getNode(PPCISD::TOC_ENTRY, DL, MVT::i64, GA, DAG.getRegister(PPC::X2, MVT::i64)); @@ -3763,6 +3779,7 @@ unsigned PrepareCall(SelectionDAG &DAG, SDValue &Callee, SDValue &InFlag, MPI.getWithOffset(8), false, false, LoadsInv, 8); + setUsesTOCBasePtr(DAG); SDValue TOCVal = DAG.getCopyToReg(Chain, dl, PPC::X2, TOCPtr, InFlag); 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 // into the call. - if (isSVR4ABI && isPPC64 && !IsPatchPoint) + if (isSVR4ABI && isPPC64 && !IsPatchPoint) { + setUsesTOCBasePtr(DAG); Ops.push_back(DAG.getRegister(PPC::X2, PtrVT)); + } return CallOpc; } @@ -4794,6 +4813,7 @@ PPCTargetLowering::LowerCall_64SVR4(SDValue Chain, SDValue Callee, !isFunctionGlobalAddress(Callee) && !isa(Callee)) { // 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); // TOC save area offset. unsigned TOCSaveOffset = PPCFrameLowering::getTOCSaveOffset(isELFv2ABI); @@ -7190,6 +7210,7 @@ PPCTargetLowering::emitEHSjLjSetJmp(MachineInstr *MI, unsigned BufReg = MI->getOperand(1).getReg(); if (Subtarget.isPPC64() && Subtarget.isSVR4ABI()) { + setUsesTOCBasePtr(*MBB->getParent()); MIB = BuildMI(*thisMBB, MI, DL, TII->get(PPC::STD)) .addReg(PPC::X2) .addImm(TOCOffset) @@ -7353,6 +7374,7 @@ PPCTargetLowering::emitEHSjLjLongJmp(MachineInstr *MI, // Reload TOC if (PVT == MVT::i64 && Subtarget.isSVR4ABI()) { + setUsesTOCBasePtr(*MBB->getParent()); MIB = BuildMI(*MBB, MI, DL, TII->get(PPC::LD), PPC::X2) .addImm(TOCOffset) .addReg(BufReg); @@ -7381,6 +7403,7 @@ PPCTargetLowering::EmitInstrWithCustomInserter(MachineInstr *MI, // way to mark the dependence as implicit there, and so the stackmap code // will confuse it with a regular operand. Instead, add the dependence // here. + setUsesTOCBasePtr(*BB->getParent()); MI->addOperand(MachineOperand::CreateReg(PPC::X2, false, true)); } @@ -9769,7 +9792,7 @@ unsigned PPCTargetLowering::getRegisterByName(const char* RegName, bool is64Bit = isPPC64 && VT == MVT::i64; unsigned Reg = StringSwitch(RegName) .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 : (is64Bit ? PPC::X13 : PPC::R13)) .Default(0); diff --git a/lib/Target/PowerPC/PPCMachineFunctionInfo.h b/lib/Target/PowerPC/PPCMachineFunctionInfo.h index 37b2ff83c45..607cdf612ee 100644 --- a/lib/Target/PowerPC/PPCMachineFunctionInfo.h +++ b/lib/Target/PowerPC/PPCMachineFunctionInfo.h @@ -62,6 +62,9 @@ class PPCFunctionInfo : public MachineFunctionInfo { /// entry, even though LR may otherwise apparently not be used. 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 /// potential caller (parameter+linkage area). unsigned MinReservedArea; @@ -112,6 +115,7 @@ public: SpillsCR(false), SpillsVRSAVE(false), LRStoreRequired(false), + UsesTOCBasePtr(false), MinReservedArea(0), TailCallSPDelta(0), HasFastCall(false), @@ -164,6 +168,9 @@ public: void setLRStoreRequired() { LRStoreRequired = true; } bool isLRStoreRequired() const { return LRStoreRequired; } + void setUsesTOCBasePtr() { UsesTOCBasePtr = true; } + bool usesTOCBasePtr() const { return UsesTOCBasePtr; } + void setHasFastCall() { HasFastCall = true; } bool hasFastCall() const { return HasFastCall;} diff --git a/lib/Target/PowerPC/PPCRegisterInfo.cpp b/lib/Target/PowerPC/PPCRegisterInfo.cpp index 2645b1cc3a7..b0b20a037f2 100644 --- a/lib/Target/PowerPC/PPCRegisterInfo.cpp +++ b/lib/Target/PowerPC/PPCRegisterInfo.cpp @@ -115,9 +115,14 @@ PPCRegisterInfo::getCalleeSavedRegs(const MachineFunction *MF) const { CSR_Darwin32_Altivec_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() ? - CSR_SVR464_Altivec_SaveList : - CSR_SVR464_SaveList) : + (SaveR2 ? CSR_SVR464_R2_Altivec_SaveList : + CSR_SVR464_Altivec_SaveList) : + (SaveR2 ? CSR_SVR464_R2_SaveList : + CSR_SVR464_SaveList)) : (Subtarget.hasAltivec() ? CSR_SVR432_Altivec_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. 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(); + if (FuncInfo->usesTOCBasePtr() || MF.hasInlineAsm()) + Reserved.set(PPC::X2); + else + Reserved.reset(PPC::R2); } } diff --git a/lib/Target/PowerPC/PPCRegisterInfo.td b/lib/Target/PowerPC/PPCRegisterInfo.td index 2fdf04eaaee..a495ae04899 100644 --- a/lib/Target/PowerPC/PPCRegisterInfo.td +++ b/lib/Target/PowerPC/PPCRegisterInfo.td @@ -219,17 +219,50 @@ def RM: PPCReg<"**ROUNDING MODE**">; // 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), (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(); + return S.isPPC64() && S.isSVR4ABI(); + }]; +} def G8RC : RegisterClass<"PPC", [i64], 64, (add (sequence "X%u", 2, 12), (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(); + return S.isPPC64() && S.isSVR4ABI(); + }]; +} // 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 // prevent r0 from being allocated for use by those instructions. -def GPRC_NOR0 : RegisterClass<"PPC", [i32], 32, (add (sub GPRC, R0), ZERO)>; -def G8RC_NOX0 : RegisterClass<"PPC", [i64], 64, (add (sub G8RC, X0), ZERO8)>; +def GPRC_NOR0 : RegisterClass<"PPC", [i32], 32, (add (sub GPRC, R0), ZERO)> { + // 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(); + 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(); + return S.isPPC64() && S.isSVR4ABI(); + }]; +} // 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 diff --git a/test/CodeGen/PowerPC/named-reg-alloc-r2-64.ll b/test/CodeGen/PowerPC/named-reg-alloc-r2-64.ll index d4ed05b9e50..834df8b4d91 100644 --- a/test/CodeGen/PowerPC/named-reg-alloc-r2-64.ll +++ b/test/CodeGen/PowerPC/named-reg-alloc-r2-64.ll @@ -1,15 +1,12 @@ -; RUN: not llc < %s -mtriple=powerpc64-apple-darwin 2>&1 | FileCheck %s --check-prefix=CHECK-DARWIN -; RUN: llc < %s -mtriple=powerpc64-unknown-linux-gnu 2>&1 | FileCheck %s +; RUN: not llc < %s -mtriple=powerpc64-apple-darwin 2>&1 | FileCheck %s +; RUN: not llc < %s -mtriple=powerpc64-unknown-linux-gnu 2>&1 | FileCheck %s define i64 @get_reg() nounwind { entry: ; 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) ret i64 %reg - -; CHECK-LABEL: @get_reg -; CHECK: mr 3, 2 } declare i64 @llvm.read_register.i64(metadata) nounwind diff --git a/test/CodeGen/PowerPC/named-reg-alloc-r2.ll b/test/CodeGen/PowerPC/named-reg-alloc-r2.ll index 262d034e16b..45d9816793c 100644 --- a/test/CodeGen/PowerPC/named-reg-alloc-r2.ll +++ b/test/CodeGen/PowerPC/named-reg-alloc-r2.ll @@ -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=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 { entry: ; 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) ret i32 %reg diff --git a/test/CodeGen/PowerPC/ppc64-r2-alloc.ll b/test/CodeGen/PowerPC/ppc64-r2-alloc.ll new file mode 100644 index 00000000000..87292d82129 --- /dev/null +++ b/test/CodeGen/PowerPC/ppc64-r2-alloc.ll @@ -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 +