-
Notifications
You must be signed in to change notification settings - Fork 14.9k
CodeGen, Driver: Introduce -fpreferred-function-alignment option. #155528
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
base: users/pcc/spr/main.codegen-driver-introduce-fpreferred-function-alignment-option
Are you sure you want to change the base?
Conversation
Created using spr 1.3.6-beta.1
@llvm/pr-subscribers-clang @llvm/pr-subscribers-clang-driver Author: Peter Collingbourne (pcc) ChangesThis option may be used to specify a function's preferred alignment. Part of this RFC: Full diff: https://github.com/llvm/llvm-project/pull/155528.diff 7 Files Affected:
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@t@@QEAAXXZ"({{.*}}) #0 align 16 {
+// CHECK-NOEXTRAALIGN: @_ZN1t3bazEv({{.*}}) #0 align 16 prefalign 16 {
+// CHECK-EXTRAALIGN: @_ZN1t3bazEv({{.*}}) #0 align 16 prefalign 16 {
+// CHECK-MSVC: @"?baz@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'
|
@llvm/pr-subscribers-clang-codegen Author: Peter Collingbourne (pcc) ChangesThis option may be used to specify a function's preferred alignment. Part of this RFC: Full diff: https://github.com/llvm/llvm-project/pull/155528.diff 7 Files Affected:
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@t@@QEAAXXZ"({{.*}}) #0 align 16 {
+// CHECK-NOEXTRAALIGN: @_ZN1t3bazEv({{.*}}) #0 align 16 prefalign 16 {
+// CHECK-EXTRAALIGN: @_ZN1t3bazEv({{.*}}) #0 align 16 prefalign 16 {
+// CHECK-MSVC: @"?baz@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'
|
You can test this locally with the following command:git-clang-format --diff HEAD~1 HEAD --extensions cpp,c -- clang/test/CodeGen/prefalign.c clang/test/Driver/prefalign.c clang/lib/CodeGen/CodeGenModule.cpp clang/lib/Driver/ToolChains/Clang.cpp clang/test/CodeGenCXX/member-alignment.cpp View the diff from clang-format here.diff --git a/clang/lib/Driver/ToolChains/Clang.cpp b/clang/lib/Driver/ToolChains/Clang.cpp
index c2ab8d931..e4ae40a6a 100644
--- a/clang/lib/Driver/ToolChains/Clang.cpp
+++ b/clang/lib/Driver/ToolChains/Clang.cpp
@@ -5504,7 +5504,8 @@ 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)) {
+ 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))
@@ -5515,7 +5516,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
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)) {
|
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