[PATCH] D77749: [PowerPC][Future] Remove redundant r2 save and restore for indirect call

Victor Huang via Phabricator via llvm-commits llvm-commits at lists.llvm.org
Wed Apr 8 12:30:33 PDT 2020


NeHuang created this revision.
NeHuang added reviewers: nemanjai, stefanp, lei, hfinkel, power-llvm-team.
NeHuang added projects: LLVM, PowerPC.
Herald added subscribers: llvm-commits, shchenz, kbarton, hiraditya.

Currently an indirect call produces the following sequence on PCRelative mode:

  extern void function( );
  extern void (*ptrfunc) ( );
  
  void g() {
    ptrfunc=function;
  }
  
  void f() {
    (*ptrfunc) ( );
  }

Produce

  	paddi 3, 0, .LC0 at PCREL, 1
  	ld 3, 0(3)
  	std 2, 24(1)
  	ld 12, 0(3)
  	mtctr 12
  	bctrl
  	ld 2, 24(1)

Though the caller does not use or preserve r2, it is still saved and restored across a function call.  
This patch is added to remove these redundant save and restores for indirect call.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D77749

Files:
  llvm/lib/Target/PowerPC/PPCISelLowering.cpp
  llvm/test/CodeGen/PowerPC/pcrel-got-indirect.ll


Index: llvm/test/CodeGen/PowerPC/pcrel-got-indirect.ll
===================================================================
--- llvm/test/CodeGen/PowerPC/pcrel-got-indirect.ll
+++ 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 at 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
Index: llvm/lib/Target/PowerPC/PPCISelLowering.cpp
===================================================================
--- llvm/lib/Target/PowerPC/PPCISelLowering.cpp
+++ 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.


-------------- next part --------------
A non-text attachment was scrubbed...
Name: D77749.256082.patch
Type: text/x-patch
Size: 4638 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20200408/bdfdfc47/attachment.bin>


More information about the llvm-commits mailing list