-
Notifications
You must be signed in to change notification settings - Fork 14.3k
[clang][ARM] disable frame pointers by default for bare metal ARM targets #117140
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
…gets because: - This brings Clang in line with GCC for which this is the default for ARM - It frees up a register, so performance increase, especially on Thumb/6-M - It will also decrease code size
@llvm/pr-subscribers-backend-arm @llvm/pr-subscribers-clang-driver Author: Ties Stuij (stuij) Changesbecause:
Full diff: https://github.com/llvm/llvm-project/pull/117140.diff 4 Files Affected:
diff --git a/clang/lib/Driver/ToolChains/BareMetal.cpp b/clang/lib/Driver/ToolChains/BareMetal.cpp
index f9a73f60973e4c..13b510e7e70994 100644
--- a/clang/lib/Driver/ToolChains/BareMetal.cpp
+++ b/clang/lib/Driver/ToolChains/BareMetal.cpp
@@ -128,8 +128,11 @@ BareMetal::BareMetal(const Driver &D, const llvm::Triple &Triple,
}
}
+namespace clang {
+namespace driver {
+namespace toolchains {
/// Is the triple {arm,armeb,thumb,thumbeb}-none-none-{eabi,eabihf} ?
-static bool isARMBareMetal(const llvm::Triple &Triple) {
+bool isARMBareMetal(const llvm::Triple &Triple) {
if (Triple.getArch() != llvm::Triple::arm &&
Triple.getArch() != llvm::Triple::thumb &&
Triple.getArch() != llvm::Triple::armeb &&
@@ -148,6 +151,9 @@ static bool isARMBareMetal(const llvm::Triple &Triple) {
return true;
}
+} // namespace clang
+} // namespace driver
+} // namespace clang
/// Is the triple {aarch64.aarch64_be}-none-elf?
static bool isAArch64BareMetal(const llvm::Triple &Triple) {
diff --git a/clang/lib/Driver/ToolChains/BareMetal.h b/clang/lib/Driver/ToolChains/BareMetal.h
index b385c8cf76aab0..ae09bcedd78a28 100644
--- a/clang/lib/Driver/ToolChains/BareMetal.h
+++ b/clang/lib/Driver/ToolChains/BareMetal.h
@@ -19,6 +19,8 @@ namespace driver {
namespace toolchains {
+bool isARMBareMetal(const llvm::Triple &Triple);
+
class LLVM_LIBRARY_VISIBILITY BareMetal : public ToolChain {
public:
BareMetal(const Driver &D, const llvm::Triple &Triple,
diff --git a/clang/lib/Driver/ToolChains/CommonArgs.cpp b/clang/lib/Driver/ToolChains/CommonArgs.cpp
index 8d977149e62485..8d54d0a8649cc9 100644
--- a/clang/lib/Driver/ToolChains/CommonArgs.cpp
+++ b/clang/lib/Driver/ToolChains/CommonArgs.cpp
@@ -19,6 +19,7 @@
#include "Arch/SystemZ.h"
#include "Arch/VE.h"
#include "Arch/X86.h"
+#include "BareMetal.h"
#include "HIPAMD.h"
#include "Hexagon.h"
#include "MSP430.h"
@@ -151,6 +152,10 @@ static bool useFramePointerForTargetByDefault(const llvm::opt::ArgList &Args,
}
}
+ if (toolchains::isARMBareMetal(Triple)) {
+ return false;
+ }
+
return true;
}
diff --git a/clang/test/Driver/frame-pointer-elim.c b/clang/test/Driver/frame-pointer-elim.c
index cdedcc7ae4c89f..667c47b34bc703 100644
--- a/clang/test/Driver/frame-pointer-elim.c
+++ b/clang/test/Driver/frame-pointer-elim.c
@@ -162,5 +162,34 @@
// RUN: FileCheck --check-prefix=KEEP-NON-LEAF %s
// RUN: not %clang -### --target=riscv64-linux-android -mbig-endian -O1 -S %s 2>&1 | \
// RUN: FileCheck --check-prefix=KEEP-NON-LEAF %s
+
+// On ARM backend bare metal targets, frame pointer is omitted
+// RUN: %clang -### --target=arm-arm-none-eabi -S %s 2>&1 | \
+// RUN: FileCheck --check-prefix=KEEP-NONE %s
+// RUN: %clang -### --target=arm-arm-none-eabihf -S %s 2>&1 | \
+// RUN: FileCheck --check-prefix=KEEP-NONE %s
+// RUN: %clang -### --target=arm-arm-none-eabi -S -fno-omit-frame-pointer %s 2>&1 | \
+// RUN: FileCheck --check-prefix=KEEP-ALL %s
+// RUN: %clang -### --target=arm-arm-none-eabihf -S -fno-omit-frame-pointer %s 2>&1 | \
+// RUN: FileCheck --check-prefix=KEEP-ALL %s
+// RUN: %clang -### --target=arm-arm-none-eabi -S -O1 %s 2>&1 | \
+// RUN: FileCheck --check-prefix=KEEP-NONE %s
+// RUN: %clang -### --target=arm-arm-none-eabihf -S -O1 %s 2>&1 | \
+// RUN: FileCheck --check-prefix=KEEP-NONE %s
+// RUN: %clang -### --target=arm-arm-none-eabi -S -O1 -fno-omit-frame-pointer %s 2>&1 | \
+// RUN: FileCheck --check-prefix=KEEP-ALL %s
+// RUN: %clang -### --target=arm-arm-none-eabihf -S -O1 -fno-omit-frame-pointer %s 2>&1 | \
+// RUN: FileCheck --check-prefix=KEEP-ALL %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
+
void f0() {}
void f1() { f0(); }
|
This change was discussed in the LLVM Embedded Toolchains working group sync up two weeks ago, and at the time people were in agreement that it made sense: |
✅ With the latest revision this PR passed the C/C++ code formatter. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What are your thoughts on moving the definition into the BareMetal.h header, then adding cases for arm, armeb, thumb, and thumbeb to the existing getArch switch in CommonArgs.cpp#L85? Then we should be able to inline isARMBareMetal and elide the getArch checks in it.
I feel that in It's up to interpretation, but putting the different Arm variants there seems less elegant to me (that might not be saying much..). I'd say let's leave it alone for now, and if the bare metal logic gets more impenetrable at some point, refactor. |
also add a few more non-apple embedded tests and make isARMBareMetal slightly more elegant
To make it clearer what the fn is testing for.
I think this change in behaviour deserves an entry in clang/docs/ReleaseNotes.rst |
Pull request #109628 automatically turned on frame pointers for leaf functions in Clang when frame pointers are enabled. This triggered a latent bug in picolibc for armv4t and armv5te, which consequentially broke our tests for them. There is currently a pull request that fixes this bug (picolibc/picolibc#897), but we don't have to wait for this to merge to reinstate the tests, because we recently changed the behaviour of Clang to by default omit frame pointers altogether (llvm/llvm-project#117140), and that is how picolibc is built now. In general the advice is that you shouldn't build AArch32 targets with frame pointers enabled for various reasons.
Pull request #109628 automatically turned on frame pointers for leaf functions in Clang when frame pointers are enabled. This triggered a latent bug in picolibc for armv4t and armv5te, which consequentially broke our tests for them. There is currently a pull request that fixes this bug (picolibc/picolibc#897), but we don't have to wait for this to merge to reinstate the tests, because we recently changed the behaviour of Clang to by default omit frame pointers altogether (llvm/llvm-project#117140), and that is how picolibc is built now. In general the advice is that you shouldn't build AArch32 targets with frame pointers enabled for various reasons.
because: