[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