https://github.com/fpetrogalli updated https://github.com/llvm/llvm-project/pull/154216
>From 228a94f28e5f80c014769227a850b705cea4e34c Mon Sep 17 00:00:00 2001 From: Francesco Petrogalli <francesco.petroga...@apple.com> Date: Mon, 18 Aug 2025 10:01:25 -0700 Subject: [PATCH 1/4] [clang][driver][arm][macho] Default to -mframe-pointer=non-leaf. 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 --- clang/lib/Driver/ToolChains/CommonArgs.cpp | 3 ++ clang/test/Driver/frame-pointer-elim.c | 45 +++++++++++++++------- clang/test/Driver/frame-pointer.c | 4 ++ llvm/test/CodeGen/ARM/frame-chain.ll | 30 +++++++++++++++ llvm/test/CodeGen/Thumb/frame-chain.ll | 41 ++++++++++++++++++++ llvm/test/CodeGen/Thumb2/frame-pointer.ll | 8 ++++ 6 files changed, 117 insertions(+), 14 deletions(-) diff --git a/clang/lib/Driver/ToolChains/CommonArgs.cpp b/clang/lib/Driver/ToolChains/CommonArgs.cpp index 299422328aecf..04ae67273e873 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.isThumb() || Triple.isARM()) && 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..2b2e1e5600f32 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,22 @@ // 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 // AArch64 bare metal targets behave like hosted targets // RUN: %clang -### --target=aarch64-none-elf -S %s 2>&1 | \ @@ -221,5 +221,22 @@ // RUN: %clang -### --target=aarch64-pc-windows-msvc -S -fomit-frame-pointer %s 2>&1 | \ // RUN: FileCheck --check-prefix=KEEP-RESERVED %s +// When targeting Mach-O on Arm, the frame pointer is "none" if +// -fomit-frame-pointer is specified. +// RUN: %clang --target=armv7-apple-macho -### -S %s 2>&1 \ +// RUN: -fomit-frame-pointer \ +// RUN: | FileCheck -check-prefix=KEEP-NONE %s + +// When targeting Mach-O on Arm, -fno-omit-frame-pointer + +// -mno-omit-leaf-frame-pointer give frame-pointer=all +// 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 + +// When targeting Mach-O on Arm, -fomit-frame-pointer wins over +// -mno-omit-leaf-frame-pointer +// 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 void f0() {} void f1() { f0(); } diff --git a/clang/test/Driver/frame-pointer.c b/clang/test/Driver/frame-pointer.c index 2015fa520c2a2..4c69de8951777 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-32-MACHO %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-32-MACHO: -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..ad6f7bd83c411 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 @non_leaf_tailcall(i32 noundef %0) { +; LEAF-FP-LABEL: non_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: non_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: non_leaf_tailcall: +; LEAF-NOFP: @ %bb.0: +; LEAF-NOFP-NEXT: b leaf +; +; LEAF-NOFP-AAPCS-LABEL: non_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..03b9fa29a2803 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 @non_leaf_tailcall(i32 noundef %0) { +; FP-LABEL: non_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: non_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: non_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: non_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: >From 2796a49f9d4656ced4f6d3b17ee786966d5bdf8c Mon Sep 17 00:00:00 2001 From: Francesco Petrogalli <francesco.petroga...@apple.com> Date: Thu, 4 Sep 2025 13:35:08 -0700 Subject: [PATCH 2/4] s/non_leaf_tailcall/leaf_tailcall/ [NFC] --- llvm/test/CodeGen/ARM/frame-chain.ll | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/llvm/test/CodeGen/ARM/frame-chain.ll b/llvm/test/CodeGen/ARM/frame-chain.ll index ad6f7bd83c411..51de31aa393f5 100644 --- a/llvm/test/CodeGen/ARM/frame-chain.ll +++ b/llvm/test/CodeGen/ARM/frame-chain.ll @@ -224,8 +224,8 @@ define dso_local void @required_fp(i32 %0, i32 %1) { ret void } -define dso_local noundef i32 @non_leaf_tailcall(i32 noundef %0) { -; LEAF-FP-LABEL: non_leaf_tailcall: +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} @@ -234,7 +234,7 @@ define dso_local noundef i32 @non_leaf_tailcall(i32 noundef %0) { ; LEAF-FP-NEXT: pop {r11, lr} ; LEAF-FP-NEXT: b leaf ; -; LEAF-FP-AAPCS-LABEL: non_leaf_tailcall: +; 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} @@ -243,11 +243,11 @@ define dso_local noundef i32 @non_leaf_tailcall(i32 noundef %0) { ; LEAF-FP-AAPCS-NEXT: pop {r11, lr} ; LEAF-FP-AAPCS-NEXT: b leaf ; -; LEAF-NOFP-LABEL: non_leaf_tailcall: +; LEAF-NOFP-LABEL: leaf_tailcall: ; LEAF-NOFP: @ %bb.0: ; LEAF-NOFP-NEXT: b leaf ; -; LEAF-NOFP-AAPCS-LABEL: non_leaf_tailcall: +; 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) >From b5624a66d344f4cf0dc28d9fb7b614bfb74ae6c8 Mon Sep 17 00:00:00 2001 From: Francesco Petrogalli <francesco.petroga...@apple.com> Date: Thu, 4 Sep 2025 13:37:20 -0700 Subject: [PATCH 3/4] [driver][tests] Move tests closer to the group they belong to. [NFC] --- clang/test/Driver/frame-pointer-elim.c | 29 +++++++++++++------------- 1 file changed, 15 insertions(+), 14 deletions(-) diff --git a/clang/test/Driver/frame-pointer-elim.c b/clang/test/Driver/frame-pointer-elim.c index 2b2e1e5600f32..6636c617c169b 100644 --- a/clang/test/Driver/frame-pointer-elim.c +++ b/clang/test/Driver/frame-pointer-elim.c @@ -207,20 +207,6 @@ // RUN: %clang -### --target=arm-apple-none-macho -S -O1 -fno-omit-frame-pointer %s 2>&1 | \ // RUN: FileCheck --check-prefix=KEEP-NON-LEAF %s -// AArch64 bare metal targets behave like hosted targets -// RUN: %clang -### --target=aarch64-none-elf -S %s 2>&1 | \ -// RUN: FileCheck --check-prefix=KEEP-NON-LEAF %s -// RUN: %clang -### --target=aarch64-none-elf -S -O1 %s 2>&1 | \ -// RUN: FileCheck --check-prefix=KEEP-NON-LEAF %s -// RUN: %clang -### --target=aarch64-none-elf -S -fno-omit-frame-pointer %s 2>&1 | \ -// RUN: FileCheck --check-prefix=KEEP-NON-LEAF %s -// RUN: %clang -### --target=aarch64-none-elf -S -O1 -fno-omit-frame-pointer %s 2>&1 | \ -// RUN: FileCheck --check-prefix=KEEP-NON-LEAF %s - -// AArch64 Windows requires that the frame pointer be reserved -// RUN: %clang -### --target=aarch64-pc-windows-msvc -S -fomit-frame-pointer %s 2>&1 | \ -// RUN: FileCheck --check-prefix=KEEP-RESERVED %s - // When targeting Mach-O on Arm, the frame pointer is "none" if // -fomit-frame-pointer is specified. // RUN: %clang --target=armv7-apple-macho -### -S %s 2>&1 \ @@ -238,5 +224,20 @@ // 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 | \ +// RUN: FileCheck --check-prefix=KEEP-NON-LEAF %s +// RUN: %clang -### --target=aarch64-none-elf -S -O1 %s 2>&1 | \ +// RUN: FileCheck --check-prefix=KEEP-NON-LEAF %s +// RUN: %clang -### --target=aarch64-none-elf -S -fno-omit-frame-pointer %s 2>&1 | \ +// RUN: FileCheck --check-prefix=KEEP-NON-LEAF %s +// RUN: %clang -### --target=aarch64-none-elf -S -O1 -fno-omit-frame-pointer %s 2>&1 | \ +// RUN: FileCheck --check-prefix=KEEP-NON-LEAF %s + +// AArch64 Windows requires that the frame pointer be reserved +// RUN: %clang -### --target=aarch64-pc-windows-msvc -S -fomit-frame-pointer %s 2>&1 | \ +// RUN: FileCheck --check-prefix=KEEP-RESERVED %s + void f0() {} void f1() { f0(); } >From a61db8eefb915626de239f6a2c080028096b0e0b Mon Sep 17 00:00:00 2001 From: Francesco Petrogalli <francesco.petroga...@apple.com> Date: Thu, 4 Sep 2025 13:53:25 -0700 Subject: [PATCH 4/4] s/non_leaf_tailcall/leaf_tailcall/ [NFC] --- llvm/test/CodeGen/Thumb/frame-chain.ll | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/llvm/test/CodeGen/Thumb/frame-chain.ll b/llvm/test/CodeGen/Thumb/frame-chain.ll index 03b9fa29a2803..a680f2fa4a481 100644 --- a/llvm/test/CodeGen/Thumb/frame-chain.ll +++ b/llvm/test/CodeGen/Thumb/frame-chain.ll @@ -274,8 +274,8 @@ define dso_local void @required_fp(i32 %0, i32 %1) { ret void } -define dso_local noundef i32 @non_leaf_tailcall(i32 noundef %0) { -; FP-LABEL: non_leaf_tailcall: +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} @@ -284,7 +284,7 @@ define dso_local noundef i32 @non_leaf_tailcall(i32 noundef %0) { ; FP-NEXT: bl leaf ; FP-NEXT: pop {r7, pc} ; -; FP-AAPCS-LABEL: non_leaf_tailcall: +; FP-AAPCS-LABEL: leaf_tailcall: ; FP-AAPCS: @ %bb.0: ; FP-AAPCS-NEXT: .save {lr} ; FP-AAPCS-NEXT: push {lr} @@ -298,14 +298,14 @@ define dso_local noundef i32 @non_leaf_tailcall(i32 noundef %0) { ; FP-AAPCS-NEXT: mov r11, r1 ; FP-AAPCS-NEXT: pop {pc} ; -; NOFP-LABEL: non_leaf_tailcall: +; 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: non_leaf_tailcall: +; NOFP-AAPCS-LABEL: leaf_tailcall: ; NOFP-AAPCS: @ %bb.0: ; NOFP-AAPCS-NEXT: .save {r7, lr} ; NOFP-AAPCS-NEXT: push {r7, lr} _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits