Index: include/clang/Basic/DiagnosticDriverKinds.td =================================================================== --- include/clang/Basic/DiagnosticDriverKinds.td +++ include/clang/Basic/DiagnosticDriverKinds.td @@ -124,6 +124,10 @@ "%0 in '%1'">; def err_drv_no_neon_modifier : Error<"[no]neon is not accepted as modifier, please use [no]simd instead">; +def err_drv_align_opt_pos_int : Error<"argument '%1' to '-%0' should be a non-negative integer">; +def err_drv_align_opt_pow2 : Error<"argument '%1' to '-%0' is not a positive power of 2">; +def err_drv_align_opt_too_large : Error<"argument '%1' to '-%0' should be %2 or smaller">; + def warn_O4_is_O3 : Warning<"-O4 is equivalent to -O3">, InGroup; def warn_drv_lto_libpath : Warning<"libLTO.dylib relative to clang installed dir not found; using 'ld' default search path instead">, InGroup; Index: include/clang/Driver/Options.td =================================================================== --- include/clang/Driver/Options.td +++ include/clang/Driver/Options.td @@ -1907,6 +1907,10 @@ def Z_reserved_lib_cckext : Flag<["-"], "Z-reserved-lib-cckext">, Flags<[LinkerInput, NoArgumentUnused, Unsupported]>, Group; +def falign_functions : Flag<["-"], "falign-functions">, Group, Flags<[CC1Option]>; +def fno_align_functions : Flag<["-"], "fno-align-functions">, Group; +def falign_functions_EQ : Joined<["-"], "falign-functions=">, Group, Flags<[CC1Option]>; + // Ignored options // FIXME: multiclasess produce suffixes, not prefixes. This is fine for now // since it is only used in ignored options. @@ -1921,8 +1925,6 @@ def fuse_ld_EQ : Joined<["-"], "fuse-ld=">, Group; -defm align_functions : BooleanFFlag<"align-functions">, Group; -def falign_functions_EQ : Joined<["-"], "falign-functions=">, Group; defm align_labels : BooleanFFlag<"align-labels">, Group; def falign_labels_EQ : Joined<["-"], "falign-labels=">, Group; defm align_loops : BooleanFFlag<"align-loops">, Group; Index: include/clang/Frontend/CodeGenOptions.def =================================================================== --- include/clang/Frontend/CodeGenOptions.def +++ include/clang/Frontend/CodeGenOptions.def @@ -145,6 +145,9 @@ CODEGENOPT(VectorizeLoop , 1, 0) ///< Run loop vectorizer. CODEGENOPT(VectorizeSLP , 1, 0) ///< Run SLP vectorizer. +CODEGENOPT(AlignFunctions , 1, 0) ///< Set when -falign-functions is enabled. +CODEGENOPT(AlignFunctionsBytes, 32, 0) ///< Set when -falign-functions= is defined. + /// Attempt to use register sized accesses to bit-fields in structures, when /// possible. CODEGENOPT(UseRegisterSizedBitfieldAccess , 1, 0) Index: lib/CodeGen/CodeGenModule.cpp =================================================================== --- lib/CodeGen/CodeGenModule.cpp +++ lib/CodeGen/CodeGenModule.cpp @@ -846,9 +846,12 @@ if (MD->isVirtual()) F->setUnnamedAddr(true); - unsigned alignment = D->getMaxAlignment() / Context.getCharWidth(); - if (alignment) - F->setAlignment(alignment); + unsigned Alignment = D->getMaxAlignment() / Context.getCharWidth(); + // Honor -falign-functions=*. + if (CodeGenOpts.AlignFunctionsBytes) + Alignment = std::max(Alignment, CodeGenOpts.AlignFunctionsBytes); + if (Alignment) + F->setAlignment(Alignment); // Some C++ ABIs require 2-byte alignment for member functions, in order to // reserve a bit for differentiating between virtual and non-virtual member Index: lib/Driver/Tools.cpp =================================================================== --- lib/Driver/Tools.cpp +++ lib/Driver/Tools.cpp @@ -2980,6 +2980,16 @@ return false; } +static bool shouldEnableAlignOpt(const ArgList &Args) { + if (Arg *A = Args.getLastArg(options::OPT_O_Group)) { + if (A->getOption().matches(options::OPT_O)) { + StringRef S(A->getValue()); + return S != "s" && S != "z"; + } + } + return true; +} + /// Add -x lang to \p CmdArgs for \p Input. static void addDashXForInput(const ArgList &Args, const InputInfo &Input, ArgStringList &CmdArgs) { @@ -4690,6 +4700,40 @@ CmdArgs.push_back("-fblocks-runtime-optional"); } + // -fno-align-function is default. + if (Arg *A = Args.getLastArg(options::OPT_falign_functions, + options::OPT_falign_functions_EQ, + options::OPT_falign_functions)) { + // These alignment optimizations are disabled with -Os and -Oz. + if (shouldEnableAlignOpt(Args)) { + if (A->getOption().matches(options::OPT_falign_functions)) + CmdArgs.push_back("-falign-functions"); + else if (A->getOption().matches(options::OPT_falign_functions_EQ)) { + StringRef BytesStr(A->getValue()); + int Bytes = 0; + bool Error = false; + // The argument should be a non-negative integer. + if (BytesStr.getAsInteger(10, Bytes) || Bytes < 0) { + Error = true; + D.Diag(diag::err_drv_align_opt_pos_int) << A->getOption().getName() << BytesStr; + } + // The argument should be a power of 2. + if (!Error && !llvm::isPowerOf2_32(Bytes)) { + Error = true; + D.Diag(diag::err_drv_align_opt_pow2) << A->getOption().getName() << BytesStr; + } + // The argument shouldn't be too large. + if (!Error && Bytes > 0x10000000) { + Error = true; + D.Diag(diag::err_drv_align_opt_too_large) << A->getOption().getName() << BytesStr << 268435456; + } + // -falign-functions=1 is equivalent to -fno-align-functions. + if (!Error && Bytes != 1) + CmdArgs.push_back(Args.MakeArgString("-falign-functions=" + BytesStr)); + } + } + } + // -fmodules enables the use of precompiled modules (off by default). // Users can pass -fno-cxx-modules to turn off modules support for // C++/Objective-C++ programs. Index: lib/Frontend/CompilerInvocation.cpp =================================================================== --- lib/Frontend/CompilerInvocation.cpp +++ lib/Frontend/CompilerInvocation.cpp @@ -537,6 +537,14 @@ Opts.VectorizeLoop = Args.hasArg(OPT_vectorize_loops); Opts.VectorizeSLP = Args.hasArg(OPT_vectorize_slp); + Opts.AlignFunctions = Args.hasArg(OPT_falign_functions); + if (Arg *A = Args.getLastArg(OPT_falign_functions_EQ)) { + StringRef Val = A->getValue(); + unsigned Bytes = 0; + Val.getAsInteger(10, Bytes); + Opts.AlignFunctionsBytes = Bytes; + } + Opts.MainFileName = Args.getLastArgValue(OPT_main_file_name); Opts.VerifyModule = !Args.hasArg(OPT_disable_llvm_verifier); Index: test/CodeGen/func-aligned.c =================================================================== --- test/CodeGen/func-aligned.c +++ test/CodeGen/func-aligned.c @@ -1,7 +1,20 @@ // RUN: %clang_cc1 -triple x86_64-apple-darwin %s -emit-llvm -o - | FileCheck %s +// RUN: %clang_cc1 -triple x86_64-apple-darwin %s -falign-functions=128 -emit-llvm -o - | FileCheck -check-prefix=FALIGN-FUNC %s // rdar://7270273 void foo() __attribute__((aligned (64))); void foo() { // CHECK: define void @foo() {{.*}} align 64 } + +// The function should be aligned based on the command line option. +void test1() { +// FALIGN-FUNC: define void @test1() {{.*}} align 128 +} + +// The function alignment specified on the command line should override that +// specified by the attribute. +void test2() __attribute__((aligned (64))); +void test2() { +// FALIGN-FUNC: define void @test2() {{.*}} align 128 +} Index: test/Driver/clang_f_opts.c =================================================================== --- test/Driver/clang_f_opts.c +++ test/Driver/clang_f_opts.c @@ -290,8 +290,6 @@ // RUN: -fno-keep-inline-functions \ // RUN: -freorder-blocks \ // RUN: -fprofile-dir=/rand/dir \ -// RUN: -falign-functions \ -// RUN: -falign-functions=1 \ // RUN: -ffloat-store \ // RUN: -fgcse \ // RUN: -fivopts \ @@ -358,8 +356,6 @@ // 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 '-fprofile-dir=/rand/dir' 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 @@ -462,3 +458,42 @@ // CHECK-WCHAR2: -fshort-wchar // CHECK-WCHAR2-NOT: -fno-short-wchar // DELIMITERS: {{^ *"}} + +// RUN: %clang -### -S -falign-functions %s 2>&1 | FileCheck -check-prefix=CHECK-FALIGN-FUNCTIONS %s +// RUN: %clang -### -S -O0 -falign-functions %s 2>&1 | FileCheck -check-prefix=CHECK-FALIGN-FUNCTIONS %s +// RUN: %clang -### -S -O1 -falign-functions %s 2>&1 | FileCheck -check-prefix=CHECK-FALIGN-FUNCTIONS %s +// RUN: %clang -### -S -O2 -falign-functions %s 2>&1 | FileCheck -check-prefix=CHECK-FALIGN-FUNCTIONS %s +// RUN: %clang -### -S -O3 -falign-functions %s 2>&1 | FileCheck -check-prefix=CHECK-FALIGN-FUNCTIONS %s +// RUN: %clang -### -S -Ofast -falign-functions %s 2>&1 | FileCheck -check-prefix=CHECK-FALIGN-FUNCTIONS %s +// CHECK-FALIGN-FUNCTIONS: -falign-functions + +// RUN: %clang -### -S -falign-functions=2 %s 2>&1 | FileCheck -check-prefix=CHECK-FALIGN-FUNCTIONS_EQ %s +// RUN: %clang -### -S -O0 -falign-functions=4 %s 2>&1 | FileCheck -check-prefix=CHECK-FALIGN-FUNCTIONS_EQ %s +// RUN: %clang -### -S -O1 -falign-functions=8 %s 2>&1 | FileCheck -check-prefix=CHECK-FALIGN-FUNCTIONS_EQ %s +// RUN: %clang -### -S -O2 -falign-functions=16 %s 2>&1 | FileCheck -check-prefix=CHECK-FALIGN-FUNCTIONS_EQ %s +// RUN: %clang -### -S -O3 -falign-functions=32 %s 2>&1 | FileCheck -check-prefix=CHECK-FALIGN-FUNCTIONS_EQ %s +// RUN: %clang -### -S -Ofast -falign-functions=16 %s 2>&1 | FileCheck -check-prefix=CHECK-FALIGN-FUNCTIONS_EQ %s +// CHECK-FALIGN-FUNCTIONS_EQ: -falign-functions= + +// Argument to -falign-functions= should be a non-negative integer +// RUN: %clang -### -S -falign-functions=-8 %s 2>&1 | FileCheck -check-prefix=CHECK-FALIGN-FUNCTIONS_EQ1 %s +// CHECK-FALIGN-FUNCTIONS_EQ1: argument '-8' to '-falign-functions=' should be a non-negative integer +// RUN: %clang -### -S -falign-functions=abc %s 2>&1 | FileCheck -check-prefix=CHECK-FALIGN-FUNCTIONS_EQ2 %s +// CHECK-FALIGN-FUNCTIONS_EQ2: argument 'abc' to '-falign-functions=' should be a non-negative integer + +// Argument to -falign-functions= should be a power of 2. +// RUN: %clang -### -S -falign-functions=11 %s 2>&1 | FileCheck -check-prefix=CHECK-FALIGN-FUNCTIONS_EQ3 %s +// CHECK-FALIGN-FUNCTIONS_EQ3: argument '11' to '-falign-functions=' is not a positive power of 2 + +// Argument to -falign-functions= shouldn't be too big. +// RUN: %clang -### -S -falign-functions=1073741824 %s 2>&1 | FileCheck -check-prefix=CHECK-FALIGN-FUNCTIONS_EQ4 %s +// CHECK-FALIGN-FUNCTIONS_EQ4: argument '1073741824' to '-falign-functions=' should be 268435456 or smaller + +// -falign-functions is disabled when optimizing for size. +// RUN: %clang -### -S -Os -falign-functions %s 2>&1 | FileCheck -check-prefix=CHECK-FALIGN-FUNCTIONS-OSIZE %s +// RUN: %clang -### -S -Oz -falign-functions %s 2>&1 | FileCheck -check-prefix=CHECK-FALIGN-FUNCTIONS-OSIZE %s + +// -falign-functions=1 is equivalent to -fno-align-functions. +// RUN: %clang -### -S -O3 -falign-functions=1 %s 2>&1 | FileCheck -check-prefix=CHECK-FALIGN-FUNCTIONS-OSIZE %s + +// CHECK-FALIGN-FUNCTIONS-OSIZE-NOT: -falign-functions