From c38efb4899eac7b82daaf1320ad79f6271f9648a Mon Sep 17 00:00:00 2001 From: Fangrui Song Date: Thu, 5 Aug 2021 12:17:50 -0700 Subject: [PATCH] [clang] Implement -falign-loops=N (N is a power of 2) for non-LTO GCC supports multiple forms of -falign-loops=. -falign-loops= is currently ignored in Clang. This patch implements the simplest but the most useful form where N is a power of 2. The underlying implementation uses a `llvm::TargetOptions` option for now. Bitcode generation ignores this option. Differential Revision: https://reviews.llvm.org/D106701 --- clang/include/clang/Basic/CodeGenOptions.def | 2 ++ clang/include/clang/Basic/DiagnosticDriverKinds.td | 1 + clang/include/clang/Basic/LangOptions.def | 1 + clang/include/clang/Driver/Options.td | 4 +++- clang/lib/CodeGen/BackendUtil.cpp | 1 + clang/lib/Driver/ToolChains/Clang.cpp | 16 ++++++++++++++++ clang/test/CodeGen/align-loops.c | 15 +++++++++++++++ clang/test/Driver/clang_f_opts.c | 1 - clang/test/Driver/falign-loops.c | 17 +++++++++++++++++ 9 files changed, 56 insertions(+), 2 deletions(-) create mode 100644 clang/test/CodeGen/align-loops.c create mode 100644 clang/test/Driver/falign-loops.c diff --git a/clang/include/clang/Basic/CodeGenOptions.def b/clang/include/clang/Basic/CodeGenOptions.def index e3202cf..73edae6 100644 --- a/clang/include/clang/Basic/CodeGenOptions.def +++ b/clang/include/clang/Basic/CodeGenOptions.def @@ -293,6 +293,8 @@ CODEGENOPT(StackRealignment , 1, 0) ///< Control whether to force stack ///< realignment. CODEGENOPT(UseInitArray , 1, 0) ///< Control whether to use .init_array or ///< .ctors. +VALUE_CODEGENOPT(LoopAlignment , 32, 0) ///< Overrides default loop + ///< alignment, if not 0. VALUE_CODEGENOPT(StackAlignment , 32, 0) ///< Overrides default stack ///< alignment, if not 0. VALUE_CODEGENOPT(StackProbeSize , 32, 4096) ///< Overrides default stack diff --git a/clang/include/clang/Basic/DiagnosticDriverKinds.td b/clang/include/clang/Basic/DiagnosticDriverKinds.td index 78d7ba6..660f7e4 100644 --- a/clang/include/clang/Basic/DiagnosticDriverKinds.td +++ b/clang/include/clang/Basic/DiagnosticDriverKinds.td @@ -228,6 +228,7 @@ def err_drv_invalid_value : Error<"invalid value '%1' in '%0'">; def err_drv_invalid_int_value : Error<"invalid integral value '%1' in '%0'">; def err_drv_invalid_value_with_suggestion : Error< "invalid value '%1' in '%0', expected one of: %2">; +def err_drv_alignment_not_power_of_two : Error<"alignment is not a power of 2 in '%0'">; def err_drv_invalid_remap_file : Error< "invalid option '%0' not of the form ;">; def err_drv_invalid_gcc_output_type : Error< diff --git a/clang/include/clang/Basic/LangOptions.def b/clang/include/clang/Basic/LangOptions.def index 4a91e2c..7549ad4 100644 --- a/clang/include/clang/Basic/LangOptions.def +++ b/clang/include/clang/Basic/LangOptions.def @@ -399,6 +399,7 @@ ENUM_LANGOPT(ClangABICompat, ClangABI, 4, ClangABI::Latest, "with") COMPATIBLE_VALUE_LANGOPT(FunctionAlignment, 5, 0, "Default alignment for functions") +COMPATIBLE_VALUE_LANGOPT(LoopAlignment, 32, 0, "Default alignment for loops") LANGOPT(FixedPoint, 1, 0, "fixed point types") LANGOPT(PaddingOnUnsignedFixedPoint, 1, 0, diff --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td index 9f42072..79f541f 100644 --- a/clang/include/clang/Driver/Options.td +++ b/clang/include/clang/Driver/Options.td @@ -1087,6 +1087,9 @@ defm access_control : BoolFOption<"access-control", PosFlag>; def falign_functions : Flag<["-"], "falign-functions">, Group; def falign_functions_EQ : Joined<["-"], "falign-functions=">, Group; +def falign_loops_EQ : Joined<["-"], "falign-loops=">, Group, Flags<[CC1Option]>, MetaVarName<"">, + HelpText<"N must be a power of two. Align loops to the boundary">, + MarshallingInfoInt>; def fno_align_functions: Flag<["-"], "fno-align-functions">, Group; defm allow_editor_placeholders : BoolFOption<"allow-editor-placeholders", LangOpts<"AllowEditorPlaceholders">, DefaultFalse, @@ -4336,7 +4339,6 @@ def ld_path_EQ : Joined<["--"], "ld-path=">, Group; defm align_labels : BooleanFFlag<"align-labels">, Group; def falign_labels_EQ : Joined<["-"], "falign-labels=">, Group; defm align_loops : BooleanFFlag<"align-loops">, Group; -def falign_loops_EQ : Joined<["-"], "falign-loops=">, Group; defm align_jumps : BooleanFFlag<"align-jumps">, Group; def falign_jumps_EQ : Joined<["-"], "falign-jumps=">, Group; diff --git a/clang/lib/CodeGen/BackendUtil.cpp b/clang/lib/CodeGen/BackendUtil.cpp index 0915255..9e4e40a 100644 --- a/clang/lib/CodeGen/BackendUtil.cpp +++ b/clang/lib/CodeGen/BackendUtil.cpp @@ -580,6 +580,7 @@ static bool initTargetOptions(DiagnosticsEngine &Diags, Options.ValueTrackingVariableLocations = CodeGenOpts.ValueTrackingVariableLocations; Options.XRayOmitFunctionIndex = CodeGenOpts.XRayOmitFunctionIndex; + Options.LoopAlignment = CodeGenOpts.LoopAlignment; Options.MCOptions.SplitDwarfFile = CodeGenOpts.SplitDwarfFile; Options.MCOptions.MCRelaxAll = CodeGenOpts.RelaxAll; diff --git a/clang/lib/Driver/ToolChains/Clang.cpp b/clang/lib/Driver/ToolChains/Clang.cpp index 3de54e2..1c79640 100644 --- a/clang/lib/Driver/ToolChains/Clang.cpp +++ b/clang/lib/Driver/ToolChains/Clang.cpp @@ -4739,6 +4739,22 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, CmdArgs.push_back(Args.MakeArgString(std::to_string(FunctionAlignment))); } + // 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)) { + 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(); + else if (Value & Value - 1) + TC.getDriver().Diag(diag::err_drv_alignment_not_power_of_two) + << A->getAsString(Args) << A->getValue(); + // Treat =0 as unspecified (use the target preference). + if (Value) + CmdArgs.push_back(Args.MakeArgString("-falign-loops=" + + Twine(std::min(Value, 65536u)))); + } + llvm::Reloc::Model RelocationModel; unsigned PICLevel; bool IsPIE; diff --git a/clang/test/CodeGen/align-loops.c b/clang/test/CodeGen/align-loops.c new file mode 100644 index 0000000..a42c8be --- /dev/null +++ b/clang/test/CodeGen/align-loops.c @@ -0,0 +1,15 @@ +// REQUIRES: x86-registered-target +/// Check asm because we use llvm::TargetOptions. + +// RUN: %clang_cc1 -triple=x86_64 -S %s -falign-loops=8 -O -o - | FileCheck %s --check-prefixes=CHECK,CHECK_8 +// RUN: %clang_cc1 -triple=x86_64 -S %s -falign-loops=32 -O -o - | FileCheck %s --check-prefixes=CHECK,CHECK_32 + +// CHECK-LABEL: foo: +// CHECK_8: .p2align 3, 0x90 +// CHECK_32: .p2align 5, 0x90 + +void bar(); +void foo() { + for (int i = 0; i < 64; ++i) + bar(); +} diff --git a/clang/test/Driver/clang_f_opts.c b/clang/test/Driver/clang_f_opts.c index 979ab4e..487ae08 100644 --- a/clang/test/Driver/clang_f_opts.c +++ b/clang/test/Driver/clang_f_opts.c @@ -397,7 +397,6 @@ // CHECK-WARNING-DAG: optimization flag '-falign-labels' is not supported // CHECK-WARNING-DAG: optimization flag '-falign-labels=100' is not supported // CHECK-WARNING-DAG: optimization flag '-falign-loops' is not supported -// CHECK-WARNING-DAG: optimization flag '-falign-loops=100' is not supported // CHECK-WARNING-DAG: optimization flag '-falign-jumps' is not supported // CHECK-WARNING-DAG: optimization flag '-falign-jumps=100' is not supported // CHECK-WARNING-DAG: optimization flag '-fexcess-precision=100' is not supported diff --git a/clang/test/Driver/falign-loops.c b/clang/test/Driver/falign-loops.c new file mode 100644 index 0000000..30a9ae9 --- /dev/null +++ b/clang/test/Driver/falign-loops.c @@ -0,0 +1,17 @@ +/// Treat -falign-loops=0 as not specifying the option. +// RUN: %clang -### -falign-loops=0 %s 2>&1 | FileCheck %s --check-prefix=CHECK_NO +// RUN: %clang -### -falign-loops=1 %s 2>&1 | FileCheck %s --check-prefix=CHECK_1 +// RUN: %clang -### -falign-loops=4 %s 2>&1 | FileCheck %s --check-prefix=CHECK_4 +/// Only powers of 2 are supported for now. +// RUN: %clang -### -falign-loops=5 %s 2>&1 | FileCheck %s --check-prefix=CHECK_5 +// RUN: %clang -### -falign-loops=65536 %s 2>&1 | FileCheck %s --check-prefix=CHECK_65536 +// RUN: %clang -### -falign-loops=65537 %s 2>&1 | FileCheck %s --check-prefix=CHECK_65537 +// RUN: %clang -### -falign-loops=a %s 2>&1 | FileCheck %s --check-prefix=CHECK_ERR_A + +// CHECK_NO-NOT: "-falign-loops= +// CHECK_1: "-falign-loops=1" +// CHECK_4: "-falign-loops=4" +// CHECK_5: error: alignment is not a power of 2 in '-falign-loops=5' +// CHECK_65536: "-falign-loops=65536" +// CHECK_65537: error: invalid integral value '65537' in '-falign-loops=65537' +// CHECK_ERR_A: error: invalid integral value 'a' in '-falign-loops=a' -- 2.7.4