]> granicus.if.org Git - clang/commitdiff
Implement proper support for `-falign-functions`
authorSaleem Abdulrasool <compnerd@compnerd.org>
Thu, 19 Apr 2018 23:14:57 +0000 (23:14 +0000)
committerSaleem Abdulrasool <compnerd@compnerd.org>
Thu, 19 Apr 2018 23:14:57 +0000 (23:14 +0000)
This implements support for the previously ignored flag
`-falign-functions`.  This allows the frontend to request alignment on
function definitions in the translation unit where they are not
explicitly requested in code.  This is compatible with the GCC behaviour
and the ICC behaviour.

The scalar value passed to `-falign-functions` aligns functions to a
power-of-two boundary.  If flag is used, the functions are aligned to
16-byte boundaries.  If the scalar is specified, it must be an integer
less than or equal to 4096.  If the value is not a power-of-two, the
driver will round it up to the nearest power of two.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@330378 91177308-0d34-0410-b5e6-96231b3b80d8

include/clang/Basic/LangOptions.def
include/clang/Driver/CC1Options.td
include/clang/Driver/Options.td
lib/CodeGen/CodeGenModule.cpp
lib/Driver/ToolChains/Clang.cpp
lib/Driver/ToolChains/CommonArgs.cpp
lib/Driver/ToolChains/CommonArgs.h
lib/Frontend/CompilerInvocation.cpp
test/CodeGen/function-alignment.c [new file with mode: 0644]
test/Driver/clang_f_opts.c
test/Driver/function-alignment.c [new file with mode: 0644]

index 029e6516c0a22cfb7d3cba58ae7071e2722b31f4..e7d8302e5c55921dadcb8b7bfa82ba016329ef7a 100644 (file)
@@ -292,6 +292,8 @@ ENUM_LANGOPT(ClangABICompat, ClangABI, 4, ClangABI::Latest,
              "version of Clang that we should attempt to be ABI-compatible "
              "with")
 
+COMPATIBLE_VALUE_LANGOPT(FunctionAlignment, 5, 0, "Default alignment for functions")
+
 #undef LANGOPT
 #undef COMPATIBLE_LANGOPT
 #undef BENIGN_LANGOPT
index d6202a25b3898ba632845ea6adac0805915e7bdc..03b43ddd48ffc2f39538ee930a172b56205f053c 100644 (file)
@@ -645,6 +645,8 @@ def disable_objc_default_synthesize_properties : Flag<["-"], "disable-objc-defau
   HelpText<"disable the default synthesis of Objective-C properties">;
 def fencode_extended_block_signature : Flag<["-"], "fencode-extended-block-signature">,
   HelpText<"enable extended encoding of block type signature">;
+def function_alignment : Separate<["-"], "function-alignment">,
+    HelpText<"default alignment for functions">;
 def pic_level : Separate<["-"], "pic-level">,
   HelpText<"Value for __PIC__">;
 def pic_is_pie : Flag<["-"], "pic-is-pie">,
index d8e784a8abb8825791e2798c7c61f69a05dfe78e..99a438092be755f4b0622352e2bee69af1e1cb77 100644 (file)
@@ -611,6 +611,9 @@ def fno_PIC : Flag<["-"], "fno-PIC">, Group<f_Group>;
 def fPIE : Flag<["-"], "fPIE">, Group<f_Group>;
 def fno_PIE : Flag<["-"], "fno-PIE">, Group<f_Group>;
 def faccess_control : Flag<["-"], "faccess-control">, Group<f_Group>;
+def falign_functions : Flag<["-"], "falign-functions">, Group<f_Group>;
+def falign_functions_EQ : Joined<["-"], "falign-functions=">, Group<f_Group>;
+def fno_align_functions: Flag<["-"], "fno-align-functions">, Group<f_Group>;
 def fallow_unsupported : Flag<["-"], "fallow-unsupported">, Group<f_Group>;
 def fapple_kext : Flag<["-"], "fapple-kext">, Group<f_Group>, Flags<[CC1Option]>,
   HelpText<"Use Apple's kernel extensions ABI">;
@@ -2728,8 +2731,6 @@ def fprofile_dir : Joined<["-"], "fprofile-dir=">, Group<f_Group>;
 
 def fuse_ld_EQ : Joined<["-"], "fuse-ld=">, Group<f_Group>, Flags<[CoreOption]>;
 
-defm align_functions : BooleanFFlag<"align-functions">, Group<clang_ignored_gcc_optimization_f_Group>;
-def falign_functions_EQ : Joined<["-"], "falign-functions=">, Group<clang_ignored_gcc_optimization_f_Group>;
 defm align_labels : BooleanFFlag<"align-labels">, Group<clang_ignored_gcc_optimization_f_Group>;
 def falign_labels_EQ : Joined<["-"], "falign-labels=">, Group<clang_ignored_gcc_optimization_f_Group>;
 defm align_loops : BooleanFFlag<"align-loops">, Group<clang_ignored_gcc_optimization_f_Group>;
index a21527abba1f59df6fecb557eb8260e704c04d66..17d9db3399f29eb71cc1d2cd7a1c7745c93058d8 100644 (file)
@@ -1238,6 +1238,10 @@ void CodeGenModule::SetLLVMFunctionAttributesForDefinition(const Decl *D,
   if (alignment)
     F->setAlignment(alignment);
 
+  if (!D->hasAttr<AlignedAttr>())
+    if (LangOpts.FunctionAlignment)
+      F->setAlignment(1 << LangOpts.FunctionAlignment);
+
   // Some C++ ABIs require 2-byte alignment for member functions, in order to
   // reserve a bit for differentiating between virtual and non-virtual member
   // functions. If the current target's C++ ABI requires this and this is a
index 15e7cf2847c697dbf84c2f23e20ad857daa691e5..e96b5b7590f631d7c47960b3f289fb6a677d36c6 100644 (file)
@@ -3323,6 +3323,13 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
 
   CheckCodeGenerationOptions(D, Args);
 
+  unsigned FunctionAlignment = ParseFunctionAlignment(getToolChain(), Args);
+  assert(FunctionAlignment <= 31 && "function alignment will be truncated!");
+  if (FunctionAlignment) {
+    CmdArgs.push_back("-function-alignment");
+    CmdArgs.push_back(Args.MakeArgString(std::to_string(FunctionAlignment)));
+  }
+
   llvm::Reloc::Model RelocationModel;
   unsigned PICLevel;
   bool IsPIE;
index 869cf4c8f2ef690c5a1081d3e4c6b49fd492ec93..1527238c66391ad95b482f1167cf08c4f0133fcb 100644 (file)
@@ -1033,6 +1033,40 @@ tools::ParsePICArgs(const ToolChain &ToolChain, const ArgList &Args) {
   return std::make_tuple(RelocM, 0U, false);
 }
 
+// `-falign-functions` indicates that the functions should be aligned to a
+// 16-byte boundary.
+//
+// `-falign-functions=1` is the same as `-fno-align-functions`.
+//
+// The scalar `n` in `-falign-functions=n` must be an integral value between
+// [0, 65536].  If the value is not a power-of-two, it will be rounded up to
+// the nearest power-of-two.
+//
+// If we return `0`, the frontend will default to the backend's preferred
+// alignment.
+//
+// NOTE: icc only allows values between [0, 4096].  icc uses `-falign-functions`
+// to mean `-falign-functions=16`.  GCC defaults to the backend's preferred
+// alignment.  For unaligned functions, we default to the backend's preferred
+// alignment.
+unsigned tools::ParseFunctionAlignment(const ToolChain &TC,
+                                       const ArgList &Args) {
+  const Arg *A = Args.getLastArg(options::OPT_falign_functions,
+                                 options::OPT_falign_functions_EQ,
+                                 options::OPT_fno_align_functions);
+  if (!A || A->getOption().matches(options::OPT_fno_align_functions))
+    return 0;
+
+  if (A->getOption().matches(options::OPT_falign_functions))
+    return 0;
+
+  unsigned Value = 0;
+  if (StringRef(A->getValue()).getAsInteger(10, Value) || Value > 65536)
+    TC.getDriver().Diag(diag::err_drv_invalid_int_value)
+        << A->getAsString(Args) << A->getValue();
+  return Value ? llvm::Log2_32_Ceil(std::min(Value, 65536u)) : Value;
+}
+
 void tools::AddAssemblerKPIC(const ToolChain &ToolChain, const ArgList &Args,
                              ArgStringList &CmdArgs) {
   llvm::Reloc::Model RelocationModel;
index 14db1ea730212d8030fcd2c15bc60f8a0596197a..10a03d4a1787e4f16cc865f84048cd772387d060 100644 (file)
@@ -66,6 +66,9 @@ void AddGoldPlugin(const ToolChain &ToolChain, const llvm::opt::ArgList &Args,
 std::tuple<llvm::Reloc::Model, unsigned, bool>
 ParsePICArgs(const ToolChain &ToolChain, const llvm::opt::ArgList &Args);
 
+unsigned ParseFunctionAlignment(const ToolChain &TC,
+                                const llvm::opt::ArgList &Args);
+
 void AddAssemblerKPIC(const ToolChain &ToolChain,
                       const llvm::opt::ArgList &Args,
                       llvm::opt::ArgStringList &CmdArgs);
index 9146d2a36dfd18112ae593ff2c3af976f13380cf..67e15b41add119b54d073c39cd455900780d9b61 100644 (file)
@@ -2968,6 +2968,9 @@ bool CompilerInvocation::CreateFromArgs(CompilerInvocation &Res,
       LangOpts.ObjCExceptions = 1;
   }
 
+  LangOpts.FunctionAlignment =
+      getLastArgIntValue(Args, OPT_function_alignment, 0, Diags);
+
   if (LangOpts.CUDA) {
     // During CUDA device-side compilation, the aux triple is the
     // triple used for host compilation.
diff --git a/test/CodeGen/function-alignment.c b/test/CodeGen/function-alignment.c
new file mode 100644 (file)
index 0000000..9101b2c
--- /dev/null
@@ -0,0 +1,16 @@
+// RUN: %clang_cc1 -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-NONE
+// RUN: %clang_cc1 -emit-llvm -function-alignment 4 %s -o - | FileCheck %s -check-prefix CHECK-16
+// RUN: %clang_cc1 -emit-llvm -function-alignment 5 %s -o - | FileCheck %s -check-prefix CHECK-32
+
+void f(void) {}
+void __attribute__((__aligned__(64))) g(void) {}
+
+// CHECK-NONE-NOT: define void @f() #0 align
+// CHECK-NONE: define void @g() #0 align 64
+
+// CHECK-16: define void @f() #0 align 16
+// CHECK-16: define void @g() #0 align 64
+
+// CHECK-32: define void @f() #0 align 32
+// CHECK-32: define void @g() #0 align 64
+
index 2b2a7e7b98fefda9475a3faccb71d87ce1317fd5..be9ca2c93d61e729df08185ccb37d4a3ecc5de0e 100644 (file)
 // RUN: -fkeep-inline-functions                                               \
 // RUN: -fno-keep-inline-functions                                            \
 // RUN: -freorder-blocks                                                      \
-// RUN: -falign-functions                                                     \
-// RUN: -falign-functions=1                                                   \
 // RUN: -ffloat-store                                                         \
 // RUN: -fgcse                                                                \
 // RUN: -fivopts                                                              \
 // CHECK-WARNING-DAG: optimization flag '-fkeep-inline-functions' is not supported
 // CHECK-WARNING-DAG: optimization flag '-fno-keep-inline-functions' is not supported
 // CHECK-WARNING-DAG: optimization flag '-freorder-blocks' is not supported
-// CHECK-WARNING-DAG: optimization flag '-falign-functions' is not supported
-// CHECK-WARNING-DAG: optimization flag '-falign-functions=1' is not supported
 // CHECK-WARNING-DAG: optimization flag '-ffloat-store' is not supported
 // CHECK-WARNING-DAG: optimization flag '-fgcse' is not supported
 // CHECK-WARNING-DAG: optimization flag '-fivopts' is not supported
diff --git a/test/Driver/function-alignment.c b/test/Driver/function-alignment.c
new file mode 100644 (file)
index 0000000..3dd6ad1
--- /dev/null
@@ -0,0 +1,17 @@
+// RUN: %clang -### %s 2>&1 | FileCheck %s -check-prefix CHECK-0
+// RUN: %clang -### -falign-functions %s 2>&1 | FileCheck %s -check-prefix CHECK-1
+// RUN: %clang -### -falign-functions=1 %s 2>&1 | FileCheck %s -check-prefix CHECK-1
+// RUN: %clang -### -falign-functions=2 %s 2>&1 | FileCheck %s -check-prefix CHECK-2
+// RUN: %clang -### -falign-functions=3 %s 2>&1 | FileCheck %s -check-prefix CHECK-3
+// RUN: %clang -### -falign-functions=4 %s 2>&1 | FileCheck %s -check-prefix CHECK-4
+// RUN: %clang -### -falign-functions=65537 %s 2>&1 | FileCheck %s -check-prefix CHECK-ERR-65537
+// RUN: %clang -### -falign-functions=a %s 2>&1 | FileCheck %s -check-prefix CHECK-ERR-A
+
+// CHECK-0-NOT: "-function-alignment"
+// CHECK-1-NOT: "-function-alignment"
+// CHECK-2: "-function-alignment" "1"
+// CHECK-3: "-function-alignment" "2"
+// CHECK-4: "-function-alignment" "2"
+// CHECK-ERR-65537: error: invalid integral value '65537' in '-falign-functions=65537'
+// CHECK-ERR-A: error: invalid integral value 'a' in '-falign-functions=a'
+