diff --git a/llvm/lib/Target/PowerPC/PPCISelLowering.cpp b/llvm/lib/Target/PowerPC/PPCISelLowering.cpp --- a/llvm/lib/Target/PowerPC/PPCISelLowering.cpp +++ b/llvm/lib/Target/PowerPC/PPCISelLowering.cpp @@ -5143,19 +5143,15 @@ // represents the 2 instruction sequence of an indirect branch and link, // immediately followed by a load of the TOC pointer from the the stack save // slot into gpr2. - if (Subtarget.isAIXABI() || Subtarget.is64BitELFABI()) + // For 64-bit ELF ABI PCREL, a indirect call does not need a TOC restore. + if (Subtarget.isAIXABI() || + (Subtarget.is64BitELFABI() && !Subtarget.isUsingPCRelativeCalls())) return PPCISD::BCTRL_LOAD_TOC; // An indirect call that does not need a TOC restore. return PPCISD::BCTRL; } - // FIXME: At this moment indirect calls are treated ahead of the - // PC Relative condition because binaries can still contain a possible - // mix of functions that use a TOC and functions that do not use a TOC. - // Once the PC Relative feature is complete this condition should be moved - // up ahead of the indirect calls and should return a PPCISD::BCTRL for - // that case. if (Subtarget.isUsingPCRelativeCalls()) { assert(Subtarget.is64BitELFABI() && "PC Relative is only on ELF ABI."); return PPCISD::CALL_NOTOC; @@ -5426,7 +5422,9 @@ // pointer from the linkage area. The operand for the TOC restore is an add // of the TOC save offset to the stack pointer. This must be the second // operand: after the chain input but before any other variadic arguments. - if (Subtarget.is64BitELFABI() || Subtarget.isAIXABI()) { + // For 64-bit ELFv2 ABI PCRel, disable the code as TOC is not used. + if ((Subtarget.is64BitELFABI() && !Subtarget.isUsingPCRelativeCalls()) || + Subtarget.isAIXABI()) { const MCRegister StackPtrReg = Subtarget.getStackPointerRegister(); SDValue StackPtr = DAG.getRegister(StackPtrReg, RegVT); @@ -6497,17 +6495,21 @@ // See prepareDescriptorIndirectCall and buildCallOperands for more // information about calls through function pointers in the 64-bit SVR4 ABI. if (CFlags.IsIndirect) { - assert(!CFlags.IsTailCall && "Indirect tails calls not supported"); - // 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 = Subtarget.getFrameLowering()->getTOCSaveOffset(); - SDValue PtrOff = DAG.getIntPtrConstant(TOCSaveOffset, dl); - SDValue AddPtr = DAG.getNode(ISD::ADD, dl, PtrVT, StackPtr, PtrOff); - Chain = DAG.getStore( - Val.getValue(1), dl, Val, AddPtr, - MachinePointerInfo::getStack(DAG.getMachineFunction(), TOCSaveOffset)); + // When PCRel is enabled for 64-bit ELFv2 ABI, do not save the TOC of the + // caller in the TOC save area + if (!Subtarget.isUsingPCRelativeCalls()) { + assert(!CFlags.IsTailCall && "Indirect tails calls not supported"); + // 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 = Subtarget.getFrameLowering()->getTOCSaveOffset(); + SDValue PtrOff = DAG.getIntPtrConstant(TOCSaveOffset, dl); + SDValue AddPtr = DAG.getNode(ISD::ADD, dl, PtrVT, StackPtr, PtrOff); + Chain = DAG.getStore(Val.getValue(1), dl, Val, AddPtr, + MachinePointerInfo::getStack( + DAG.getMachineFunction(), TOCSaveOffset)); + } // In the ELFv2 ABI, R12 must contain the address of an indirect callee. // This does not mean the MTCTR instruction must use R12; it's easier // to model this as an extra parameter, so do that. diff --git a/llvm/test/CodeGen/PowerPC/pcrel-got-indirect.ll b/llvm/test/CodeGen/PowerPC/pcrel-got-indirect.ll --- a/llvm/test/CodeGen/PowerPC/pcrel-got-indirect.ll +++ b/llvm/test/CodeGen/PowerPC/pcrel-got-indirect.ll @@ -219,14 +219,12 @@ ; CHECK-NEXT: mflr r0 ; CHECK-NEXT: std r0, 16(r1) ; CHECK-NEXT: stdu r1, -32(r1) -; CHECK-NEXT: std r2, 24(r1) ; CHECK-NEXT: .cfi_def_cfa_offset 32 ; CHECK-NEXT: .cfi_offset lr, 16 ; CHECK-NEXT: pld r3, ptrfunc@got@pcrel(0), 1 ; CHECK-NEXT: ld r12, 0(r3) ; CHECK-NEXT: mtctr r12 ; CHECK-NEXT: bctrl -; CHECK-NEXT: ld 2, 24(r1) ; CHECK-NEXT: addi r1, r1, 32 ; CHECK-NEXT: ld r0, 16(r1) ; CHECK-NEXT: mtlr r0