[llvm] f82023d - [clang][driver][arm][macho] Default to -mframe-pointer=non-leaf. (#154216)
via llvm-commits
llvm-commits at lists.llvm.org
Tue Sep 9 11:39:29 PDT 2025
Author: Francesco Petrogalli
Date: 2025-09-09T18:39:26Z
New Revision: f82023d72e1190ca46a05dcb253df5aaf4205876
URL: https://github.com/llvm/llvm-project/commit/f82023d72e1190ca46a05dcb253df5aaf4205876
DIFF: https://github.com/llvm/llvm-project/commit/f82023d72e1190ca46a05dcb253df5aaf4205876.diff
LOG: [clang][driver][arm][macho] Default to -mframe-pointer=non-leaf. (#154216)
The commit in [1] changes the behavior of the Arm backend for the
attribute frame-pointer=all. Before [1], leaf functions marked with
frame-pointer=all were not emitting the frame-pointer.
After [1], frame-pointer=all started generating frame pointer for all
functions, including leaf functions.
However, the default behavior for the driver in clang is to emit the
command line option `-mframe-pointer=all` on Arm, if no options for
handling the frame pointer is specified at command line. This causes
observable regressions.
This patch addresses these regressions by configuring the driver so
to emit `-mframe-pointer=non-leaf` when targeting Arm.
Codegen tests dealing with frame pointer generation have been extended
to handle functions with a tail call, since this configuration was
missing.
[1] 4a2bd78f5b0d0661c23dff9c4b93a393a49dbf9a
Added:
Modified:
clang/lib/Driver/ToolChains/CommonArgs.cpp
clang/test/Driver/frame-pointer-elim.c
clang/test/Driver/frame-pointer.c
llvm/test/CodeGen/ARM/frame-chain.ll
llvm/test/CodeGen/Thumb/frame-chain.ll
llvm/test/CodeGen/Thumb2/frame-pointer.ll
Removed:
################################################################################
diff --git a/clang/lib/Driver/ToolChains/CommonArgs.cpp b/clang/lib/Driver/ToolChains/CommonArgs.cpp
index 299422328aecf..416b4d91b921e 100644
--- a/clang/lib/Driver/ToolChains/CommonArgs.cpp
+++ b/clang/lib/Driver/ToolChains/CommonArgs.cpp
@@ -156,6 +156,9 @@ static bool useLeafFramePointerForTargetByDefault(const llvm::Triple &Triple) {
(Triple.isAndroid() && !Triple.isARM()))
return false;
+ if ((Triple.isARM() || Triple.isThumb()) && Triple.isOSBinFormatMachO())
+ return false;
+
return true;
}
diff --git a/clang/test/Driver/frame-pointer-elim.c b/clang/test/Driver/frame-pointer-elim.c
index 6e21671f43775..6d719828c6a06 100644
--- a/clang/test/Driver/frame-pointer-elim.c
+++ b/clang/test/Driver/frame-pointer-elim.c
@@ -73,12 +73,12 @@
// RUN: %clang -### -target armv7s-apple-ios -fomit-frame-pointer %s 2>&1 | \
// RUN: FileCheck --check-prefix=WARN-OMIT-7S %s
// WARN-OMIT-7S: warning: optimization flag '-fomit-frame-pointer' is not supported for target 'armv7s'
-// WARN-OMIT-7S: "-mframe-pointer=all"
+// WARN-OMIT-7S: "-mframe-pointer=non-leaf"
// RUN: %clang -### -target armv7k-apple-watchos -fomit-frame-pointer %s 2>&1 | \
// RUN: FileCheck --check-prefix=WARN-OMIT-7K %s
// WARN-OMIT-7K: warning: optimization flag '-fomit-frame-pointer' is not supported for target 'armv7k'
-// WARN-OMIT-7K: "-mframe-pointer=all"
+// WARN-OMIT-7K: "-mframe-pointer=non-leaf"
// RUN: %clang -### -target armv7s-apple-ios8.0 -momit-leaf-frame-pointer %s 2>&1 | \
// RUN: FileCheck --check-prefix=WARN-OMIT-LEAF-7S %s
@@ -190,22 +190,34 @@
// RUN: FileCheck --check-prefix=KEEP-NONE %s
// Check that for Apple bare metal targets, we're keeping frame pointers by default
-// RUN: %clang -### --target=thumbv6m-apple-none-macho -S %s 2>&1 | \
-// RUN: FileCheck --check-prefix=KEEP-ALL %s
-// RUN: %clang -### --target=thumbv6m-apple-none-macho -S -fno-omit-frame-pointer %s 2>&1 | \
-// RUN: FileCheck --check-prefix=KEEP-ALL %s
+// RUN: %clang -### --target=armv6m-apple-none-macho -S %s 2>&1 | \
+// RUN: FileCheck --check-prefix=KEEP-NON-LEAF %s
+// RUN: %clang -### --target=armv6m-apple-none-macho -S -fno-omit-frame-pointer %s 2>&1 | \
+// RUN: FileCheck --check-prefix=KEEP-NON-LEAF %s
// RUN: %clang -### --target=arm-apple-none-macho -S %s 2>&1 | \
-// RUN: FileCheck --check-prefix=KEEP-ALL %s
+// RUN: FileCheck --check-prefix=KEEP-NON-LEAF %s
// RUN: %clang -### --target=arm-apple-none-macho -S -fno-omit-frame-pointer %s 2>&1 | \
-// RUN: FileCheck --check-prefix=KEEP-ALL %s
-// RUN: %clang -### --target=thumbv6m-apple-none-macho -S -O1 %s 2>&1 | \
-// RUN: FileCheck --check-prefix=KEEP-ALL %s
-// RUN: %clang -### --target=thumbv6m-apple-none-macho -S -O1 -fno-omit-frame-pointer %s 2>&1 | \
-// RUN: FileCheck --check-prefix=KEEP-ALL %s
+// RUN: FileCheck --check-prefix=KEEP-NON-LEAF %s
+// RUN: %clang -### --target=armv6m-apple-none-macho -S -O1 %s 2>&1 | \
+// RUN: FileCheck --check-prefix=KEEP-NON-LEAF %s
+// RUN: %clang -### --target=armv6m-apple-none-macho -S -O1 -fno-omit-frame-pointer %s 2>&1 | \
+// RUN: FileCheck --check-prefix=KEEP-NON-LEAF %s
// RUN: %clang -### --target=arm-apple-none-macho -S -O1 %s 2>&1 | \
-// RUN: FileCheck --check-prefix=KEEP-ALL %s
+// RUN: FileCheck --check-prefix=KEEP-NON-LEAF %s
// RUN: %clang -### --target=arm-apple-none-macho -S -O1 -fno-omit-frame-pointer %s 2>&1 | \
-// RUN: FileCheck --check-prefix=KEEP-ALL %s
+// RUN: FileCheck --check-prefix=KEEP-NON-LEAF %s
+
+// RUN: %clang --target=armv7-apple-macho -### -S %s 2>&1 \
+// RUN: -fomit-frame-pointer \
+// RUN: | FileCheck -check-prefix=KEEP-NONE %s
+
+// RUN: %clang --target=armv7-apple-macho -### -S %s 2>&1 \
+// RUN: -fno-omit-frame-pointer -mno-omit-leaf-frame-pointer \
+// RUN: | FileCheck -check-prefix=KEEP-ALL %s
+
+// RUN: %clang --target=armv7-apple-macho -### -S %s 2>&1 \
+// RUN: -fomit-frame-pointer -mno-omit-leaf-frame-pointer \
+// RUN: | FileCheck -check-prefix=KEEP-NONE %s
// AArch64 bare metal targets behave like hosted targets
// RUN: %clang -### --target=aarch64-none-elf -S %s 2>&1 | \
diff --git a/clang/test/Driver/frame-pointer.c b/clang/test/Driver/frame-pointer.c
index 2015fa520c2a2..22592465e8b2d 100644
--- a/clang/test/Driver/frame-pointer.c
+++ b/clang/test/Driver/frame-pointer.c
@@ -80,12 +80,16 @@
// RUN: %clang --target=loongarch64 -### -S -O3 %s -o %t.s 2>&1 | FileCheck -check-prefix=CHECK3-64 %s
// RUN: %clang --target=loongarch64 -### -S -Os %s -o %t.s 2>&1 | FileCheck -check-prefix=CHECKs-64 %s
+// RUN: %clang --target=armv7-apple-macho -### -S %s -o %t.s 2>&1 | FileCheck -check-prefix=CHECK-MACHO-32 %s
+
// CHECK0-32: -mframe-pointer=all
// CHECK1-32-NOT: -mframe-pointer=all
// CHECK2-32-NOT: -mframe-pointer=all
// CHECK3-32-NOT: -mframe-pointer=all
// CHECKs-32-NOT: -mframe-pointer=all
+// CHECK-MACHO-32: -mframe-pointer=non-leaf
+
// CHECK0-64: -mframe-pointer=all
// CHECK1-64-NOT: -mframe-pointer=all
// CHECK2-64-NOT: -mframe-pointer=all
diff --git a/llvm/test/CodeGen/ARM/frame-chain.ll b/llvm/test/CodeGen/ARM/frame-chain.ll
index 7b722cd5fcef2..51de31aa393f5 100644
--- a/llvm/test/CodeGen/ARM/frame-chain.ll
+++ b/llvm/test/CodeGen/ARM/frame-chain.ll
@@ -223,3 +223,33 @@ define dso_local void @required_fp(i32 %0, i32 %1) {
store i64 %8, ptr %6, align 8
ret void
}
+
+define dso_local noundef i32 @leaf_tailcall(i32 noundef %0) {
+; LEAF-FP-LABEL: leaf_tailcall:
+; LEAF-FP: @ %bb.0:
+; LEAF-FP-NEXT: .save {r11, lr}
+; LEAF-FP-NEXT: push {r11, lr}
+; LEAF-FP-NEXT: .setfp r11, sp
+; LEAF-FP-NEXT: mov r11, sp
+; LEAF-FP-NEXT: pop {r11, lr}
+; LEAF-FP-NEXT: b leaf
+;
+; LEAF-FP-AAPCS-LABEL: leaf_tailcall:
+; LEAF-FP-AAPCS: @ %bb.0:
+; LEAF-FP-AAPCS-NEXT: .save {r11, lr}
+; LEAF-FP-AAPCS-NEXT: push {r11, lr}
+; LEAF-FP-AAPCS-NEXT: .setfp r11, sp
+; LEAF-FP-AAPCS-NEXT: mov r11, sp
+; LEAF-FP-AAPCS-NEXT: pop {r11, lr}
+; LEAF-FP-AAPCS-NEXT: b leaf
+;
+; LEAF-NOFP-LABEL: leaf_tailcall:
+; LEAF-NOFP: @ %bb.0:
+; LEAF-NOFP-NEXT: b leaf
+;
+; LEAF-NOFP-AAPCS-LABEL: leaf_tailcall:
+; LEAF-NOFP-AAPCS: @ %bb.0:
+; LEAF-NOFP-AAPCS-NEXT: b leaf
+ %a = tail call noundef i32 @leaf(i32 noundef %0)
+ ret i32 %a
+}
diff --git a/llvm/test/CodeGen/Thumb/frame-chain.ll b/llvm/test/CodeGen/Thumb/frame-chain.ll
index 134362cfd0cb6..a680f2fa4a481 100644
--- a/llvm/test/CodeGen/Thumb/frame-chain.ll
+++ b/llvm/test/CodeGen/Thumb/frame-chain.ll
@@ -273,3 +273,44 @@ define dso_local void @required_fp(i32 %0, i32 %1) {
store i64 %8, ptr %6, align 8
ret void
}
+
+define dso_local noundef i32 @leaf_tailcall(i32 noundef %0) {
+; FP-LABEL: leaf_tailcall:
+; FP: @ %bb.0:
+; FP-NEXT: .save {r7, lr}
+; FP-NEXT: push {r7, lr}
+; FP-NEXT: .setfp r7, sp
+; FP-NEXT: add r7, sp, #0
+; FP-NEXT: bl leaf
+; FP-NEXT: pop {r7, pc}
+;
+; FP-AAPCS-LABEL: leaf_tailcall:
+; FP-AAPCS: @ %bb.0:
+; 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: bl leaf
+; FP-AAPCS-NEXT: pop {r1}
+; FP-AAPCS-NEXT: mov r11, r1
+; FP-AAPCS-NEXT: pop {pc}
+;
+; NOFP-LABEL: leaf_tailcall:
+; NOFP: @ %bb.0:
+; NOFP-NEXT: .save {r7, lr}
+; NOFP-NEXT: push {r7, lr}
+; NOFP-NEXT: bl leaf
+; NOFP-NEXT: pop {r7, pc}
+;
+; NOFP-AAPCS-LABEL: leaf_tailcall:
+; NOFP-AAPCS: @ %bb.0:
+; NOFP-AAPCS-NEXT: .save {r7, lr}
+; NOFP-AAPCS-NEXT: push {r7, lr}
+; NOFP-AAPCS-NEXT: bl leaf
+; NOFP-AAPCS-NEXT: pop {r7, pc}
+ %a = tail call noundef i32 @leaf(i32 noundef %0)
+ ret i32 %a
+}
diff --git a/llvm/test/CodeGen/Thumb2/frame-pointer.ll b/llvm/test/CodeGen/Thumb2/frame-pointer.ll
index 85c919a50d88c..0ca72055e3823 100644
--- a/llvm/test/CodeGen/Thumb2/frame-pointer.ll
+++ b/llvm/test/CodeGen/Thumb2/frame-pointer.ll
@@ -93,6 +93,14 @@ define void @call_nononleaffpelim() "frame-pointer"="non-leaf" {
ret void
}
+define void @call_nononleaffpelim_tailcall() "frame-pointer"="non-leaf" {
+; CHECK-LABEL: call_nononleaffpelim_tailcall:
+; CHECK-NOT: push
+; CHECK: b foo
+ tail call void @foo()
+ ret void
+}
+
; Has a high register clobbered, no need for a frame pointer.
define void @highreg() {
; CHECK-LABEL: highreg:
More information about the llvm-commits
mailing list