[llvm] 99e0066 - [PowerPC] Fix return address computation for "__builtin_return_address"

Victor Huang via llvm-commits llvm-commits at lists.llvm.org
Thu Aug 12 08:15:25 PDT 2021


Author: Victor Huang
Date: 2021-08-12T09:44:49-05:00
New Revision: 99e00663d4cd13b0c296380147ef3f53a2172fbf

URL: https://github.com/llvm/llvm-project/commit/99e00663d4cd13b0c296380147ef3f53a2172fbf
DIFF: https://github.com/llvm/llvm-project/commit/99e00663d4cd13b0c296380147ef3f53a2172fbf.diff

LOG: [PowerPC] Fix return address computation for "__builtin_return_address"

When depth > 0, callee frame address is used to compute the return address of
callee producing improper return address. This patch adds the fix to use caller
frame address to compute the return address of callee.

Reviewed By: nemanjai, #powerpc

Differential revision: https://reviews.llvm.org/D107646

Added: 
    llvm/test/CodeGen/PowerPC/retaddr_multi_levels.ll

Modified: 
    llvm/lib/Target/PowerPC/PPCISelLowering.cpp
    llvm/test/CodeGen/PowerPC/2010-05-03-retaddr1.ll

Removed: 
    


################################################################################
diff  --git a/llvm/lib/Target/PowerPC/PPCISelLowering.cpp b/llvm/lib/Target/PowerPC/PPCISelLowering.cpp
index 37358176f35e6..6d38b39f48238 100644
--- a/llvm/lib/Target/PowerPC/PPCISelLowering.cpp
+++ b/llvm/lib/Target/PowerPC/PPCISelLowering.cpp
@@ -15960,7 +15960,12 @@ SDValue PPCTargetLowering::LowerRETURNADDR(SDValue Op,
   auto PtrVT = getPointerTy(MF.getDataLayout());
 
   if (Depth > 0) {
-    SDValue FrameAddr = LowerFRAMEADDR(Op, DAG);
+    // The link register (return address) is saved in the caller's frame
+    // not the callee's stack frame. So we must get the caller's frame
+    // address and load the return address at the LR offset from there.
+    SDValue FrameAddr =
+        DAG.getLoad(Op.getValueType(), dl, DAG.getEntryNode(),
+                    LowerFRAMEADDR(Op, DAG), MachinePointerInfo());
     SDValue Offset =
         DAG.getConstant(Subtarget.getFrameLowering()->getReturnSaveOffset(), dl,
                         isPPC64 ? MVT::i64 : MVT::i32);

diff  --git a/llvm/test/CodeGen/PowerPC/2010-05-03-retaddr1.ll b/llvm/test/CodeGen/PowerPC/2010-05-03-retaddr1.ll
index 170a82afc77d6..055cd4455866a 100644
--- a/llvm/test/CodeGen/PowerPC/2010-05-03-retaddr1.ll
+++ b/llvm/test/CodeGen/PowerPC/2010-05-03-retaddr1.ll
@@ -23,6 +23,7 @@ define i8* @g() nounwind readnone {
 ; CHECK-NEXT:    stw 0, 4(1)
 ; CHECK-NEXT:    stwu 1, -16(1)
 ; CHECK-NEXT:    lwz 3, 0(1)
+; CHECK-NEXT:    lwz 3, 0(3)
 ; CHECK-NEXT:    lwz 3, 4(3)
 ; CHECK-NEXT:    lwz 0, 20(1)
 ; CHECK-NEXT:    addi 1, 1, 16

diff  --git a/llvm/test/CodeGen/PowerPC/retaddr_multi_levels.ll b/llvm/test/CodeGen/PowerPC/retaddr_multi_levels.ll
new file mode 100644
index 0000000000000..7e55f05f1df97
--- /dev/null
+++ b/llvm/test/CodeGen/PowerPC/retaddr_multi_levels.ll
@@ -0,0 +1,140 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
+; RUN: llc -verify-machineinstrs < %s -mtriple=powerpc64le-unknown-linux \
+; RUN:   -mcpu=pwr8 | FileCheck %s -check-prefix=CHECK-64B-LE
+; RUN: llc -verify-machineinstrs < %s -mtriple=powerpc64-unknown-linux \
+; RUN:   -mcpu=pwr7 | FileCheck %s -check-prefix=CHECK-64B-BE
+; RUN: llc -verify-machineinstrs < %s -mtriple=powerpc64-unknown-aix \
+; RUN:   -mcpu=pwr7 | FileCheck %s -check-prefix=CHECK-64B-BE
+; RUN: llc -verify-machineinstrs < %s -mtriple=powerpc-unknown-aix \
+; RUN:   -mcpu=pwr7 | FileCheck %s -check-prefix=CHECK-32B-BE
+
+declare i8* @llvm.returnaddress(i32) nounwind readnone
+
+define i8* @test0() nounwind readnone {
+; CHECK-64B-LE-LABEL: test0:
+; CHECK-64B-LE:       # %bb.0: # %entry
+; CHECK-64B-LE-NEXT:    mflr 0
+; CHECK-64B-LE-NEXT:    std 0, 16(1)
+; CHECK-64B-LE-NEXT:    stdu 1, -32(1)
+; CHECK-64B-LE-NEXT:    ld 3, 48(1)
+; CHECK-64B-LE-NEXT:    addi 1, 1, 32
+; CHECK-64B-LE-NEXT:    ld 0, 16(1)
+; CHECK-64B-LE-NEXT:    mtlr 0
+; CHECK-64B-LE-NEXT:    blr
+;
+; CHECK-64B-BE-LABEL: test0:
+; CHECK-64B-BE:       # %bb.0: # %entry
+; CHECK-64B-BE-NEXT:    mflr 0
+; CHECK-64B-BE-NEXT:    std 0, 16(1)
+; CHECK-64B-BE-NEXT:    stdu 1, -48(1)
+; CHECK-64B-BE-NEXT:    ld 3, 64(1)
+; CHECK-64B-BE-NEXT:    addi 1, 1, 48
+; CHECK-64B-BE-NEXT:    ld 0, 16(1)
+; CHECK-64B-BE-NEXT:    mtlr 0
+; CHECK-64B-BE-NEXT:    blr
+;
+; CHECK-32B-BE-LABEL: test0:
+; CHECK-32B-BE:       # %bb.0: # %entry
+; CHECK-32B-BE-NEXT:    mflr 0
+; CHECK-32B-BE-NEXT:    stw 0, 8(1)
+; CHECK-32B-BE-NEXT:    stwu 1, -32(1)
+; CHECK-32B-BE-NEXT:    lwz 3, 40(1)
+; CHECK-32B-BE-NEXT:    addi 1, 1, 32
+; CHECK-32B-BE-NEXT:    lwz 0, 8(1)
+; CHECK-32B-BE-NEXT:    mtlr 0
+; CHECK-32B-BE-NEXT:    blr
+entry:
+  %0 = tail call i8* @llvm.returnaddress(i32 0);
+  ret i8* %0
+}
+
+define i8* @test1() nounwind readnone {
+; CHECK-64B-LE-LABEL: test1:
+; CHECK-64B-LE:       # %bb.0: # %entry
+; CHECK-64B-LE-NEXT:    mflr 0
+; CHECK-64B-LE-NEXT:    std 0, 16(1)
+; CHECK-64B-LE-NEXT:    stdu 1, -32(1)
+; CHECK-64B-LE-NEXT:    ld 3, 0(1)
+; CHECK-64B-LE-NEXT:    ld 3, 0(3)
+; CHECK-64B-LE-NEXT:    ld 3, 16(3)
+; CHECK-64B-LE-NEXT:    addi 1, 1, 32
+; CHECK-64B-LE-NEXT:    ld 0, 16(1)
+; CHECK-64B-LE-NEXT:    mtlr 0
+; CHECK-64B-LE-NEXT:    blr
+;
+; CHECK-64B-BE-LABEL: test1:
+; CHECK-64B-BE:       # %bb.0: # %entry
+; CHECK-64B-BE-NEXT:    mflr 0
+; CHECK-64B-BE-NEXT:    std 0, 16(1)
+; CHECK-64B-BE-NEXT:    stdu 1, -48(1)
+; CHECK-64B-BE-NEXT:    ld 3, 0(1)
+; CHECK-64B-BE-NEXT:    ld 3, 0(3)
+; CHECK-64B-BE-NEXT:    ld 3, 16(3)
+; CHECK-64B-BE-NEXT:    addi 1, 1, 48
+; CHECK-64B-BE-NEXT:    ld 0, 16(1)
+; CHECK-64B-BE-NEXT:    mtlr 0
+; CHECK-64B-BE-NEXT:    blr
+;
+; CHECK-32B-BE-LABEL: test1:
+; CHECK-32B-BE:       # %bb.0: # %entry
+; CHECK-32B-BE-NEXT:    mflr 0
+; CHECK-32B-BE-NEXT:    stw 0, 8(1)
+; CHECK-32B-BE-NEXT:    stwu 1, -32(1)
+; CHECK-32B-BE-NEXT:    lwz 3, 0(1)
+; CHECK-32B-BE-NEXT:    lwz 3, 0(3)
+; CHECK-32B-BE-NEXT:    lwz 3, 8(3)
+; CHECK-32B-BE-NEXT:    addi 1, 1, 32
+; CHECK-32B-BE-NEXT:    lwz 0, 8(1)
+; CHECK-32B-BE-NEXT:    mtlr 0
+; CHECK-32B-BE-NEXT:    blr
+entry:
+  %0 = tail call i8* @llvm.returnaddress(i32 1);
+  ret i8* %0
+}
+
+define i8* @test2() nounwind readnone {
+; CHECK-64B-LE-LABEL: test2:
+; CHECK-64B-LE:       # %bb.0: # %entry
+; CHECK-64B-LE-NEXT:    mflr 0
+; CHECK-64B-LE-NEXT:    std 0, 16(1)
+; CHECK-64B-LE-NEXT:    stdu 1, -32(1)
+; CHECK-64B-LE-NEXT:    ld 3, 0(1)
+; CHECK-64B-LE-NEXT:    ld 3, 0(3)
+; CHECK-64B-LE-NEXT:    ld 3, 0(3)
+; CHECK-64B-LE-NEXT:    ld 3, 16(3)
+; CHECK-64B-LE-NEXT:    addi 1, 1, 32
+; CHECK-64B-LE-NEXT:    ld 0, 16(1)
+; CHECK-64B-LE-NEXT:    mtlr 0
+; CHECK-64B-LE-NEXT:    blr
+;
+; CHECK-64B-BE-LABEL: test2:
+; CHECK-64B-BE:       # %bb.0: # %entry
+; CHECK-64B-BE-NEXT:    mflr 0
+; CHECK-64B-BE-NEXT:    std 0, 16(1)
+; CHECK-64B-BE-NEXT:    stdu 1, -48(1)
+; CHECK-64B-BE-NEXT:    ld 3, 0(1)
+; CHECK-64B-BE-NEXT:    ld 3, 0(3)
+; CHECK-64B-BE-NEXT:    ld 3, 0(3)
+; CHECK-64B-BE-NEXT:    ld 3, 16(3)
+; CHECK-64B-BE-NEXT:    addi 1, 1, 48
+; CHECK-64B-BE-NEXT:    ld 0, 16(1)
+; CHECK-64B-BE-NEXT:    mtlr 0
+; CHECK-64B-BE-NEXT:    blr
+;
+; CHECK-32B-BE-LABEL: test2:
+; CHECK-32B-BE:       # %bb.0: # %entry
+; CHECK-32B-BE-NEXT:    mflr 0
+; CHECK-32B-BE-NEXT:    stw 0, 8(1)
+; CHECK-32B-BE-NEXT:    stwu 1, -32(1)
+; CHECK-32B-BE-NEXT:    lwz 3, 0(1)
+; CHECK-32B-BE-NEXT:    lwz 3, 0(3)
+; CHECK-32B-BE-NEXT:    lwz 3, 0(3)
+; CHECK-32B-BE-NEXT:    lwz 3, 8(3)
+; CHECK-32B-BE-NEXT:    addi 1, 1, 32
+; CHECK-32B-BE-NEXT:    lwz 0, 8(1)
+; CHECK-32B-BE-NEXT:    mtlr 0
+; CHECK-32B-BE-NEXT:    blr
+entry:
+  %0 = tail call i8* @llvm.returnaddress(i32 2);
+  ret i8* %0
+}


        


More information about the llvm-commits mailing list