[llvm] 0c0f765 - [ARM] Fix llvm.returnaddress for Thumb1 with R11 frame-pointer (#117735)

via llvm-commits llvm-commits at lists.llvm.org
Thu Nov 28 01:38:01 PST 2024


Author: Oliver Stannard
Date: 2024-11-28T09:37:57Z
New Revision: 0c0f765cab4b16eb0342d514584cdf64cabc433a

URL: https://github.com/llvm/llvm-project/commit/0c0f765cab4b16eb0342d514584cdf64cabc433a
DIFF: https://github.com/llvm/llvm-project/commit/0c0f765cab4b16eb0342d514584cdf64cabc433a.diff

LOG: [ARM] Fix llvm.returnaddress for Thumb1 with R11 frame-pointer (#117735)

When the llvm.returnaddress intrinsic is used, the LR is marked as
live-in to the function, so it must be preserved through the prologue.
This is normally fine, but there is one case for Thumb1 where we use LR
as a temporary in the prologue to set up a frame chain using r11 as the
frame pointer. There are no other registers guaranteed to be free to do
this, so we have to re-load LR from the stack after pushing the callee
saved registers.

Added: 
    llvm/test/CodeGen/Thumb/returnaddress.ll

Modified: 
    llvm/lib/Target/ARM/ARMAsmPrinter.cpp
    llvm/lib/Target/ARM/Thumb1FrameLowering.cpp
    llvm/test/CodeGen/Thumb/frame-chain.ll

Removed: 
    


################################################################################
diff  --git a/llvm/lib/Target/ARM/ARMAsmPrinter.cpp b/llvm/lib/Target/ARM/ARMAsmPrinter.cpp
index a119db472fc034..af47d0e176f362 100644
--- a/llvm/lib/Target/ARM/ARMAsmPrinter.cpp
+++ b/llvm/lib/Target/ARM/ARMAsmPrinter.cpp
@@ -1309,6 +1309,10 @@ void ARMAsmPrinter::EmitUnwindingInstruction(const MachineInstr *MI) {
       default:
         MI->print(errs());
         llvm_unreachable("Unsupported opcode for unwinding information");
+      case ARM::tLDRspi:
+        // Used to restore LR in a prologue which uses it as a temporary, has
+        // no effect on unwind tables.
+        return;
       case ARM::MOVr:
       case ARM::tMOVr:
         Offset = 0;

diff  --git a/llvm/lib/Target/ARM/Thumb1FrameLowering.cpp b/llvm/lib/Target/ARM/Thumb1FrameLowering.cpp
index 890c2344c24314..faa0352507fbaf 100644
--- a/llvm/lib/Target/ARM/Thumb1FrameLowering.cpp
+++ b/llvm/lib/Target/ARM/Thumb1FrameLowering.cpp
@@ -43,6 +43,8 @@
 #include <iterator>
 #include <vector>
 
+#define DEBUG_TYPE "arm-frame-lowering"
+
 using namespace llvm;
 
 Thumb1FrameLowering::Thumb1FrameLowering(const ARMSubtarget &sti)
@@ -277,6 +279,20 @@ void Thumb1FrameLowering::emitPrologue(MachineFunction &MF,
     }
   }
 
+  // Skip past this code sequence, which is emitted to restore the LR if it is
+  // live-in and clobbered by the frame record setup code:
+  //   ldr rX, [sp, #Y]
+  //   mov lr, rX
+  if (MBBI != MBB.end() && MBBI->getOpcode() == ARM::tLDRspi &&
+      MBBI->getFlag(MachineInstr::FrameSetup)) {
+    ++MBBI;
+    if (MBBI != MBB.end() && MBBI->getOpcode() == ARM::tMOVr &&
+        MBBI->getOperand(0).getReg() == ARM::LR &&
+        MBBI->getFlag(MachineInstr::FrameSetup)) {
+      ++MBBI;
+    }
+  }
+
   // Determine starting offsets of spill areas.
   unsigned DPRCSOffset = NumBytes - ArgRegsSaveSize -
                          (FRSize + GPRCS1Size + GPRCS2Size + DPRCSSize);
@@ -857,7 +873,8 @@ static void pushRegsToStack(MachineBasicBlock &MBB,
                             MachineBasicBlock::iterator MI,
                             const TargetInstrInfo &TII,
                             const std::set<Register> &RegsToSave,
-                            const std::set<Register> &CopyRegs) {
+                            const std::set<Register> &CopyRegs,
+                            bool &UsedLRAsTemp) {
   MachineFunction &MF = *MBB.getParent();
   const MachineRegisterInfo &MRI = MF.getRegInfo();
   DebugLoc DL;
@@ -914,6 +931,8 @@ static void pushRegsToStack(MachineBasicBlock &MBB,
         bool isKill = !MRI.isLiveIn(*HiRegToSave);
         if (isKill && !MRI.isReserved(*HiRegToSave))
           MBB.addLiveIn(*HiRegToSave);
+        if (*CopyRegIt == ARM::LR)
+          UsedLRAsTemp = true;
 
         // Emit a MOV from the high reg to the low reg.
         BuildMI(MBB, MI, DL, TII.get(ARM::tMOVr))
@@ -1093,6 +1112,8 @@ bool Thumb1FrameLowering::spillCalleeSavedRegisters(
   // In case FP is a high reg, we need a separate push sequence to generate
   // a correct Frame Record
   bool NeedsFrameRecordPush = hasFP(MF) && ARM::hGPRRegClass.contains(FPReg);
+  bool LRLiveIn = MF.getRegInfo().isLiveIn(ARM::LR);
+  bool UsedLRAsTemp = false;
 
   std::set<Register> FrameRecord;
   std::set<Register> SpilledGPRs;
@@ -1104,7 +1125,22 @@ bool Thumb1FrameLowering::spillCalleeSavedRegisters(
       SpilledGPRs.insert(Reg);
   }
 
-  pushRegsToStack(MBB, MI, TII, FrameRecord, {ARM::LR});
+  // Determine intermediate registers which can be used for pushing the frame
+  // record:
+  // - Unused argument registers
+  // - LR: This is possible because the first PUSH will save it on the stack,
+  //       so it is free to be used as a temporary for the second. However, it
+  //       is possible for LR to be live-in to the function, in which case we
+  //       will need to restore it later in the prologue, so we only use this
+  //       if there are no free argument registers.
+  std::set<Register> FrameRecordCopyRegs;
+  for (unsigned ArgReg : {ARM::R0, ARM::R1, ARM::R2, ARM::R3})
+    if (!MF.getRegInfo().isLiveIn(ArgReg))
+      FrameRecordCopyRegs.insert(ArgReg);
+  if (FrameRecordCopyRegs.empty())
+    FrameRecordCopyRegs.insert(ARM::LR);
+
+  pushRegsToStack(MBB, MI, TII, FrameRecord, FrameRecordCopyRegs, UsedLRAsTemp);
 
   // Determine intermediate registers which can be used for pushing high regs:
   // - Spilled low regs
@@ -1118,7 +1154,33 @@ bool Thumb1FrameLowering::spillCalleeSavedRegisters(
     if (!MF.getRegInfo().isLiveIn(ArgReg))
       CopyRegs.insert(ArgReg);
 
-  pushRegsToStack(MBB, MI, TII, SpilledGPRs, CopyRegs);
+  pushRegsToStack(MBB, MI, TII, SpilledGPRs, CopyRegs, UsedLRAsTemp);
+
+  // If the push sequence used LR as a temporary, and LR is live-in (for
+  // example because it is used by the llvm.returnaddress intrinsic), then we
+  // need to reload it from the stack. Thumb1 does not have a load instruction
+  // which can use LR, so we need to load into a temporary low register and
+  // copy to LR.
+  if (LRLiveIn && UsedLRAsTemp) {
+    auto CopyRegIt = getNextOrderedReg(OrderedCopyRegs.rbegin(),
+                                       OrderedCopyRegs.rend(), CopyRegs);
+    assert(CopyRegIt != OrderedCopyRegs.rend());
+    unsigned NumRegsPushed = FrameRecord.size() + SpilledGPRs.size();
+    LLVM_DEBUG(
+        dbgs() << "LR is live-in but clobbered in prologue, restoring via "
+               << RegInfo->getName(*CopyRegIt) << "\n");
+
+    BuildMI(MBB, MI, DebugLoc(), TII.get(ARM::tLDRspi), *CopyRegIt)
+        .addReg(ARM::SP)
+        .addImm(NumRegsPushed - 1)
+        .add(predOps(ARMCC::AL))
+        .setMIFlags(MachineInstr::FrameSetup);
+
+    BuildMI(MBB, MI, DebugLoc(), TII.get(ARM::tMOVr), ARM::LR)
+        .addReg(*CopyRegIt)
+        .add(predOps(ARMCC::AL))
+        .setMIFlags(MachineInstr::FrameSetup);
+  }
 
   return true;
 }

diff  --git a/llvm/test/CodeGen/Thumb/frame-chain.ll b/llvm/test/CodeGen/Thumb/frame-chain.ll
index e68fc626be9819..134362cfd0cb65 100644
--- a/llvm/test/CodeGen/Thumb/frame-chain.ll
+++ b/llvm/test/CodeGen/Thumb/frame-chain.ll
@@ -23,9 +23,9 @@ define dso_local noundef i32 @leaf(i32 noundef %0) {
 ; LEAF-FP-AAPCS:       @ %bb.0:
 ; LEAF-FP-AAPCS-NEXT:    .save {lr}
 ; LEAF-FP-AAPCS-NEXT:    push {lr}
-; LEAF-FP-AAPCS-NEXT:    mov lr, r11
+; LEAF-FP-AAPCS-NEXT:    mov r3, r11
 ; LEAF-FP-AAPCS-NEXT:    .save {r11}
-; LEAF-FP-AAPCS-NEXT:    push {lr}
+; LEAF-FP-AAPCS-NEXT:    push {r3}
 ; LEAF-FP-AAPCS-NEXT:    .setfp r11, sp
 ; LEAF-FP-AAPCS-NEXT:    mov r11, sp
 ; LEAF-FP-AAPCS-NEXT:    .pad #4
@@ -80,9 +80,9 @@ define dso_local noundef i32 @non_leaf(i32 noundef %0) {
 ; FP-AAPCS:       @ %bb.0:
 ; FP-AAPCS-NEXT:    .save {lr}
 ; FP-AAPCS-NEXT:    push {lr}
-; FP-AAPCS-NEXT:    mov lr, r11
+; FP-AAPCS-NEXT:    mov r3, r11
 ; FP-AAPCS-NEXT:    .save {r11}
-; FP-AAPCS-NEXT:    push {lr}
+; FP-AAPCS-NEXT:    push {r3}
 ; FP-AAPCS-NEXT:    .setfp r11, sp
 ; FP-AAPCS-NEXT:    mov r11, sp
 ; FP-AAPCS-NEXT:    .pad #8
@@ -161,9 +161,9 @@ define dso_local void @required_fp(i32 %0, i32 %1) {
 ; FP-AAPCS:       @ %bb.0:
 ; FP-AAPCS-NEXT:    .save {lr}
 ; FP-AAPCS-NEXT:    push {lr}
-; FP-AAPCS-NEXT:    mov lr, r11
+; FP-AAPCS-NEXT:    mov r3, r11
 ; FP-AAPCS-NEXT:    .save {r11}
-; FP-AAPCS-NEXT:    push {lr}
+; FP-AAPCS-NEXT:    push {r3}
 ; FP-AAPCS-NEXT:    .setfp r11, sp
 ; FP-AAPCS-NEXT:    mov r11, sp
 ; FP-AAPCS-NEXT:    .save {r4, r6}
@@ -227,9 +227,9 @@ define dso_local void @required_fp(i32 %0, i32 %1) {
 ; NOFP-AAPCS:       @ %bb.0:
 ; NOFP-AAPCS-NEXT:    .save {lr}
 ; NOFP-AAPCS-NEXT:    push {lr}
-; NOFP-AAPCS-NEXT:    mov lr, r11
+; NOFP-AAPCS-NEXT:    mov r3, r11
 ; NOFP-AAPCS-NEXT:    .save {r11}
-; NOFP-AAPCS-NEXT:    push {lr}
+; NOFP-AAPCS-NEXT:    push {r3}
 ; NOFP-AAPCS-NEXT:    .setfp r11, sp
 ; NOFP-AAPCS-NEXT:    mov r11, sp
 ; NOFP-AAPCS-NEXT:    .save {r4, r6}

diff  --git a/llvm/test/CodeGen/Thumb/returnaddress.ll b/llvm/test/CodeGen/Thumb/returnaddress.ll
new file mode 100644
index 00000000000000..c13daf6b8c91c4
--- /dev/null
+++ b/llvm/test/CodeGen/Thumb/returnaddress.ll
@@ -0,0 +1,440 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 5
+; RUN: llc < %s -mtriple=thumbv6m-none-eabi -frame-pointer=none                          -verify-machineinstrs | FileCheck %s --check-prefix=FP-NONE
+; RUN: llc < %s -mtriple=thumbv6m-none-eabi -frame-pointer=all                           -verify-machineinstrs | FileCheck %s --check-prefix=FP-ALL
+; RUN: llc < %s -mtriple=thumbv6m-none-eabi -frame-pointer=all -mattr=+aapcs-frame-chain -verify-machineinstrs | FileCheck %s --check-prefix=FP-AAPCS
+
+define void @ra_call() {
+; FP-NONE-LABEL: ra_call:
+; FP-NONE:       @ %bb.0: @ %entry
+; FP-NONE-NEXT:    .save {r7, lr}
+; FP-NONE-NEXT:    push {r7, lr}
+; FP-NONE-NEXT:    mov r0, lr
+; FP-NONE-NEXT:    bl sink_ptr
+; FP-NONE-NEXT:    pop {r7, pc}
+;
+; FP-ALL-LABEL: ra_call:
+; FP-ALL:       @ %bb.0: @ %entry
+; FP-ALL-NEXT:    .save {r7, lr}
+; FP-ALL-NEXT:    push {r7, lr}
+; FP-ALL-NEXT:    .setfp r7, sp
+; FP-ALL-NEXT:    add r7, sp, #0
+; FP-ALL-NEXT:    mov r0, lr
+; FP-ALL-NEXT:    bl sink_ptr
+; FP-ALL-NEXT:    pop {r7, pc}
+;
+; FP-AAPCS-LABEL: ra_call:
+; FP-AAPCS:       @ %bb.0: @ %entry
+; FP-AAPCS-NEXT:    .save {lr}
+; FP-AAPCS-NEXT:    push {lr}
+; FP-AAPCS-NEXT:    mov r3, r11
+; FP-AAPCS-NEXT:    .save {r11}
+; FP-AAPCS-NEXT:    push {r3}
+; FP-AAPCS-NEXT:    .setfp r11, sp
+; FP-AAPCS-NEXT:    mov r11, sp
+; FP-AAPCS-NEXT:    mov r0, lr
+; FP-AAPCS-NEXT:    bl sink_ptr
+; FP-AAPCS-NEXT:    pop {r0}
+; FP-AAPCS-NEXT:    mov r11, r0
+; FP-AAPCS-NEXT:    pop {pc}
+entry:
+  %r = tail call ptr @llvm.returnaddress(i32 0)
+  tail call void @sink_ptr(ptr %r)
+  ret void
+}
+
+define ptr @ra_return() {
+; FP-NONE-LABEL: ra_return:
+; FP-NONE:       @ %bb.0: @ %entry
+; FP-NONE-NEXT:    mov r0, lr
+; FP-NONE-NEXT:    bx lr
+;
+; FP-ALL-LABEL: ra_return:
+; FP-ALL:       @ %bb.0: @ %entry
+; FP-ALL-NEXT:    .save {r7, lr}
+; FP-ALL-NEXT:    push {r7, lr}
+; FP-ALL-NEXT:    .setfp r7, sp
+; FP-ALL-NEXT:    add r7, sp, #0
+; FP-ALL-NEXT:    mov r0, lr
+; FP-ALL-NEXT:    pop {r7, pc}
+;
+; FP-AAPCS-LABEL: ra_return:
+; FP-AAPCS:       @ %bb.0: @ %entry
+; FP-AAPCS-NEXT:    .save {lr}
+; FP-AAPCS-NEXT:    push {lr}
+; FP-AAPCS-NEXT:    mov r3, r11
+; FP-AAPCS-NEXT:    .save {r11}
+; FP-AAPCS-NEXT:    push {r3}
+; FP-AAPCS-NEXT:    .setfp r11, sp
+; FP-AAPCS-NEXT:    mov r11, sp
+; FP-AAPCS-NEXT:    mov r0, lr
+; FP-AAPCS-NEXT:    pop {r1}
+; FP-AAPCS-NEXT:    mov r11, r1
+; FP-AAPCS-NEXT:    pop {pc}
+entry:
+  %r = tail call ptr @llvm.returnaddress(i32 0)
+  ret ptr %r
+}
+
+define ptr @callee_saved_low() {
+; FP-NONE-LABEL: callee_saved_low:
+; FP-NONE:       @ %bb.0: @ %entry
+; FP-NONE-NEXT:    .save {r4, r5, r7, lr}
+; FP-NONE-NEXT:    push {r4, r5, r7, lr}
+; FP-NONE-NEXT:    mov r0, lr
+; FP-NONE-NEXT:    @APP
+; FP-NONE-NEXT:    @NO_APP
+; FP-NONE-NEXT:    pop {r4, r5, r7, pc}
+;
+; FP-ALL-LABEL: callee_saved_low:
+; FP-ALL:       @ %bb.0: @ %entry
+; FP-ALL-NEXT:    .save {r4, r5, r7, lr}
+; FP-ALL-NEXT:    push {r4, r5, r7, lr}
+; FP-ALL-NEXT:    .setfp r7, sp, #8
+; FP-ALL-NEXT:    add r7, sp, #8
+; FP-ALL-NEXT:    mov r0, lr
+; FP-ALL-NEXT:    @APP
+; FP-ALL-NEXT:    @NO_APP
+; FP-ALL-NEXT:    pop {r4, r5, r7, pc}
+;
+; FP-AAPCS-LABEL: callee_saved_low:
+; FP-AAPCS:       @ %bb.0: @ %entry
+; FP-AAPCS-NEXT:    .save {lr}
+; FP-AAPCS-NEXT:    push {lr}
+; FP-AAPCS-NEXT:    mov r3, r11
+; FP-AAPCS-NEXT:    .save {r11}
+; FP-AAPCS-NEXT:    push {r3}
+; FP-AAPCS-NEXT:    .setfp r11, sp
+; FP-AAPCS-NEXT:    mov r11, sp
+; FP-AAPCS-NEXT:    .save {r4, r5}
+; FP-AAPCS-NEXT:    push {r4, r5}
+; FP-AAPCS-NEXT:    mov r0, lr
+; FP-AAPCS-NEXT:    @APP
+; FP-AAPCS-NEXT:    @NO_APP
+; FP-AAPCS-NEXT:    pop {r4, r5}
+; FP-AAPCS-NEXT:    pop {r1}
+; FP-AAPCS-NEXT:    mov r11, r1
+; FP-AAPCS-NEXT:    pop {pc}
+entry:
+  call void asm sideeffect "", "~{r4},~{r5}"()
+  %r = tail call ptr @llvm.returnaddress(i32 0)
+  ret ptr %r
+}
+
+define ptr @callee_saved_high() {
+; FP-NONE-LABEL: callee_saved_high:
+; FP-NONE:       @ %bb.0: @ %entry
+; FP-NONE-NEXT:    mov r3, r9
+; FP-NONE-NEXT:    mov r2, r8
+; FP-NONE-NEXT:    .save {r8, r9}
+; FP-NONE-NEXT:    push {r2, r3}
+; FP-NONE-NEXT:    mov r0, lr
+; FP-NONE-NEXT:    @APP
+; FP-NONE-NEXT:    @NO_APP
+; FP-NONE-NEXT:    pop {r1, r2}
+; FP-NONE-NEXT:    mov r8, r1
+; FP-NONE-NEXT:    mov r9, r2
+; FP-NONE-NEXT:    bx lr
+;
+; FP-ALL-LABEL: callee_saved_high:
+; FP-ALL:       @ %bb.0: @ %entry
+; FP-ALL-NEXT:    .save {r7, lr}
+; FP-ALL-NEXT:    push {r7, lr}
+; FP-ALL-NEXT:    .setfp r7, sp
+; FP-ALL-NEXT:    add r7, sp, #0
+; FP-ALL-NEXT:    mov r3, r9
+; FP-ALL-NEXT:    mov r2, r8
+; FP-ALL-NEXT:    .save {r8, r9}
+; FP-ALL-NEXT:    push {r2, r3}
+; FP-ALL-NEXT:    mov r0, lr
+; FP-ALL-NEXT:    @APP
+; FP-ALL-NEXT:    @NO_APP
+; FP-ALL-NEXT:    pop {r1, r2}
+; FP-ALL-NEXT:    mov r8, r1
+; FP-ALL-NEXT:    mov r9, r2
+; FP-ALL-NEXT:    pop {r7, pc}
+;
+; FP-AAPCS-LABEL: callee_saved_high:
+; FP-AAPCS:       @ %bb.0: @ %entry
+; FP-AAPCS-NEXT:    .save {lr}
+; FP-AAPCS-NEXT:    push {lr}
+; FP-AAPCS-NEXT:    mov r3, r11
+; FP-AAPCS-NEXT:    .save {r11}
+; FP-AAPCS-NEXT:    push {r3}
+; FP-AAPCS-NEXT:    .setfp r11, sp
+; FP-AAPCS-NEXT:    mov r11, sp
+; FP-AAPCS-NEXT:    mov r3, r9
+; FP-AAPCS-NEXT:    mov r2, r8
+; FP-AAPCS-NEXT:    .save {r8, r9}
+; FP-AAPCS-NEXT:    push {r2, r3}
+; FP-AAPCS-NEXT:    mov r0, lr
+; FP-AAPCS-NEXT:    @APP
+; FP-AAPCS-NEXT:    @NO_APP
+; FP-AAPCS-NEXT:    pop {r1, r2}
+; FP-AAPCS-NEXT:    mov r8, r1
+; FP-AAPCS-NEXT:    mov r9, r2
+; FP-AAPCS-NEXT:    pop {r1}
+; FP-AAPCS-NEXT:    mov r11, r1
+; FP-AAPCS-NEXT:    pop {pc}
+entry:
+  call void asm sideeffect "", "~{r8},~{r9}"()
+  %r = tail call ptr @llvm.returnaddress(i32 0)
+  ret ptr %r
+}
+
+define ptr @large_alloca() {
+; FP-NONE-LABEL: large_alloca:
+; FP-NONE:       @ %bb.0: @ %entry
+; FP-NONE-NEXT:    .save {r4, r5, r6, lr}
+; FP-NONE-NEXT:    push {r4, r5, r6, lr}
+; FP-NONE-NEXT:    ldr r6, .LCPI4_0
+; FP-NONE-NEXT:    .pad #2000
+; FP-NONE-NEXT:    add sp, r6
+; FP-NONE-NEXT:    mov r4, lr
+; FP-NONE-NEXT:    mov r0, sp
+; FP-NONE-NEXT:    bl sink_ptr
+; FP-NONE-NEXT:    mov r0, r4
+; FP-NONE-NEXT:    ldr r6, .LCPI4_1
+; FP-NONE-NEXT:    add sp, r6
+; FP-NONE-NEXT:    pop {r4, r5, r6, pc}
+; FP-NONE-NEXT:    .p2align 2
+; FP-NONE-NEXT:  @ %bb.1:
+; FP-NONE-NEXT:  .LCPI4_0:
+; FP-NONE-NEXT:    .long 4294965296 @ 0xfffff830
+; FP-NONE-NEXT:  .LCPI4_1:
+; FP-NONE-NEXT:    .long 2000 @ 0x7d0
+;
+; FP-ALL-LABEL: large_alloca:
+; FP-ALL:       @ %bb.0: @ %entry
+; FP-ALL-NEXT:    .save {r4, r6, r7, lr}
+; FP-ALL-NEXT:    push {r4, r6, r7, lr}
+; FP-ALL-NEXT:    .setfp r7, sp, #8
+; FP-ALL-NEXT:    add r7, sp, #8
+; FP-ALL-NEXT:    ldr r6, .LCPI4_0
+; FP-ALL-NEXT:    .pad #2000
+; FP-ALL-NEXT:    add sp, r6
+; FP-ALL-NEXT:    mov r4, lr
+; FP-ALL-NEXT:    mov r0, sp
+; FP-ALL-NEXT:    bl sink_ptr
+; FP-ALL-NEXT:    mov r0, r4
+; FP-ALL-NEXT:    subs r6, r7, #7
+; FP-ALL-NEXT:    subs r6, #1
+; FP-ALL-NEXT:    mov sp, r6
+; FP-ALL-NEXT:    pop {r4, r6, r7, pc}
+; FP-ALL-NEXT:    .p2align 2
+; FP-ALL-NEXT:  @ %bb.1:
+; FP-ALL-NEXT:  .LCPI4_0:
+; FP-ALL-NEXT:    .long 4294965296 @ 0xfffff830
+;
+; FP-AAPCS-LABEL: large_alloca:
+; FP-AAPCS:       @ %bb.0: @ %entry
+; FP-AAPCS-NEXT:    .save {lr}
+; FP-AAPCS-NEXT:    push {lr}
+; FP-AAPCS-NEXT:    mov r3, r11
+; FP-AAPCS-NEXT:    .save {r11}
+; FP-AAPCS-NEXT:    push {r3}
+; FP-AAPCS-NEXT:    .setfp r11, sp
+; FP-AAPCS-NEXT:    mov r11, sp
+; FP-AAPCS-NEXT:    .save {r4, r7}
+; FP-AAPCS-NEXT:    push {r4, r7}
+; FP-AAPCS-NEXT:    ldr r7, .LCPI4_0
+; FP-AAPCS-NEXT:    .pad #2000
+; FP-AAPCS-NEXT:    add sp, r7
+; FP-AAPCS-NEXT:    mov r4, lr
+; FP-AAPCS-NEXT:    mov r0, sp
+; FP-AAPCS-NEXT:    bl sink_ptr
+; FP-AAPCS-NEXT:    mov r0, r4
+; FP-AAPCS-NEXT:    mov r7, r11
+; FP-AAPCS-NEXT:    subs r7, #8
+; FP-AAPCS-NEXT:    mov sp, r7
+; FP-AAPCS-NEXT:    pop {r4, r7}
+; FP-AAPCS-NEXT:    pop {r1}
+; FP-AAPCS-NEXT:    mov r11, r1
+; FP-AAPCS-NEXT:    pop {pc}
+; FP-AAPCS-NEXT:    .p2align 2
+; FP-AAPCS-NEXT:  @ %bb.1:
+; FP-AAPCS-NEXT:  .LCPI4_0:
+; FP-AAPCS-NEXT:    .long 4294965296 @ 0xfffff830
+entry:
+  %big = alloca i8, i32 2000
+  tail call void @sink_ptr(ptr %big)
+  %r = tail call ptr @llvm.returnaddress(i32 0)
+  ret ptr %r
+}
+
+define ptr @var_alloca(i32 %size) {
+; FP-NONE-LABEL: var_alloca:
+; FP-NONE:       @ %bb.0: @ %entry
+; FP-NONE-NEXT:    .save {r4, r6, r7, lr}
+; FP-NONE-NEXT:    push {r4, r6, r7, lr}
+; FP-NONE-NEXT:    .setfp r7, sp, #8
+; FP-NONE-NEXT:    add r7, sp, #8
+; FP-NONE-NEXT:    mov r6, sp
+; FP-NONE-NEXT:    mov r4, lr
+; FP-NONE-NEXT:    adds r0, r0, #7
+; FP-NONE-NEXT:    movs r1, #7
+; FP-NONE-NEXT:    bics r0, r1
+; FP-NONE-NEXT:    mov r1, sp
+; FP-NONE-NEXT:    subs r0, r1, r0
+; FP-NONE-NEXT:    mov sp, r0
+; FP-NONE-NEXT:    bl sink_ptr
+; FP-NONE-NEXT:    mov r0, r4
+; FP-NONE-NEXT:    subs r6, r7, #7
+; FP-NONE-NEXT:    subs r6, #1
+; FP-NONE-NEXT:    mov sp, r6
+; FP-NONE-NEXT:    pop {r4, r6, r7, pc}
+;
+; FP-ALL-LABEL: var_alloca:
+; FP-ALL:       @ %bb.0: @ %entry
+; FP-ALL-NEXT:    .save {r4, r6, r7, lr}
+; FP-ALL-NEXT:    push {r4, r6, r7, lr}
+; FP-ALL-NEXT:    .setfp r7, sp, #8
+; FP-ALL-NEXT:    add r7, sp, #8
+; FP-ALL-NEXT:    mov r6, sp
+; FP-ALL-NEXT:    mov r4, lr
+; FP-ALL-NEXT:    adds r0, r0, #7
+; FP-ALL-NEXT:    movs r1, #7
+; FP-ALL-NEXT:    bics r0, r1
+; FP-ALL-NEXT:    mov r1, sp
+; FP-ALL-NEXT:    subs r0, r1, r0
+; FP-ALL-NEXT:    mov sp, r0
+; FP-ALL-NEXT:    bl sink_ptr
+; FP-ALL-NEXT:    mov r0, r4
+; FP-ALL-NEXT:    subs r6, r7, #7
+; FP-ALL-NEXT:    subs r6, #1
+; FP-ALL-NEXT:    mov sp, r6
+; FP-ALL-NEXT:    pop {r4, r6, r7, pc}
+;
+; FP-AAPCS-LABEL: var_alloca:
+; FP-AAPCS:       @ %bb.0: @ %entry
+; FP-AAPCS-NEXT:    .save {lr}
+; FP-AAPCS-NEXT:    push {lr}
+; FP-AAPCS-NEXT:    mov r3, r11
+; FP-AAPCS-NEXT:    .save {r11}
+; FP-AAPCS-NEXT:    push {r3}
+; FP-AAPCS-NEXT:    .setfp r11, sp
+; FP-AAPCS-NEXT:    mov r11, sp
+; FP-AAPCS-NEXT:    .save {r4, r6}
+; FP-AAPCS-NEXT:    push {r4, r6}
+; FP-AAPCS-NEXT:    mov r6, sp
+; FP-AAPCS-NEXT:    mov r4, lr
+; FP-AAPCS-NEXT:    adds r0, r0, #7
+; FP-AAPCS-NEXT:    movs r1, #7
+; FP-AAPCS-NEXT:    bics r0, r1
+; FP-AAPCS-NEXT:    mov r1, sp
+; FP-AAPCS-NEXT:    subs r0, r1, r0
+; FP-AAPCS-NEXT:    mov sp, r0
+; FP-AAPCS-NEXT:    bl sink_ptr
+; FP-AAPCS-NEXT:    mov r0, r4
+; FP-AAPCS-NEXT:    mov r6, r11
+; FP-AAPCS-NEXT:    subs r6, #8
+; FP-AAPCS-NEXT:    mov sp, r6
+; FP-AAPCS-NEXT:    pop {r4, r6}
+; FP-AAPCS-NEXT:    pop {r1}
+; FP-AAPCS-NEXT:    mov r11, r1
+; FP-AAPCS-NEXT:    pop {pc}
+entry:
+  %var = alloca i8, i32 %size
+  tail call void @sink_ptr(ptr %var)
+  %r = tail call ptr @llvm.returnaddress(i32 0)
+  ret ptr %r
+}
+
+define i32 @all_arg_regs(i32 %a, i32 %b, i32 %c, i32 %d) {
+; FP-NONE-LABEL: all_arg_regs:
+; FP-NONE:       @ %bb.0: @ %entry
+; FP-NONE-NEXT:    .save {r4, lr}
+; FP-NONE-NEXT:    push {r4, lr}
+; FP-NONE-NEXT:    mov r4, lr
+; FP-NONE-NEXT:    adds r0, r0, r1
+; FP-NONE-NEXT:    adds r0, r0, r2
+; FP-NONE-NEXT:    adds r0, r0, r3
+; FP-NONE-NEXT:    adds r0, r0, r4
+; FP-NONE-NEXT:    pop {r4, pc}
+;
+; FP-ALL-LABEL: all_arg_regs:
+; FP-ALL:       @ %bb.0: @ %entry
+; FP-ALL-NEXT:    .save {r4, r6, r7, lr}
+; FP-ALL-NEXT:    push {r4, r6, r7, lr}
+; FP-ALL-NEXT:    .setfp r7, sp, #8
+; FP-ALL-NEXT:    add r7, sp, #8
+; FP-ALL-NEXT:    mov r4, lr
+; FP-ALL-NEXT:    adds r0, r0, r1
+; FP-ALL-NEXT:    adds r0, r0, r2
+; FP-ALL-NEXT:    adds r0, r0, r3
+; FP-ALL-NEXT:    adds r0, r0, r4
+; FP-ALL-NEXT:    pop {r4, r6, r7, pc}
+;
+; FP-AAPCS-LABEL: all_arg_regs:
+; FP-AAPCS:       @ %bb.0: @ %entry
+; FP-AAPCS-NEXT:    .save {lr}
+; FP-AAPCS-NEXT:    push {lr}
+; FP-AAPCS-NEXT:    mov lr, r11
+; FP-AAPCS-NEXT:    .save {r11}
+; FP-AAPCS-NEXT:    push {lr}
+; FP-AAPCS-NEXT:    .setfp r11, sp
+; FP-AAPCS-NEXT:    mov r11, sp
+; FP-AAPCS-NEXT:    .save {r4, r7}
+; FP-AAPCS-NEXT:    push {r4, r7}
+; FP-AAPCS-NEXT:    ldr r7, [sp, #12]
+; FP-AAPCS-NEXT:    mov lr, r7
+; FP-AAPCS-NEXT:    mov r4, lr
+; FP-AAPCS-NEXT:    adds r0, r0, r1
+; FP-AAPCS-NEXT:    adds r0, r0, r2
+; FP-AAPCS-NEXT:    adds r0, r0, r3
+; FP-AAPCS-NEXT:    adds r0, r0, r4
+; FP-AAPCS-NEXT:    pop {r4, r7}
+; FP-AAPCS-NEXT:    pop {r1}
+; FP-AAPCS-NEXT:    mov r11, r1
+; FP-AAPCS-NEXT:    pop {pc}
+entry:
+  %r = tail call ptr @llvm.returnaddress(i32 0)
+  %ri = ptrtoint ptr %r to i32
+  %t1 = add i32 %a, %b
+  %t2 = add i32 %t1, %c
+  %t3 = add i32 %t2, %d
+  %t4 = add i32 %t3, %ri
+  ret i32 %t4
+}
+
+define ptr @ra_depth_1() {
+; FP-NONE-LABEL: ra_depth_1:
+; FP-NONE:       @ %bb.0: @ %entry
+; FP-NONE-NEXT:    .save {r7, lr}
+; FP-NONE-NEXT:    push {r7, lr}
+; FP-NONE-NEXT:    .setfp r7, sp
+; FP-NONE-NEXT:    add r7, sp, #0
+; FP-NONE-NEXT:    ldr r0, [r7]
+; FP-NONE-NEXT:    ldr r0, [r0, #4]
+; FP-NONE-NEXT:    pop {r7, pc}
+;
+; FP-ALL-LABEL: ra_depth_1:
+; FP-ALL:       @ %bb.0: @ %entry
+; FP-ALL-NEXT:    .save {r7, lr}
+; FP-ALL-NEXT:    push {r7, lr}
+; FP-ALL-NEXT:    .setfp r7, sp
+; FP-ALL-NEXT:    add r7, sp, #0
+; FP-ALL-NEXT:    ldr r0, [r7]
+; FP-ALL-NEXT:    ldr r0, [r0, #4]
+; FP-ALL-NEXT:    pop {r7, pc}
+;
+; FP-AAPCS-LABEL: ra_depth_1:
+; FP-AAPCS:       @ %bb.0: @ %entry
+; FP-AAPCS-NEXT:    .save {lr}
+; FP-AAPCS-NEXT:    push {lr}
+; FP-AAPCS-NEXT:    mov r3, r11
+; FP-AAPCS-NEXT:    .save {r11}
+; FP-AAPCS-NEXT:    push {r3}
+; FP-AAPCS-NEXT:    .setfp r11, sp
+; FP-AAPCS-NEXT:    mov r11, sp
+; FP-AAPCS-NEXT:    mov r0, r11
+; FP-AAPCS-NEXT:    ldr r0, [r0]
+; FP-AAPCS-NEXT:    ldr r0, [r0, #4]
+; FP-AAPCS-NEXT:    pop {r1}
+; FP-AAPCS-NEXT:    mov r11, r1
+; FP-AAPCS-NEXT:    pop {pc}
+entry:
+  %r = tail call ptr @llvm.returnaddress(i32 1)
+  ret ptr %r
+}
+
+declare void @sink_ptr(ptr)


        


More information about the llvm-commits mailing list