[llvm-branch-commits] CodeGen, Driver: Introduce -fpreferred-function-alignment option. (PR #155528)
via llvm-branch-commits
llvm-branch-commits at lists.llvm.org
Tue Aug 26 17:13:02 PDT 2025
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-clang-driver
Author: Peter Collingbourne (pcc)
<details>
<summary>Changes</summary>
This option may be used to specify a function's preferred alignment.
The -falign-functions option and the aligned attribute now control
both the minimum alignment and the preferred alignment for consistency
with gcc. In contrast to the previous approach implemented in #<!-- -->149444
the preferred alignment is retained for member functions.
Part of this RFC:
https://discourse.llvm.org/t/rfc-enhancing-function-alignment-attributes/88019
---
Full diff: https://github.com/llvm/llvm-project/pull/155528.diff
7 Files Affected:
- (modified) clang/include/clang/Basic/LangOptions.def (+1)
- (modified) clang/include/clang/Driver/Options.td (+5)
- (modified) clang/lib/CodeGen/CodeGenModule.cpp (+13-7)
- (modified) clang/lib/Driver/ToolChains/Clang.cpp (+13)
- (added) clang/test/CodeGen/prefalign.c (+4)
- (modified) clang/test/CodeGenCXX/member-alignment.cpp (+3-3)
- (added) clang/test/Driver/prefalign.c (+5)
``````````diff
diff --git a/clang/include/clang/Basic/LangOptions.def b/clang/include/clang/Basic/LangOptions.def
index f094ba112988f..19bdc43abaac0 100644
--- a/clang/include/clang/Basic/LangOptions.def
+++ b/clang/include/clang/Basic/LangOptions.def
@@ -418,6 +418,7 @@ ENUM_LANGOPT(ClangABICompat, ClangABI, 4, ClangABI::Latest, NotCompatible,
"with")
VALUE_LANGOPT(FunctionAlignment, 5, 0, Compatible, "Default alignment for functions")
+VALUE_LANGOPT(PreferredFunctionAlignment, 5, 0, Compatible, "Preferred alignment for functions")
VALUE_LANGOPT(LoopAlignment, 32, 0, Compatible, "Default alignment for loops")
LANGOPT(FixedPoint, 1, 0, NotCompatible, "fixed point types")
diff --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td
index 82e8212bee12d..2dfc0872bac1f 100644
--- a/clang/include/clang/Driver/Options.td
+++ b/clang/include/clang/Driver/Options.td
@@ -1550,6 +1550,8 @@ defm access_control : BoolFOption<"access-control",
PosFlag<SetTrue>>;
def falign_functions : Flag<["-"], "falign-functions">, Group<f_Group>;
def falign_functions_EQ : Joined<["-"], "falign-functions=">, Group<f_Group>;
+def fpreferred_function_alignment_EQ :
+ Joined<["-"], "fpreferred-function-alignment=">, Group<f_Group>;
def falign_loops_EQ : Joined<["-"], "falign-loops=">, Group<f_Group>,
Visibility<[ClangOption, CC1Option]>, MetaVarName<"<N>">,
HelpText<"N must be a power of two. Align loops to the boundary">,
@@ -8446,6 +8448,9 @@ def fencode_extended_block_signature : Flag<["-"], "fencode-extended-block-signa
def function_alignment : Separate<["-"], "function-alignment">,
HelpText<"default alignment for functions">,
MarshallingInfoInt<LangOpts<"FunctionAlignment">>;
+def preferred_function_alignment : Separate<["-"], "preferred-function-alignment">,
+ HelpText<"preferred alignment for functions">,
+ MarshallingInfoInt<LangOpts<"PreferredFunctionAlignment">>;
def fhalf_no_semantic_interposition : Flag<["-"], "fhalf-no-semantic-interposition">,
HelpText<"Like -fno-semantic-interposition but don't use local aliases">,
MarshallingInfoFlag<LangOpts<"HalfNoSemanticInterposition">>;
diff --git a/clang/lib/CodeGen/CodeGenModule.cpp b/clang/lib/CodeGen/CodeGenModule.cpp
index 7064421fe0613..e7d94ed878e10 100644
--- a/clang/lib/CodeGen/CodeGenModule.cpp
+++ b/clang/lib/CodeGen/CodeGenModule.cpp
@@ -2794,13 +2794,19 @@ void CodeGenModule::SetLLVMFunctionAttributesForDefinition(const Decl *D,
F->addFnAttrs(B);
- unsigned alignment = D->getMaxAlignment() / Context.getCharWidth();
- if (alignment)
- F->setAlignment(llvm::Align(alignment));
-
- if (!D->hasAttr<AlignedAttr>())
- if (LangOpts.FunctionAlignment)
- F->setAlignment(llvm::Align(1ull << LangOpts.FunctionAlignment));
+ llvm::MaybeAlign ExplicitAlignment;
+ if (unsigned alignment = D->getMaxAlignment() / Context.getCharWidth())
+ ExplicitAlignment = llvm::Align(alignment);
+ else if (LangOpts.FunctionAlignment)
+ ExplicitAlignment = llvm::Align(1ull << LangOpts.FunctionAlignment);
+
+ if (ExplicitAlignment) {
+ F->setAlignment(ExplicitAlignment);
+ F->setPreferredAlignment(ExplicitAlignment);
+ } else if (LangOpts.PreferredFunctionAlignment) {
+ F->setPreferredAlignment(
+ llvm::Align(1ull << LangOpts.PreferredFunctionAlignment));
+ }
// Some C++ ABIs require 2-byte alignment for member functions, in order to
// reserve a bit for differentiating between virtual and non-virtual member
diff --git a/clang/lib/Driver/ToolChains/Clang.cpp b/clang/lib/Driver/ToolChains/Clang.cpp
index 1b44090534e82..c2ab8d9318a33 100644
--- a/clang/lib/Driver/ToolChains/Clang.cpp
+++ b/clang/lib/Driver/ToolChains/Clang.cpp
@@ -46,6 +46,7 @@
#include "llvm/Support/Compression.h"
#include "llvm/Support/Error.h"
#include "llvm/Support/FileSystem.h"
+#include "llvm/Support/MathExtras.h"
#include "llvm/Support/Path.h"
#include "llvm/Support/Process.h"
#include "llvm/Support/YAMLParser.h"
@@ -5503,6 +5504,18 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
CmdArgs.push_back(Args.MakeArgString(std::to_string(FunctionAlignment)));
}
+ if (const Arg *A = Args.getLastArg(options::OPT_fpreferred_function_alignment_EQ)) {
+ unsigned Value = 0;
+ if (StringRef(A->getValue()).getAsInteger(10, Value) || Value > 65536 ||
+ !llvm::isPowerOf2_32(Value))
+ TC.getDriver().Diag(diag::err_drv_invalid_int_value)
+ << A->getAsString(Args) << A->getValue();
+
+ CmdArgs.push_back("-preferred-function-alignment");
+ CmdArgs.push_back(Args.MakeArgString(
+ std::to_string(llvm::Log2_32_Ceil(std::min(Value, 65536u)))));
+ }
+
// We support -falign-loops=N where N is a power of 2. GCC supports more
// forms.
if (const Arg *A = Args.getLastArg(options::OPT_falign_loops_EQ)) {
diff --git a/clang/test/CodeGen/prefalign.c b/clang/test/CodeGen/prefalign.c
new file mode 100644
index 0000000000000..2370585a8e457
--- /dev/null
+++ b/clang/test/CodeGen/prefalign.c
@@ -0,0 +1,4 @@
+// RUN: %clang_cc1 -emit-llvm -triple x86_64-unknown-linux -preferred-function-alignment 4 %s -o - | FileCheck %s
+
+// CHECK: define {{.*}} void @f() {{.*}} prefalign 16
+void f() {}
diff --git a/clang/test/CodeGenCXX/member-alignment.cpp b/clang/test/CodeGenCXX/member-alignment.cpp
index d5c9a5a02b160..37ee733e18ff5 100644
--- a/clang/test/CodeGenCXX/member-alignment.cpp
+++ b/clang/test/CodeGenCXX/member-alignment.cpp
@@ -31,9 +31,9 @@ class t {
[[gnu::aligned(16)]]
void
t::baz(void) {
-// CHECK-NOEXTRAALIGN: @_ZN1t3bazEv({{.*}}) #0 align 16 {
-// CHECK-EXTRAALIGN: @_ZN1t3bazEv({{.*}}) #0 align 16 {
-// CHECK-MSVC: @"?baz at t@@QEAAXXZ"({{.*}}) #0 align 16 {
+// CHECK-NOEXTRAALIGN: @_ZN1t3bazEv({{.*}}) #0 align 16 prefalign 16 {
+// CHECK-EXTRAALIGN: @_ZN1t3bazEv({{.*}}) #0 align 16 prefalign 16 {
+// CHECK-MSVC: @"?baz at t@@QEAAXXZ"({{.*}}) #0 align 16 prefalign 16 {
}
void
diff --git a/clang/test/Driver/prefalign.c b/clang/test/Driver/prefalign.c
new file mode 100644
index 0000000000000..de52f2dcf28bc
--- /dev/null
+++ b/clang/test/Driver/prefalign.c
@@ -0,0 +1,5 @@
+// RUN: %clang -### -fpreferred-function-alignment=16 %s 2>&1 | FileCheck %s -check-prefix CHECK-16
+// RUN: not %clang -### -fpreferred-function-alignment=3 %s 2>&1 | FileCheck %s -check-prefix CHECK-INVALID
+
+// CHECK-16: "-preferred-function-alignment" "4"
+// CHECK-INVALID: invalid integral value '3' in '-fpreferred-function-alignment=3'
``````````
</details>
https://github.com/llvm/llvm-project/pull/155528
More information about the llvm-branch-commits
mailing list