[llvm] [ARM] Fix llvm.returnaddress for Thumb1 with R11 frame-pointer (PR #117735)
Oliver Stannard via llvm-commits
llvm-commits at lists.llvm.org
Wed Nov 27 09:12:04 PST 2024
https://github.com/ostannard updated https://github.com/llvm/llvm-project/pull/117735
>From 3dd3280c9ee50f291fa6cff82b1411357eeda0bc Mon Sep 17 00:00:00 2001
From: Oliver Stannard <oliver.stannard at arm.com>
Date: Wed, 27 Nov 2024 13:02:17 +0000
Subject: [PATCH 1/4] Test showing incorrect codegen
---
llvm/test/CodeGen/Thumb/returnaddress.ll | 438 +++++++++++++++++++++++
1 file changed, 438 insertions(+)
create mode 100644 llvm/test/CodeGen/Thumb/returnaddress.ll
diff --git a/llvm/test/CodeGen/Thumb/returnaddress.ll b/llvm/test/CodeGen/Thumb/returnaddress.ll
new file mode 100644
index 00000000000000..74ae00b3441fdd
--- /dev/null
+++ b/llvm/test/CodeGen/Thumb/returnaddress.ll
@@ -0,0 +1,438 @@
+; 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 | FileCheck %s --check-prefix=FP-NONE
+; RUN: llc < %s -mtriple=thumbv6m-none-eabi -frame-pointer=all | FileCheck %s --check-prefix=FP-ALL
+; RUN: llc < %s -mtriple=thumbv6m-none-eabi -frame-pointer=all -mattr=+aapcs-frame-chain | 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 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: 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 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: 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 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, 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 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: 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 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, .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 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, 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: 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 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: 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)
>From 2a146e871b07fba422cbeaf56ec95b70e8c5e607 Mon Sep 17 00:00:00 2001
From: Oliver Stannard <oliver.stannard at arm.com>
Date: Wed, 27 Nov 2024 14:36:20 +0000
Subject: [PATCH 2/4] [ARM] Fix llvm.returnaddress for Thumb1 with R11
frame-pointer
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.
---
llvm/lib/Target/ARM/ARMAsmPrinter.cpp | 4 ++
llvm/lib/Target/ARM/Thumb1FrameLowering.cpp | 54 +++++++++++++++++++--
llvm/test/CodeGen/Thumb/returnaddress.ll | 20 ++++++--
3 files changed, 72 insertions(+), 6 deletions(-)
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..6c57d2b47feff1 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,7 @@ bool Thumb1FrameLowering::spillCalleeSavedRegisters(
SpilledGPRs.insert(Reg);
}
- pushRegsToStack(MBB, MI, TII, FrameRecord, {ARM::LR});
+ pushRegsToStack(MBB, MI, TII, FrameRecord, {ARM::LR}, UsedLRAsTemp);
// Determine intermediate registers which can be used for pushing high regs:
// - Spilled low regs
@@ -1118,7 +1139,34 @@ 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/returnaddress.ll b/llvm/test/CodeGen/Thumb/returnaddress.ll
index 74ae00b3441fdd..92fee6f364a6e1 100644
--- a/llvm/test/CodeGen/Thumb/returnaddress.ll
+++ b/llvm/test/CodeGen/Thumb/returnaddress.ll
@@ -1,7 +1,7 @@
; 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 | FileCheck %s --check-prefix=FP-NONE
-; RUN: llc < %s -mtriple=thumbv6m-none-eabi -frame-pointer=all | FileCheck %s --check-prefix=FP-ALL
-; RUN: llc < %s -mtriple=thumbv6m-none-eabi -frame-pointer=all -mattr=+aapcs-frame-chain | FileCheck %s --check-prefix=FP-AAPCS
+; 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:
@@ -31,6 +31,8 @@ define void @ra_call() {
; FP-AAPCS-NEXT: push {lr}
; FP-AAPCS-NEXT: .setfp r11, sp
; FP-AAPCS-NEXT: mov r11, sp
+; FP-AAPCS-NEXT: ldr r3, [sp, #4]
+; FP-AAPCS-NEXT: mov lr, r3
; FP-AAPCS-NEXT: mov r0, lr
; FP-AAPCS-NEXT: bl sink_ptr
; FP-AAPCS-NEXT: pop {r0}
@@ -66,6 +68,8 @@ define ptr @ra_return() {
; FP-AAPCS-NEXT: push {lr}
; FP-AAPCS-NEXT: .setfp r11, sp
; FP-AAPCS-NEXT: mov r11, sp
+; FP-AAPCS-NEXT: ldr r3, [sp, #4]
+; FP-AAPCS-NEXT: mov lr, r3
; FP-AAPCS-NEXT: mov r0, lr
; FP-AAPCS-NEXT: pop {r1}
; FP-AAPCS-NEXT: mov r11, r1
@@ -107,6 +111,8 @@ define ptr @callee_saved_low() {
; FP-AAPCS-NEXT: mov r11, sp
; FP-AAPCS-NEXT: .save {r4, r5}
; FP-AAPCS-NEXT: push {r4, r5}
+; FP-AAPCS-NEXT: ldr r5, [sp, #12]
+; FP-AAPCS-NEXT: mov lr, r5
; FP-AAPCS-NEXT: mov r0, lr
; FP-AAPCS-NEXT: @APP
; FP-AAPCS-NEXT: @NO_APP
@@ -166,6 +172,8 @@ define ptr @callee_saved_high() {
; FP-AAPCS-NEXT: mov r2, r8
; FP-AAPCS-NEXT: .save {r8, r9}
; FP-AAPCS-NEXT: push {r2, r3}
+; FP-AAPCS-NEXT: ldr r3, [sp, #12]
+; FP-AAPCS-NEXT: mov lr, r3
; FP-AAPCS-NEXT: mov r0, lr
; FP-AAPCS-NEXT: @APP
; FP-AAPCS-NEXT: @NO_APP
@@ -236,6 +244,8 @@ define ptr @large_alloca() {
; 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: ldr r7, .LCPI4_0
; FP-AAPCS-NEXT: .pad #2000
; FP-AAPCS-NEXT: add sp, r7
@@ -315,6 +325,8 @@ define ptr @var_alloca(i32 %size) {
; FP-AAPCS-NEXT: mov r11, sp
; FP-AAPCS-NEXT: .save {r4, r6}
; FP-AAPCS-NEXT: push {r4, r6}
+; FP-AAPCS-NEXT: ldr r6, [sp, #12]
+; FP-AAPCS-NEXT: mov lr, r6
; FP-AAPCS-NEXT: mov r6, sp
; FP-AAPCS-NEXT: mov r4, lr
; FP-AAPCS-NEXT: adds r0, r0, #7
@@ -375,6 +387,8 @@ define i32 @all_arg_regs(i32 %a, i32 %b, i32 %c, i32 %d) {
; 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
>From 75a3296293f1842420c92331dfd1e7703d101167 Mon Sep 17 00:00:00 2001
From: Oliver Stannard <oliver.stannard at arm.com>
Date: Wed, 27 Nov 2024 16:47:23 +0000
Subject: [PATCH 3/4] [ARM] Optimise Thumb1 frame record creation to not
clobber LR
When setting up frame records using r11 as the frame pointer for Thumb1,
we currently use LR as a temporary. This requires us to re-load it in
cases where LR is live into the function, so it is better to use an
argument register if one is free.
---
llvm/lib/Target/ARM/Thumb1FrameLowering.cpp | 17 ++++++++-
llvm/test/CodeGen/Thumb/frame-chain.ll | 16 ++++-----
llvm/test/CodeGen/Thumb/returnaddress.ll | 40 ++++++++-------------
3 files changed, 38 insertions(+), 35 deletions(-)
diff --git a/llvm/lib/Target/ARM/Thumb1FrameLowering.cpp b/llvm/lib/Target/ARM/Thumb1FrameLowering.cpp
index 6c57d2b47feff1..5ab032eb52d653 100644
--- a/llvm/lib/Target/ARM/Thumb1FrameLowering.cpp
+++ b/llvm/lib/Target/ARM/Thumb1FrameLowering.cpp
@@ -1125,7 +1125,22 @@ bool Thumb1FrameLowering::spillCalleeSavedRegisters(
SpilledGPRs.insert(Reg);
}
- pushRegsToStack(MBB, MI, TII, FrameRecord, {ARM::LR}, UsedLRAsTemp);
+ // 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
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
index 92fee6f364a6e1..c13daf6b8c91c4 100644
--- a/llvm/test/CodeGen/Thumb/returnaddress.ll
+++ b/llvm/test/CodeGen/Thumb/returnaddress.ll
@@ -26,13 +26,11 @@ define void @ra_call() {
; FP-AAPCS: @ %bb.0: @ %entry
; 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: ldr r3, [sp, #4]
-; FP-AAPCS-NEXT: mov lr, r3
; FP-AAPCS-NEXT: mov r0, lr
; FP-AAPCS-NEXT: bl sink_ptr
; FP-AAPCS-NEXT: pop {r0}
@@ -63,13 +61,11 @@ define ptr @ra_return() {
; FP-AAPCS: @ %bb.0: @ %entry
; 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: ldr r3, [sp, #4]
-; FP-AAPCS-NEXT: mov lr, r3
; FP-AAPCS-NEXT: mov r0, lr
; FP-AAPCS-NEXT: pop {r1}
; FP-AAPCS-NEXT: mov r11, r1
@@ -104,15 +100,13 @@ define ptr @callee_saved_low() {
; FP-AAPCS: @ %bb.0: @ %entry
; 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, r5}
; FP-AAPCS-NEXT: push {r4, r5}
-; FP-AAPCS-NEXT: ldr r5, [sp, #12]
-; FP-AAPCS-NEXT: mov lr, r5
; FP-AAPCS-NEXT: mov r0, lr
; FP-AAPCS-NEXT: @APP
; FP-AAPCS-NEXT: @NO_APP
@@ -163,17 +157,15 @@ define ptr @callee_saved_high() {
; FP-AAPCS: @ %bb.0: @ %entry
; 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: mov r3, r9
; FP-AAPCS-NEXT: mov r2, r8
; FP-AAPCS-NEXT: .save {r8, r9}
; FP-AAPCS-NEXT: push {r2, r3}
-; FP-AAPCS-NEXT: ldr r3, [sp, #12]
-; FP-AAPCS-NEXT: mov lr, r3
; FP-AAPCS-NEXT: mov r0, lr
; FP-AAPCS-NEXT: @APP
; FP-AAPCS-NEXT: @NO_APP
@@ -237,15 +229,13 @@ define ptr @large_alloca() {
; FP-AAPCS: @ %bb.0: @ %entry
; 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, r7}
; FP-AAPCS-NEXT: push {r4, r7}
-; FP-AAPCS-NEXT: ldr r7, [sp, #12]
-; FP-AAPCS-NEXT: mov lr, r7
; FP-AAPCS-NEXT: ldr r7, .LCPI4_0
; FP-AAPCS-NEXT: .pad #2000
; FP-AAPCS-NEXT: add sp, r7
@@ -318,15 +308,13 @@ define ptr @var_alloca(i32 %size) {
; FP-AAPCS: @ %bb.0: @ %entry
; 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}
; FP-AAPCS-NEXT: push {r4, r6}
-; FP-AAPCS-NEXT: ldr r6, [sp, #12]
-; FP-AAPCS-NEXT: mov lr, r6
; FP-AAPCS-NEXT: mov r6, sp
; FP-AAPCS-NEXT: mov r4, lr
; FP-AAPCS-NEXT: adds r0, r0, #7
@@ -433,9 +421,9 @@ define ptr @ra_depth_1() {
; FP-AAPCS: @ %bb.0: @ %entry
; 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: mov r0, r11
>From 0a0dc4ede6e3b09d485065c29d789fdde191ff7d Mon Sep 17 00:00:00 2001
From: Oliver Stannard <oliver.stannard at arm.com>
Date: Wed, 27 Nov 2024 17:11:48 +0000
Subject: [PATCH 4/4] clang-format
---
llvm/lib/Target/ARM/Thumb1FrameLowering.cpp | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/llvm/lib/Target/ARM/Thumb1FrameLowering.cpp b/llvm/lib/Target/ARM/Thumb1FrameLowering.cpp
index 5ab032eb52d653..faa0352507fbaf 100644
--- a/llvm/lib/Target/ARM/Thumb1FrameLowering.cpp
+++ b/llvm/lib/Target/ARM/Thumb1FrameLowering.cpp
@@ -1163,8 +1163,7 @@ bool Thumb1FrameLowering::spillCalleeSavedRegisters(
// copy to LR.
if (LRLiveIn && UsedLRAsTemp) {
auto CopyRegIt = getNextOrderedReg(OrderedCopyRegs.rbegin(),
- OrderedCopyRegs.rend(),
- CopyRegs);
+ OrderedCopyRegs.rend(), CopyRegs);
assert(CopyRegIt != OrderedCopyRegs.rend());
unsigned NumRegsPushed = FrameRecord.size() + SpilledGPRs.size();
LLVM_DEBUG(
More information about the llvm-commits
mailing list