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: _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits