From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 38578 invoked by alias); 25 May 2018 11:04:39 -0000 Mailing-List: contact gcc-patches-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Archive: List-Post: List-Help: Sender: gcc-patches-owner@gcc.gnu.org Received: (qmail 38441 invoked by uid 89); 25 May 2018 11:04:38 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-26.9 required=5.0 tests=BAYES_00,GIT_PATCH_0,GIT_PATCH_1,GIT_PATCH_2,GIT_PATCH_3,SPF_PASS,T_FILL_THIS_FORM_SHORT autolearn=ham version=3.3.2 spammy=Minimum, Reverse, Examples, dual X-HELO: mx2.suse.de Received: from mx2.suse.de (HELO mx2.suse.de) (195.135.220.15) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Fri, 25 May 2018 11:04:29 +0000 Received: from relay2.suse.de (charybdis-ext-too.suse.de [195.135.220.254]) by mx2.suse.de (Postfix) with ESMTP id 84216AC69 for ; Fri, 25 May 2018 11:04:26 +0000 (UTC) Resent-From: =?UTF-8?Q?Martin_Li=c5=a1ka?= Resent-To: GCC Patches Resent-Date: Fri, 25 May 2018 13:04:26 +0200 Resent-Message-ID: <89141f39-ba81-10d0-c265-7565d69d2c27@suse.cz> Resent-User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:52.0) Gecko/20100101 Thunderbird/52.8.0 Message-Id: In-Reply-To: References: From: marxin Date: Fri, 25 May 2018 11:04:00 -0000 Subject: [PATCH 3/3] Extend -falign-FOO=N to N[:M[:N2[:M2]]] To: gcc-patches@gcc.gnu.org Cc: dvlasenk@redhat.com MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="------------2.16.3" X-IsSubscribed: yes X-SW-Source: 2018-05/txt/msg01490.txt.bz2 This is a multi-part message in MIME format. --------------2.16.3 Content-Type: text/plain; charset=UTF-8; format=fixed Content-Transfer-Encoding: 8bit Content-length: 7116 gcc/ChangeLog: 2018-05-25 Denys Vlasenko Martin Liska PR middle-end/66240 PR target/45996 PR c/84100 * common.opt: Rename align options with 'str_' prefix. * common/config/i386/i386-common.c (set_malign_value): New function. (ix86_handle_option): Use it to set -falign-* options/ * config/aarch64/aarch64-protos.h (struct tune_params): Change type from int to string. * config/aarch64/aarch64.c: Update default values from int to string. * config/alpha/alpha.c (alpha_override_options_after_change): Likewise. * config/arm/arm.c (arm_override_options_after_change_1): Likewise. * config/i386/dragonfly.h (ASM_OUTPUT_MAX_SKIP_ALIGN): Print max skip conditionally. * config/i386/freebsd.h (SUBALIGN_LOG): New. (ASM_OUTPUT_MAX_SKIP_ALIGN): Print max skip conditionally. * config/i386/gas.h (ASM_OUTPUT_MAX_SKIP_ALIGN): Print max skip conditionally. * config/i386/gnu-user.h (SUBALIGN_LOG): New. (ASM_OUTPUT_MAX_SKIP_ALIGN): Print max skip conditionally. * config/i386/i386.c (struct ptt): Change type from int to string. (ix86_default_align): Set default values. * config/i386/i386.h (ASM_OUTPUT_MAX_SKIP_PAD): Print max skip conditionally. * config/i386/iamcu.h (SUBALIGN_LOG): New. (ASM_OUTPUT_MAX_SKIP_ALIGN): * config/i386/lynx.h (ASM_OUTPUT_MAX_SKIP_ALIGN): * config/i386/netbsd-elf.h (ASM_OUTPUT_MAX_SKIP_ALIGN): Print max skip conditionally. * config/i386/openbsdelf.h (SUBALIGN_LOG): New. (ASM_OUTPUT_MAX_SKIP_ALIGN) Print max skip conditionally.: * config/i386/x86-64.h (SUBALIGN_LOG): New. (ASM_OUTPUT_MAX_SKIP_ALIGN): Print max skip conditionally. (ASM_OUTPUT_MAX_SKIP_PAD): Likewise. * config/mips/mips.c (mips_set_compression_mode): Change type of constants. * config/rs6000/rs6000.c (rs6000_option_override_internal): Likewise. * config/rx/rx.c (rx_option_override): Likewise. * config/rx/rx.h (JUMP_ALIGN): Use align_jumps_log. (LABEL_ALIGN): Use align_labels_log. (LOOP_ALIGN): Use align_loops_align. * config/sh/sh.c (sh_override_options_after_change): Change type of constants. * config/spu/spu.c (spu_sched_init): Likewise. * config/visium/visium.c (visium_option_override): Likewise. * doc/invoke.texi: Document extended format of -falign-*. * final.c: Use align_labels alignment. * flags.h (struct target_flag_state): Change type to use align_flags. (struct align_flags_tuple): New. (struct align_flags): Likewise. (align_loops_log): Redefine macro to use new types. (align_loops_max_skip): Redefine macro to use new types. (align_jumps_log): Redefine macro to use new types. (align_jumps_max_skip): Redefine macro to use new types. (align_labels_log): Redefine macro to use new types. (align_labels_max_skip): Redefine macro to use new types. (align_functions_log): Redefine macro to use new types. (align_loops): Redefine macro to use new types. (align_jumps): Redefine macro to use new types. (align_labels): Redefine macro to use new types. (align_functions): Redefine macro to use new types. (align_functions_max_skip): Redefine macro to use new types. * function.c (invoke_set_current_function_hook): Propagate alignment values from flags to global variables default in topleev.h. * ipa-icf.c (sem_function::equals_wpa): Use cl_optimization_option_eq instead of memcmp. * lto-streamer.h (cl_optimization_stream_out): Support streaming of string types. (cl_optimization_stream_in): Likewise. * optc-save-gen.awk: Support strings in cl_optimization. * opth-gen.awk: Likewise. * opts.c (finish_options): Remove error checking of invalid value ranges. (MAX_CODE_ALIGN): Remove. (MAX_CODE_ALIGN_VALUE): Likewise. (parse_and_check_align_values): New function. (check_alignment_argument): Likewise. (common_handle_option): Use check_alignment_argument. * opts.h (parse_and_check_align_values): Declare. * toplev.c (init_alignments): Remove. (read_log_maxskip): New. (parse_N_M): Likewise. (parse_alignment_opts): Likewise. (backend_init_target): Remove usage of init_alignments. * toplev.h (parse_alignment_opts): Declare. * tree-streamer-in.c (streamer_read_tree_bitfields): Add new argument. * tree-streamer-out.c (streamer_write_tree_bitfields): Likewise. * tree.c (cl_option_hasher::equal): New. * varasm.c: Use new global macros. gcc/lto/ChangeLog: 2018-05-25 Martin Liska PR middle-end/66240 PR target/45996 PR c/84100 * lto.c (compare_tree_sccs_1): Use cl_optimization_option_eq instead of memcmp. gcc/testsuite/ChangeLog: 2018-05-25 Martin Liska PR middle-end/66240 PR target/45996 PR c/84100 * gcc.dg/pr84100.c (foo): * gcc.target/i386/falign-functions-2.c: New test. * gcc.target/i386/falign-functions.c: New test. --- gcc/common.opt | 16 +-- gcc/common/config/i386/i386-common.c | 16 ++- gcc/config/aarch64/aarch64-protos.h | 6 +- gcc/config/aarch64/aarch64.c | 60 ++++----- gcc/config/alpha/alpha.c | 12 +- gcc/config/arm/arm.c | 7 +- gcc/config/i386/i386.c | 110 ++++++++--------- gcc/config/mips/mips.c | 18 +-- gcc/config/rs6000/rs6000.c | 28 ++--- gcc/config/rx/rx.c | 18 ++- gcc/config/rx/rx.h | 6 +- gcc/config/sh/sh.c | 26 ++-- gcc/config/spu/spu.c | 3 +- gcc/config/visium/visium.c | 19 ++- gcc/doc/invoke.texi | 66 +++++++--- gcc/final.c | 6 + gcc/flags.h | 66 ++++++---- gcc/function.c | 3 + gcc/ipa-icf.c | 2 +- gcc/lto-streamer.h | 6 +- gcc/lto/lto.c | 4 +- gcc/optc-save-gen.awk | 95 ++++++++++++++- gcc/opth-gen.awk | 3 + gcc/opts.c | 108 ++++++++++++++--- gcc/opts.h | 7 ++ gcc/testsuite/gcc.dg/pr84100.c | 2 +- gcc/testsuite/gcc.target/i386/falign-functions-2.c | 30 +++++ gcc/testsuite/gcc.target/i386/falign-functions.c | 8 ++ gcc/toplev.c | 135 +++++++++++++++++---- gcc/toplev.h | 7 ++ gcc/tree-streamer-in.c | 2 +- gcc/tree-streamer-out.c | 2 +- gcc/tree.c | 20 +-- gcc/varasm.c | 9 +- 34 files changed, 637 insertions(+), 289 deletions(-) create mode 100644 gcc/testsuite/gcc.target/i386/falign-functions-2.c create mode 100644 gcc/testsuite/gcc.target/i386/falign-functions.c --------------2.16.3 Content-Type: text/x-patch; name="0003-Extend-falign-FOO-N-to-N-M-N2-M2.patch" Content-Transfer-Encoding: 8bit Content-Disposition: attachment; filename="0003-Extend-falign-FOO-N-to-N-M-N2-M2.patch" Content-length: 58141 diff --git a/gcc/common.opt b/gcc/common.opt index 13ab5c65d43..49e46f09a56 100644 --- a/gcc/common.opt +++ b/gcc/common.opt @@ -950,35 +950,35 @@ Common Report Var(flag_aggressive_loop_optimizations) Optimization Init(1) Aggressively optimize loops using language constraints. falign-functions -Common Report Var(align_functions,0) Optimization UInteger +Common Report Var(flag_align_functions) Optimization Align the start of functions. falign-functions= -Common RejectNegative Joined UInteger Var(align_functions) Optimization +Common RejectNegative Joined Var(str_align_functions) Optimization flimit-function-alignment Common Report Var(flag_limit_function_alignment) Optimization Init(0) falign-jumps -Common Report Var(align_jumps,0) Optimization UInteger +Common Report Var(flag_align_jumps) Optimization Align labels which are only reached by jumping. falign-jumps= -Common RejectNegative Joined UInteger Var(align_jumps) Optimization +Common RejectNegative Joined Var(str_align_jumps) Optimization falign-labels -Common Report Var(align_labels,0) Optimization UInteger +Common Report Var(flag_align_labels) Optimization Align all labels. falign-labels= -Common RejectNegative Joined UInteger Var(align_labels) Optimization +Common RejectNegative Joined Var(str_align_labels) Optimization falign-loops -Common Report Var(align_loops,0) Optimization UInteger +Common Report Var(flag_align_loops) Optimization Align the start of loops. falign-loops= -Common RejectNegative Joined UInteger Var(align_loops) Optimization +Common RejectNegative Joined Var(str_align_loops) fargument-alias Common Ignore diff --git a/gcc/common/config/i386/i386-common.c b/gcc/common/config/i386/i386-common.c index 3aa32f5934b..e32dc3c2331 100644 --- a/gcc/common/config/i386/i386-common.c +++ b/gcc/common/config/i386/i386-common.c @@ -275,6 +275,16 @@ along with GCC; see the file COPYING3. If not see #define OPTION_MASK_ISA2_GENERAL_REGS_ONLY_UNSET \ (OPTION_MASK_ISA2_AVX512F_UNSET | OPTION_MASK_ISA_MPX) +/* Set 1 << value as value of -malign-FLAG option. */ + +static void +set_malign_value (const char **flag, unsigned value) +{ + char *r = XNEWVEC (char, 6); + sprintf (r, "%d", 1 << value); + *flag = r; +} + /* Implement TARGET_HANDLE_OPTION. */ bool @@ -1317,7 +1327,7 @@ ix86_handle_option (struct gcc_options *opts, error_at (loc, "-malign-loops=%d is not between 0 and %d", value, MAX_CODE_ALIGN); else - opts->x_align_loops = 1 << value; + set_malign_value (&opts->x_str_align_loops, value); return true; case OPT_malign_jumps_: @@ -1326,7 +1336,7 @@ ix86_handle_option (struct gcc_options *opts, error_at (loc, "-malign-jumps=%d is not between 0 and %d", value, MAX_CODE_ALIGN); else - opts->x_align_jumps = 1 << value; + set_malign_value (&opts->x_str_align_jumps, value); return true; case OPT_malign_functions_: @@ -1336,7 +1346,7 @@ ix86_handle_option (struct gcc_options *opts, error_at (loc, "-malign-functions=%d is not between 0 and %d", value, MAX_CODE_ALIGN); else - opts->x_align_functions = 1 << value; + set_malign_value (&opts->x_str_align_functions, value); return true; case OPT_mbranch_cost_: diff --git a/gcc/config/aarch64/aarch64-protos.h b/gcc/config/aarch64/aarch64-protos.h index 4ea50acaa59..e635b74437c 100644 --- a/gcc/config/aarch64/aarch64-protos.h +++ b/gcc/config/aarch64/aarch64-protos.h @@ -250,9 +250,9 @@ struct tune_params int memmov_cost; int issue_rate; unsigned int fusible_ops; - int function_align; - int jump_align; - int loop_align; + const char *function_align; + const char *jump_align; + const char *loop_align; int int_reassoc_width; int fp_reassoc_width; int vec_reassoc_width; diff --git a/gcc/config/aarch64/aarch64.c b/gcc/config/aarch64/aarch64.c index afc91850d6f..477af02440e 100644 --- a/gcc/config/aarch64/aarch64.c +++ b/gcc/config/aarch64/aarch64.c @@ -637,9 +637,9 @@ static const struct tune_params generic_tunings = 4, /* memmov_cost */ 2, /* issue_rate */ (AARCH64_FUSE_AES_AESMC), /* fusible_ops */ - 8, /* function_align. */ - 4, /* jump_align. */ - 8, /* loop_align. */ + "8", /* function_align. */ + "4", /* jump_align. */ + "8", /* loop_align. */ 2, /* int_reassoc_width. */ 4, /* fp_reassoc_width. */ 1, /* vec_reassoc_width. */ @@ -663,9 +663,9 @@ static const struct tune_params cortexa35_tunings = 1, /* issue_rate */ (AARCH64_FUSE_AES_AESMC | AARCH64_FUSE_MOV_MOVK | AARCH64_FUSE_ADRP_ADD | AARCH64_FUSE_MOVK_MOVK | AARCH64_FUSE_ADRP_LDR), /* fusible_ops */ - 16, /* function_align. */ - 4, /* jump_align. */ - 8, /* loop_align. */ + "16", /* function_align. */ + "4", /* jump_align. */ + "8", /* loop_align. */ 2, /* int_reassoc_width. */ 4, /* fp_reassoc_width. */ 1, /* vec_reassoc_width. */ @@ -689,9 +689,9 @@ static const struct tune_params cortexa53_tunings = 2, /* issue_rate */ (AARCH64_FUSE_AES_AESMC | AARCH64_FUSE_MOV_MOVK | AARCH64_FUSE_ADRP_ADD | AARCH64_FUSE_MOVK_MOVK | AARCH64_FUSE_ADRP_LDR), /* fusible_ops */ - 16, /* function_align. */ - 4, /* jump_align. */ - 8, /* loop_align. */ + "16", /* function_align. */ + "4", /* jump_align. */ + "8", /* loop_align. */ 2, /* int_reassoc_width. */ 4, /* fp_reassoc_width. */ 1, /* vec_reassoc_width. */ @@ -715,9 +715,9 @@ static const struct tune_params cortexa57_tunings = 3, /* issue_rate */ (AARCH64_FUSE_AES_AESMC | AARCH64_FUSE_MOV_MOVK | AARCH64_FUSE_ADRP_ADD | AARCH64_FUSE_MOVK_MOVK), /* fusible_ops */ - 16, /* function_align. */ - 4, /* jump_align. */ - 8, /* loop_align. */ + "16", /* function_align. */ + "4", /* jump_align. */ + "8", /* loop_align. */ 2, /* int_reassoc_width. */ 4, /* fp_reassoc_width. */ 1, /* vec_reassoc_width. */ @@ -741,9 +741,9 @@ static const struct tune_params cortexa72_tunings = 3, /* issue_rate */ (AARCH64_FUSE_AES_AESMC | AARCH64_FUSE_MOV_MOVK | AARCH64_FUSE_ADRP_ADD | AARCH64_FUSE_MOVK_MOVK), /* fusible_ops */ - 16, /* function_align. */ - 4, /* jump_align. */ - 8, /* loop_align. */ + "16", /* function_align. */ + "4", /* jump_align. */ + "8", /* loop_align. */ 2, /* int_reassoc_width. */ 4, /* fp_reassoc_width. */ 1, /* vec_reassoc_width. */ @@ -767,9 +767,9 @@ static const struct tune_params cortexa73_tunings = 2, /* issue_rate. */ (AARCH64_FUSE_AES_AESMC | AARCH64_FUSE_MOV_MOVK | AARCH64_FUSE_ADRP_ADD | AARCH64_FUSE_MOVK_MOVK | AARCH64_FUSE_ADRP_LDR), /* fusible_ops */ - 16, /* function_align. */ - 4, /* jump_align. */ - 8, /* loop_align. */ + "16", /* function_align. */ + "4", /* jump_align. */ + "8", /* loop_align. */ 2, /* int_reassoc_width. */ 4, /* fp_reassoc_width. */ 1, /* vec_reassoc_width. */ @@ -794,9 +794,9 @@ static const struct tune_params exynosm1_tunings = 4, /* memmov_cost */ 3, /* issue_rate */ (AARCH64_FUSE_AES_AESMC), /* fusible_ops */ - 4, /* function_align. */ - 4, /* jump_align. */ - 4, /* loop_align. */ + "4", /* function_align. */ + "4", /* jump_align. */ + "4", /* loop_align. */ 2, /* int_reassoc_width. */ 4, /* fp_reassoc_width. */ 1, /* vec_reassoc_width. */ @@ -819,9 +819,9 @@ static const struct tune_params thunderxt88_tunings = 6, /* memmov_cost */ 2, /* issue_rate */ AARCH64_FUSE_CMP_BRANCH, /* fusible_ops */ - 8, /* function_align. */ - 8, /* jump_align. */ - 8, /* loop_align. */ + "8", /* function_align. */ + "8", /* jump_align. */ + "8", /* loop_align. */ 2, /* int_reassoc_width. */ 4, /* fp_reassoc_width. */ 1, /* vec_reassoc_width. */ @@ -870,9 +870,9 @@ static const struct tune_params xgene1_tunings = 6, /* memmov_cost */ 4, /* issue_rate */ AARCH64_FUSE_NOTHING, /* fusible_ops */ - 16, /* function_align. */ - 8, /* jump_align. */ - 16, /* loop_align. */ + "16", /* function_align. */ + "8", /* jump_align. */ + "16", /* loop_align. */ 2, /* int_reassoc_width. */ 4, /* fp_reassoc_width. */ 1, /* vec_reassoc_width. */ @@ -896,9 +896,9 @@ static const struct tune_params qdf24xx_tunings = 4, /* issue_rate */ (AARCH64_FUSE_MOV_MOVK | AARCH64_FUSE_ADRP_ADD | AARCH64_FUSE_MOVK_MOVK), /* fuseable_ops */ - 16, /* function_align. */ - 8, /* jump_align. */ - 16, /* loop_align. */ + "16", /* function_align. */ + "8", /* jump_align. */ + "16", /* loop_align. */ 2, /* int_reassoc_width. */ 4, /* fp_reassoc_width. */ 1, /* vec_reassoc_width. */ diff --git a/gcc/config/alpha/alpha.c b/gcc/config/alpha/alpha.c index 26d89f3ea13..5c688d1fe81 100644 --- a/gcc/config/alpha/alpha.c +++ b/gcc/config/alpha/alpha.c @@ -614,13 +614,13 @@ alpha_override_options_after_change (void) /* ??? Kludge these by not doing anything if we don't optimize. */ if (optimize > 0) { - if (align_loops <= 0) - align_loops = 16; - if (align_jumps <= 0) - align_jumps = 16; + if (flag_align_loops && !str_align_loops) + str_align_loops = "16"; + if (flag_align_jumps && !str_align_jumps) + str_align_jumps = "16"; } - if (align_functions <= 0) - align_functions = 16; + if (flag_align_functions && !str_align_functions) + str_align_functions = "16"; } /* Returns 1 if VALUE is a mask that contains full bytes of zero or ones. */ diff --git a/gcc/config/arm/arm.c b/gcc/config/arm/arm.c index c70be366ed8..e0b3c94c6fb 100644 --- a/gcc/config/arm/arm.c +++ b/gcc/config/arm/arm.c @@ -2952,9 +2952,10 @@ static GTY(()) tree init_optimize; static void arm_override_options_after_change_1 (struct gcc_options *opts) { - if (opts->x_align_functions <= 0) - opts->x_align_functions = TARGET_THUMB_P (opts->x_target_flags) - && opts->x_optimize_size ? 2 : 4; + /* -falign-functions without argument: supply one. */ + if (opts->x_flag_align_functions && !opts->x_str_align_functions) + opts->x_str_align_functions = TARGET_THUMB_P (opts->x_target_flags) + && opts->x_optimize_size ? "2" : "4"; } /* Implement targetm.override_options_after_change. */ diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c index 637c10565d5..3796f492fab 100644 --- a/gcc/config/i386/i386.c +++ b/gcc/config/i386/i386.c @@ -837,52 +837,57 @@ struct ptt { const char *const name; /* processor name */ const struct processor_costs *cost; /* Processor costs */ - const int align_loop; /* Default alignments. */ - const int align_loop_max_skip; - const int align_jump; - const int align_jump_max_skip; - const int align_func; + + /* Default alignments. */ + const char *const align_loop; + const char *const align_jump; + const char *const align_label; + const char *const align_func; }; /* This table must be in sync with enum processor_type in i386.h. */ static const struct ptt processor_target_table[PROCESSOR_max] = { - {"generic", &generic_cost, 16, 10, 16, 10, 16}, - {"i386", &i386_cost, 4, 3, 4, 3, 4}, - {"i486", &i486_cost, 16, 15, 16, 15, 16}, - {"pentium", &pentium_cost, 16, 7, 16, 7, 16}, - {"lakemont", &lakemont_cost, 16, 7, 16, 7, 16}, - {"pentiumpro", &pentiumpro_cost, 16, 15, 16, 10, 16}, - {"pentium4", &pentium4_cost, 0, 0, 0, 0, 0}, - {"nocona", &nocona_cost, 0, 0, 0, 0, 0}, - {"core2", &core_cost, 16, 10, 16, 10, 16}, - {"nehalem", &core_cost, 16, 10, 16, 10, 16}, - {"sandybridge", &core_cost, 16, 10, 16, 10, 16}, - {"haswell", &core_cost, 16, 10, 16, 10, 16}, - {"bonnell", &atom_cost, 16, 15, 16, 7, 16}, - {"silvermont", &slm_cost, 16, 15, 16, 7, 16}, - {"goldmont", &slm_cost, 16, 15, 16, 7, 16}, - {"goldmont-plus", &slm_cost, 16, 15, 16, 7, 16}, - {"knl", &slm_cost, 16, 15, 16, 7, 16}, - {"knm", &slm_cost, 16, 15, 16, 7, 16}, - {"skylake", &skylake_cost, 16, 10, 16, 10, 16}, - {"skylake-avx512", &skylake_cost, 16, 10, 16, 10, 16}, - {"cannonlake", &skylake_cost, 16, 10, 16, 10, 16}, - {"icelake-client", &skylake_cost, 16, 10, 16, 10, 16}, - {"icelake-server", &skylake_cost, 16, 10, 16, 10, 16}, - {"intel", &intel_cost, 16, 15, 16, 7, 16}, - {"geode", &geode_cost, 0, 0, 0, 0, 0}, - {"k6", &k6_cost, 32, 7, 32, 7, 32}, - {"athlon", &athlon_cost, 16, 7, 16, 7, 16}, - {"k8", &k8_cost, 16, 7, 16, 7, 16}, - {"amdfam10", &amdfam10_cost, 32, 24, 32, 7, 32}, - {"bdver1", &bdver1_cost, 16, 10, 16, 7, 11}, - {"bdver2", &bdver2_cost, 16, 10, 16, 7, 11}, - {"bdver3", &bdver3_cost, 16, 10, 16, 7, 11}, - {"bdver4", &bdver4_cost, 16, 10, 16, 7, 11}, - {"btver1", &btver1_cost, 16, 10, 16, 7, 11}, - {"btver2", &btver2_cost, 16, 10, 16, 7, 11}, - {"znver1", &znver1_cost, 16, 15, 16, 15, 16} +/* The "0:0:8" label alignment specified for some processors generates + secondary 8-byte alignment only for those label/jump/loop targets + which have primary alignment. */ + + {"generic", &generic_cost, "16:11:8", "16:11:8", "0:0:8", "16"}, + {"i386", &i386_cost, "4", "4", NULL, "4" }, + {"i486", &i486_cost, "16", "16", "0:0:8", "16"}, + {"pentium", &pentium_cost, "16:8:8", "16:8:8", "0:0:8", "16"}, + {"lakemont", &lakemont_cost, "16:8:8", "16:8:8", "0:0:8", "16"}, + {"pentiumpro", &pentiumpro_cost, "16", "16:11:8", "0:0:8", "16"}, + {"pentium4", &pentium4_cost, NULL, NULL, NULL, NULL}, + {"nocona", &nocona_cost, NULL, NULL, NULL, NULL}, + {"core2", &core_cost, "16:11:8", "16:11:8", "0:0:8", "16"}, + {"nehalem", &core_cost, "16:11:8", "16:11:8", "0:0:8", "16"}, + {"sandybridge", &core_cost, "16:11:8", "16:11:8", "0:0:8", "16"}, + {"haswell", &core_cost, "16:11:8", "16:11:8", "0:0:8", "16"}, + {"bonnell", &atom_cost, "16", "16:8:8", "0:0:8", "16"}, + {"silvermont", &slm_cost, "16", "16:8:8", "0:0:8", "16"}, + {"goldmont", &slm_cost, "16", "16:8:8", "0:0:8", "16"}, + {"goldmont-plus", &slm_cost, "16", "16:8:8", "0:0:8", "16"}, + {"knl", &slm_cost, "16", "16:8:8", "0:0:8", "16"}, + {"knm", &slm_cost, "16", "16:8:8", "0:0:8", "16"}, + {"skylake", &skylake_cost, "16:11:8", "16:11:8", "0:0:8", "16"}, + {"skylake-avx512", &skylake_cost, "16:11:8", "16:11:8", "0:0:8", "16"}, + {"cannonlake", &skylake_cost, "16:11:8", "16:11:8", "0:0:8", "16"}, + {"icelake-client", &skylake_cost, "16:11:8", "16:11:8", "0:0:8", "16"}, + {"icelake-server", &skylake_cost, "16:11:8", "16:11:8", "0:0:8", "16"}, + {"intel", &intel_cost, "16", "16:8:8", "0:0:8", "16"}, + {"geode", &geode_cost, NULL, NULL, NULL, NULL}, + {"k6", &k6_cost, "32:8:8", "32:8:8", "0:0:8", "32"}, + {"athlon", &athlon_cost, "16:8:8", "16:8:8", "0:0:8", "16"}, + {"k8", &k8_cost, "16:8:8", "16:8:8", "0:0:8", "16"}, + {"amdfam10", &amdfam10_cost, "32:25:8", "32:8:8", "0:0:8", "32"}, + {"bdver1", &bdver1_cost, "16:11:8", "16:8:8", "0:0:8", "11"}, + {"bdver2", &bdver2_cost, "16:11:8", "16:8:8", "0:0:8", "11"}, + {"bdver3", &bdver3_cost, "16:11:8", "16:8:8", "0:0:8", "11"}, + {"bdver4", &bdver4_cost, "16:11:8", "16:8:8", "0:0:8", "11"}, + {"btver1", &btver1_cost, "16:11:8", "16:8:8", "0:0:8", "11"}, + {"btver2", &btver2_cost, "16:11:8", "16:8:8", "0:0:8", "11"}, + {"znver1", &znver1_cost, "16", "16", "0:0:8", "16"} }; static unsigned int @@ -3349,20 +3354,15 @@ set_ix86_tune_features (enum processor_type ix86_tune, bool dump) static void ix86_default_align (struct gcc_options *opts) { - if (opts->x_align_loops == 0) - { - opts->x_align_loops = processor_target_table[ix86_tune].align_loop; - align_loops_max_skip = processor_target_table[ix86_tune].align_loop_max_skip; - } - if (opts->x_align_jumps == 0) - { - opts->x_align_jumps = processor_target_table[ix86_tune].align_jump; - align_jumps_max_skip = processor_target_table[ix86_tune].align_jump_max_skip; - } - if (opts->x_align_functions == 0) - { - opts->x_align_functions = processor_target_table[ix86_tune].align_func; - } + /* -falign-foo without argument: supply one. */ + if (opts->x_flag_align_loops && !opts->x_str_align_loops) + opts->x_str_align_loops = processor_target_table[ix86_tune].align_loop; + if (opts->x_flag_align_jumps && !opts->x_str_align_jumps) + opts->x_str_align_jumps = processor_target_table[ix86_tune].align_jump; + if (opts->x_flag_align_labels && !opts->x_str_align_labels) + opts->x_str_align_labels = processor_target_table[ix86_tune].align_label; + if (opts->x_flag_align_functions && !opts->x_str_align_functions) + opts->x_str_align_functions = processor_target_table[ix86_tune].align_func; } /* Implement TARGET_OVERRIDE_OPTIONS_AFTER_CHANGE hook. */ diff --git a/gcc/config/mips/mips.c b/gcc/config/mips/mips.c index bfe64bb060c..8ae3ef39267 100644 --- a/gcc/config/mips/mips.c +++ b/gcc/config/mips/mips.c @@ -491,9 +491,9 @@ unsigned int mips_base_compression_flags; static int mips_base_schedule_insns; /* flag_schedule_insns */ static int mips_base_reorder_blocks_and_partition; /* flag_reorder... */ static int mips_base_move_loop_invariants; /* flag_move_loop_invariants */ -static int mips_base_align_loops; /* align_loops */ -static int mips_base_align_jumps; /* align_jumps */ -static int mips_base_align_functions; /* align_functions */ +static const char *mips_base_align_loops; /* align_loops */ +static const char *mips_base_align_jumps; /* align_jumps */ +static const char *mips_base_align_functions; /* align_functions */ /* Index [M][R] is true if register R is allowed to hold a value of mode M. */ static bool mips_hard_regno_mode_ok_p[MAX_MACHINE_MODE][FIRST_PSEUDO_REGISTER]; @@ -19497,12 +19497,12 @@ mips_set_compression_mode (unsigned int compression_mode) /* Provide default values for align_* for 64-bit targets. */ if (TARGET_64BIT) { - if (align_loops == 0) - align_loops = 8; - if (align_jumps == 0) - align_jumps = 8; - if (align_functions == 0) - align_functions = 8; + if (flag_align_loops && !str_align_loops) + str_align_loops = "8"; + if (flag_align_jumps && !str_align_jumps) + str_align_jumps = "8"; + if (flag_align_functions && !str_align_functions) + str_align_functions = "8"; } targetm.min_anchor_offset = -32768; diff --git a/gcc/config/rs6000/rs6000.c b/gcc/config/rs6000/rs6000.c index 26d58fc4c28..2c0a5756e68 100644 --- a/gcc/config/rs6000/rs6000.c +++ b/gcc/config/rs6000/rs6000.c @@ -4936,29 +4936,25 @@ rs6000_option_override_internal (bool global_init_p) if (rs6000_tune == PROCESSOR_TITAN || rs6000_tune == PROCESSOR_CELL) { - if (align_functions <= 0) - align_functions = 8; - if (align_jumps <= 0) - align_jumps = 8; - if (align_loops <= 0) - align_loops = 8; + if (flag_align_functions && !str_align_functions) + str_align_functions = "8"; + if (flag_align_jumps && !str_align_jumps) + str_align_jumps = "8"; + if (flag_align_loops && !str_align_loops) + str_align_loops = "8"; } if (rs6000_align_branch_targets) { - if (align_functions <= 0) - align_functions = 16; - if (align_jumps <= 0) - align_jumps = 16; - if (align_loops <= 0) + if (flag_align_functions && !str_align_functions) + str_align_functions = "16"; + if (flag_align_jumps && !str_align_jumps) + str_align_jumps = "16"; + if (flag_align_loops && !str_align_loops) { can_override_loop_align = 1; - align_loops = 16; + str_align_loops = "16"; } } - if (align_jumps_max_skip <= 0) - align_jumps_max_skip = 15; - if (align_loops_max_skip <= 0) - align_loops_max_skip = 15; } /* Arrange to save and restore machine status around nested functions. */ diff --git a/gcc/config/rx/rx.c b/gcc/config/rx/rx.c index fe467f7bd3a..af97bef301d 100644 --- a/gcc/config/rx/rx.c +++ b/gcc/config/rx/rx.c @@ -2843,12 +2843,18 @@ rx_option_override (void) rx_override_options_after_change (); /* These values are bytes, not log. */ - if (align_jumps == 0 && ! optimize_size) - align_jumps = ((rx_cpu_type == RX100 || rx_cpu_type == RX200) ? 4 : 8); - if (align_loops == 0 && ! optimize_size) - align_loops = ((rx_cpu_type == RX100 || rx_cpu_type == RX200) ? 4 : 8); - if (align_labels == 0 && ! optimize_size) - align_labels = ((rx_cpu_type == RX100 || rx_cpu_type == RX200) ? 4 : 8); + if (! optimize_size) + { + if (flag_align_jumps && !str_align_jumps) + str_align_jumps = ((rx_cpu_type == RX100 + || rx_cpu_type == RX200) ? "4" : "8"); + if (flag_align_loops && !str_align_loops) + str_align_loops = ((rx_cpu_type == RX100 + || rx_cpu_type == RX200) ? "4" : "8"); + if (flag_align_labels && !str_align_labels) + str_align_labels = ((rx_cpu_type == RX100 + || rx_cpu_type == RX200) ? "4" : "8"); + } } diff --git a/gcc/config/rx/rx.h b/gcc/config/rx/rx.h index a2aa392ce67..2f5a0e94677 100644 --- a/gcc/config/rx/rx.h +++ b/gcc/config/rx/rx.h @@ -417,9 +417,9 @@ typedef unsigned int CUMULATIVE_ARGS; /* Compute the alignment needed for label X in various situations. If the user has specified an alignment then honour that, otherwise use rx_align_for_label. */ -#define JUMP_ALIGN(x) (align_jumps > 1 ? align_jumps_log : rx_align_for_label (x, 0)) -#define LABEL_ALIGN(x) (align_labels > 1 ? align_labels_log : rx_align_for_label (x, 3)) -#define LOOP_ALIGN(x) (align_loops > 1 ? align_loops_log : rx_align_for_label (x, 2)) +#define JUMP_ALIGN(x) (align_jumps_log > 0 ? align_jumps_log : rx_align_for_label (x, 0)) +#define LABEL_ALIGN(x) (align_labels_log > 0 ? align_labels_log : rx_align_for_label (x, 3)) +#define LOOP_ALIGN(x) (align_loops_log > 0 ? align_loops_log : rx_align_for_label (x, 2)) #define LABEL_ALIGN_AFTER_BARRIER(x) rx_align_for_label (x, 0) #define ASM_OUTPUT_MAX_SKIP_ALIGN(STREAM, LOG, MAX_SKIP) \ diff --git a/gcc/config/sh/sh.c b/gcc/config/sh/sh.c index ced66408265..e5dc32e45c3 100644 --- a/gcc/config/sh/sh.c +++ b/gcc/config/sh/sh.c @@ -1007,29 +1007,29 @@ sh_override_options_after_change (void) Aligning all jumps increases the code size, even if it might result in slightly faster code. Thus, it is set to the smallest alignment possible if not specified by the user. */ - if (align_loops == 0) - align_loops = optimize_size ? 2 : 4; + if (flag_align_loops && !str_align_loops) + str_align_loops = optimize_size ? "2" : "4"; - if (align_jumps == 0) - align_jumps = 2; - else if (align_jumps < 2) - align_jumps = 2; + if (flag_align_jumps && !str_align_jumps) + str_align_jumps = "2"; + else + min_align_jumps_log = 1; - if (align_functions == 0) - align_functions = optimize_size ? 2 : 4; + if (flag_align_functions && !str_align_functions) + str_align_functions = optimize_size ? "2" : "4"; /* The linker relaxation code breaks when a function contains alignments that are larger than that at the start of a compilation unit. */ if (TARGET_RELAX) { - int min_align = align_loops > align_jumps ? align_loops : align_jumps; + parse_alignment_opts (); + min_align_functions_log = align_loops_log > align_jumps_log ? + align_loops_log : align_jumps_log; /* Also take possible .long constants / mova tables into account. */ - if (min_align < 4) - min_align = 4; - if (align_functions < min_align) - align_functions = min_align; + if (min_align_functions_log < 2) + min_align_functions_log = 2; } } diff --git a/gcc/config/spu/spu.c b/gcc/config/spu/spu.c index 53935795424..4db01e057a5 100644 --- a/gcc/config/spu/spu.c +++ b/gcc/config/spu/spu.c @@ -2769,7 +2769,8 @@ static void spu_sched_init (FILE *file ATTRIBUTE_UNUSED, int verbose ATTRIBUTE_UNUSED, int max_ready ATTRIBUTE_UNUSED) { - if (align_labels > 4 || align_loops > 4 || align_jumps > 4) + parse_alignment_opts (); + if (align_labels_log > 2 || align_loops_log > 2 || align_jumps_log > 2) { /* When any block might be at least 8-byte aligned, assume they will all be at least 8-byte aligned to make sure dual issue diff --git a/gcc/config/visium/visium.c b/gcc/config/visium/visium.c index 106cdaf9e3f..37de6249797 100644 --- a/gcc/config/visium/visium.c +++ b/gcc/config/visium/visium.c @@ -443,12 +443,12 @@ visium_option_override (void) /* Align functions on 256-byte (32-quadword) for GR5 and 64-byte (8-quadword) boundaries for GR6 so they start a new burst mode window. */ - if (align_functions == 0) + if (flag_align_functions && !str_align_functions) { if (visium_cpu == PROCESSOR_GR6) - align_functions = 64; + str_align_functions = "64"; else - align_functions = 256; + str_align_functions = "256"; /* Allow the size of compilation units to double because of inlining. In practice the global size of the object code is hardly affected @@ -459,26 +459,25 @@ visium_option_override (void) } /* Likewise for loops. */ - if (align_loops == 0) + if (flag_align_loops && !str_align_loops) { if (visium_cpu == PROCESSOR_GR6) - align_loops = 64; + str_align_loops = "64"; else { - align_loops = 256; /* But not if they are too far away from a 256-byte boundary. */ - align_loops_max_skip = 31; + str_align_loops = "256:32"; } } /* Align all jumps on quadword boundaries for the burst mode, and even on 8-quadword boundaries for GR6 so they start a new window. */ - if (align_jumps == 0) + if (flag_align_jumps && !str_align_jumps) { if (visium_cpu == PROCESSOR_GR6) - align_jumps = 64; + str_align_jumps = "64"; else - align_jumps = 8; + str_align_jumps = "8"; } /* We register a machine-specific pass. This pass must be scheduled as diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi index 65f32d67640..9b97bf0a36f 100644 --- a/gcc/doc/invoke.texi +++ b/gcc/doc/invoke.texi @@ -364,9 +364,11 @@ Objective-C and Objective-C++ Dialects}. @item Optimization Options @xref{Optimize Options,,Options that Control Optimization}. -@gccoptlist{-faggressive-loop-optimizations -falign-functions[=@var{n}] @gol --falign-jumps[=@var{n}] @gol --falign-labels[=@var{n}] -falign-loops[=@var{n}] @gol +@gccoptlist{-faggressive-loop-optimizations @gol +-falign-functions[=@var{n}[:@var{m}:[@var{n2}[:@var{m2}]]]] @gol +-falign-jumps[=@var{n}[:@var{m}:[@var{n2}[:@var{m2}]]]] @gol +-falign-labels[=@var{n}[:@var{m}:[@var{n2}[:@var{m2}]]]] @gol +-falign-loops[=@var{n}[:@var{m}:[@var{n2}[:@var{m2}]]]] @gol -fassociative-math -fauto-profile -fauto-profile[=@var{path}] @gol -fauto-inc-dec -fbranch-probabilities @gol -fbranch-target-load-optimize -fbranch-target-load-optimize2 @gol @@ -9175,19 +9177,36 @@ The @option{-fstrict-aliasing} option is enabled at levels @item -falign-functions @itemx -falign-functions=@var{n} +@itemx -falign-functions=@var{n}:@var{m} +@itemx -falign-functions=@var{n}:@var{m}:@var{n2} +@itemx -falign-functions=@var{n}:@var{m}:@var{n2}:@var{m2} @opindex falign-functions Align the start of functions to the next power-of-two greater than -@var{n}, skipping up to @var{n} bytes. For instance, -@option{-falign-functions=32} aligns functions to the next 32-byte -boundary, but @option{-falign-functions=24} aligns to the next -32-byte boundary only if this can be done by skipping 23 bytes or less. +@var{n}, skipping up to @var{m}-1 bytes. This ensures that at least +the first @var{m} bytes of the function can be fetched by the CPU +without crossing an @var{n}-byte alignment boundary. -@option{-fno-align-functions} and @option{-falign-functions=1} are -equivalent and mean that functions are not aligned. +If @var{m} is not specified, it defaults to @var{n}. + +Examples: @option{-falign-functions=32} aligns functions to the next +32-byte boundary, @option{-falign-functions=24} aligns to the next +32-byte boundary only if this can be done by skipping 23 bytes or less, +@option{-falign-functions=32:7} aligns to the next +32-byte boundary only if this can be done by skipping 6 bytes or less. + +The second pair of @var{n2}:@var{m2} values allows you to specify +a secondary alignment: @option{-falign-functions=64:7:32:3} aligns to +the next 64-byte boundary if this can be done by skipping 6 bytes or less, +otherwise aligns to the next 32-byte boundary if this can be done +by skipping 2 bytes or less. +If @var{m2} is not specified, it defaults to @var{n2}. Some assemblers only support this flag when @var{n} is a power of two; in that case, it is rounded up. +@option{-fno-align-functions} and @option{-falign-functions=1} are +equivalent and mean that functions are not aligned. + If @var{n} is not specified or is zero, use a machine-dependent default. The maximum allowed @var{n} option value is 65536. @@ -9201,12 +9220,13 @@ skip more bytes than the size of the function. @item -falign-labels @itemx -falign-labels=@var{n} +@itemx -falign-labels=@var{n}:@var{m} +@itemx -falign-labels=@var{n}:@var{m}:@var{n2} +@itemx -falign-labels=@var{n}:@var{m}:@var{n2}:@var{m2} @opindex falign-labels -Align all branch targets to a power-of-two boundary, skipping up to -@var{n} bytes like @option{-falign-functions}. This option can easily -make code slower, because it must insert dummy operations for when the -branch target is reached in the usual flow of the code. +Align all branch targets to a power-of-two boundary. +Parameters of this option are analogous to the @option{-falign-functions} option. @option{-fno-align-labels} and @option{-falign-labels=1} are equivalent and mean that labels are not aligned. @@ -9221,12 +9241,15 @@ Enabled at levels @option{-O2}, @option{-O3}. @item -falign-loops @itemx -falign-loops=@var{n} +@itemx -falign-loops=@var{n}:@var{m} +@itemx -falign-loops=@var{n}:@var{m}:@var{n2} +@itemx -falign-loops=@var{n}:@var{m}:@var{n2}:@var{m2} @opindex falign-loops -Align loops to a power-of-two boundary, skipping up to @var{n} bytes -like @option{-falign-functions}. If the loops are -executed many times, this makes up for any execution of the dummy -operations. +Align loops to a power-of-two boundary. If the loops are executed +many times, this makes up for any execution of the dummy padding +instructions. +Parameters of this option are analogous to the @option{-falign-functions} option. @option{-fno-align-loops} and @option{-falign-loops=1} are equivalent and mean that loops are not aligned. The maximum allowed @var{n} option value is 65536. @@ -9237,12 +9260,15 @@ Enabled at levels @option{-O2}, @option{-O3}. @item -falign-jumps @itemx -falign-jumps=@var{n} +@itemx -falign-jumps=@var{n}:@var{m} +@itemx -falign-jumps=@var{n}:@var{m}:@var{n2} +@itemx -falign-jumps=@var{n}:@var{m}:@var{n2}:@var{m2} @opindex falign-jumps Align branch targets to a power-of-two boundary, for branch targets -where the targets can only be reached by jumping, skipping up to @var{n} -bytes like @option{-falign-functions}. In this case, no dummy operations -need be executed. +where the targets can only be reached by jumping. In this case, +no dummy operations need be executed. +Parameters of this option are analogous to the @option{-falign-functions} option. @option{-fno-align-jumps} and @option{-falign-jumps=1} are equivalent and mean that loops are not aligned. diff --git a/gcc/final.c b/gcc/final.c index 4c600f0edf2..7a0bf2d17fd 100644 --- a/gcc/final.c +++ b/gcc/final.c @@ -2529,6 +2529,12 @@ final_scan_insn_1 (rtx_insn *insn, FILE *file, int optimize_p ATTRIBUTE_UNUSED, { #ifdef ASM_OUTPUT_MAX_SKIP_ALIGN ASM_OUTPUT_MAX_SKIP_ALIGN (file, align, max_skip); + /* Above, we don't know whether a label, jump or loop + alignment was used. Conservatively apply + label subalignment, not jump or loop + subalignment (they are almost always larger). */ + ASM_OUTPUT_MAX_SKIP_ALIGN (file, align_labels.levels[1].log, + align_labels.levels[1].maxskip); #else #ifdef ASM_OUTPUT_ALIGN_WITH_NOP ASM_OUTPUT_ALIGN_WITH_NOP (file, align); diff --git a/gcc/flags.h b/gcc/flags.h index d5d4d78e18f..26c7f021f55 100644 --- a/gcc/flags.h +++ b/gcc/flags.h @@ -42,19 +42,32 @@ extern bool final_insns_dump_p; /* Other basic status info about current function. */ -/* Target-dependent global state. */ -struct target_flag_state { +/* Align flags tuple with alignment in log form and with a maximum skip. */ + +struct align_flags_tuple +{ /* Values of the -falign-* flags: how much to align labels in code. - 0 means `use default', 1 means `don't align'. - For each variable, there is an _log variant which is the power - of two not less than the variable, for .align output. */ - int x_align_loops_log; - int x_align_loops_max_skip; - int x_align_jumps_log; - int x_align_jumps_max_skip; - int x_align_labels_log; - int x_align_labels_max_skip; - int x_align_functions_log; + log is "align to 2^log" (so 0 means no alignment). + maxskip is the maximum allowed amount of padding to insert. */ + int log; + int maxskip; +}; + +/* Target-dependent global state. */ + +struct align_flags +{ + align_flags_tuple levels[2]; +}; + +struct target_flag_state +{ + /* Each falign-foo can generate up to two levels of alignment: + -falign-foo=N:M[:N2:M2] */ + align_flags x_align_loops; + align_flags x_align_jumps; + align_flags x_align_labels; + align_flags x_align_functions; /* The excess precision currently in effect. */ enum excess_precision x_flag_excess_precision; @@ -67,20 +80,21 @@ extern struct target_flag_state *this_target_flag_state; #define this_target_flag_state (&default_target_flag_state) #endif -#define align_loops_log \ - (this_target_flag_state->x_align_loops_log) -#define align_loops_max_skip \ - (this_target_flag_state->x_align_loops_max_skip) -#define align_jumps_log \ - (this_target_flag_state->x_align_jumps_log) -#define align_jumps_max_skip \ - (this_target_flag_state->x_align_jumps_max_skip) -#define align_labels_log \ - (this_target_flag_state->x_align_labels_log) -#define align_labels_max_skip \ - (this_target_flag_state->x_align_labels_max_skip) -#define align_functions_log \ - (this_target_flag_state->x_align_functions_log) +#define align_loops (this_target_flag_state->x_align_loops) +#define align_jumps (this_target_flag_state->x_align_jumps) +#define align_labels (this_target_flag_state->x_align_labels) +#define align_functions (this_target_flag_state->x_align_functions) +#define align_loops_log (align_loops.levels[0].log) +#define align_jumps_log (align_jumps.levels[0].log) +#define align_labels_log (align_labels.levels[0].log) +#define align_functions_log (align_functions.levels[0].log) +#define align_loops_max_skip (align_loops.levels[0].maxskip) +#define align_jumps_max_skip (align_jumps.levels[0].maxskip) +#define align_labels_max_skip (align_labels.levels[0].maxskip) +#define align_functions_max_skip (align_functions.levels[0].maxskip) +/* String representaions of the above options are available in + const char *str_align_foo. NULL if not set. */ + #define flag_excess_precision \ (this_target_flag_state->x_flag_excess_precision) diff --git a/gcc/function.c b/gcc/function.c index 61515e38e47..2aa818be64e 100644 --- a/gcc/function.c +++ b/gcc/function.c @@ -4823,6 +4823,9 @@ invoke_set_current_function_hook (tree fndecl) targetm.set_current_function (fndecl); this_fn_optabs = this_target_optabs; + /* Initialize global alignment variables after op. */ + parse_alignment_opts (); + if (opts != optimization_default_node) { init_tree_optimization_optabs (opts); diff --git a/gcc/ipa-icf.c b/gcc/ipa-icf.c index 37e63fc2ba8..8ae461f2584 100644 --- a/gcc/ipa-icf.c +++ b/gcc/ipa-icf.c @@ -658,7 +658,7 @@ sem_function::equals_wpa (sem_item *item, cl_optimization *opt1 = opts_for_fn (decl); cl_optimization *opt2 = opts_for_fn (item->decl); - if (opt1 != opt2 && memcmp (opt1, opt2, sizeof(cl_optimization))) + if (opt1 != opt2 && !cl_optimization_option_eq (opt1, opt2)) { if (dump_file && (dump_flags & TDF_DETAILS)) { diff --git a/gcc/lto-streamer.h b/gcc/lto-streamer.h index d2006fad0ad..27f62056255 100644 --- a/gcc/lto-streamer.h +++ b/gcc/lto-streamer.h @@ -919,9 +919,11 @@ void cl_target_option_stream_in (struct data_in *, struct bitpack_d *, struct cl_target_option *); -void cl_optimization_stream_out (struct bitpack_d *, struct cl_optimization *); +void cl_optimization_stream_out (struct output_block *, + struct bitpack_d *, struct cl_optimization *); -void cl_optimization_stream_in (struct bitpack_d *, struct cl_optimization *); +void cl_optimization_stream_in (struct data_in *, + struct bitpack_d *, struct cl_optimization *); diff --git a/gcc/lto/lto.c b/gcc/lto/lto.c index d2ccaf67689..0ecab1f98f8 100644 --- a/gcc/lto/lto.c +++ b/gcc/lto/lto.c @@ -1222,8 +1222,8 @@ compare_tree_sccs_1 (tree t1, tree t2, tree **map) return false; if (CODE_CONTAINS_STRUCT (code, TS_OPTIMIZATION)) - if (memcmp (TREE_OPTIMIZATION (t1), TREE_OPTIMIZATION (t2), - sizeof (struct cl_optimization)) != 0) + if (!cl_optimization_option_eq (TREE_OPTIMIZATION (t1), + TREE_OPTIMIZATION (t2))) return false; if (CODE_CONTAINS_STRUCT (code, TS_BINFO)) diff --git a/gcc/optc-save-gen.awk b/gcc/optc-save-gen.awk index 1a365fc883c..6e33a4320c1 100644 --- a/gcc/optc-save-gen.awk +++ b/gcc/optc-save-gen.awk @@ -85,6 +85,7 @@ n_opt_char = 3; n_opt_short = 0; n_opt_int = 0; n_opt_enum = 0; +n_opt_string = 0; n_opt_other = 0; var_opt_char[0] = "optimize"; var_opt_char[1] = "optimize_size"; @@ -123,6 +124,8 @@ for (i = 0; i < n_opts; i++) { else if (otype ~ "^signed +char *$") var_opt_range[name] = "-128, 127" } + else if (otype ~ "^const char \\**$") + var_opt_string[n_opt_string++] = name; else var_opt_other[n_opt_other++] = name; } @@ -155,6 +158,10 @@ for (i = 0; i < n_opt_char; i++) { print " ptr->x_" var_opt_char[i] " = opts->x_" var_opt_char[i] ";"; } +for (i = 0; i < n_opt_string; i++) { + print " ptr->x_" var_opt_string[i] " = opts->x_" var_opt_string[i] ";"; +} + print "}"; print ""; @@ -183,6 +190,10 @@ for (i = 0; i < n_opt_char; i++) { print " opts->x_" var_opt_char[i] " = ptr->x_" var_opt_char[i] ";"; } +for (i = 0; i < n_opt_string; i++) { + print " opts->x_" var_opt_string[i] " = ptr->x_" var_opt_string[i] ";"; +} + print " targetm.override_options_after_change ();"; print "}"; @@ -239,6 +250,15 @@ for (i = 0; i < n_opt_char; i++) { print ""; } +for (i = 0; i < n_opt_string; i++) { + print " if (ptr->x_" var_opt_char[i] ")"; + print " fprintf (file, \"%*s%s (%s)\\n\","; + print " indent_to, \"\","; + print " \"" var_opt_string[i] "\","; + print " ptr->x_" var_opt_string[i] ");"; + print ""; +} + print "}"; print ""; @@ -301,6 +321,19 @@ for (i = 0; i < n_opt_char; i++) { print ""; } +for (i = 0; i < n_opt_string; i++) { + name = var_opt_string[i] + print " if (ptr1->x_" name " != ptr2->x_" name ""; + print " || (!ptr1->x_" name" || !ptr2->x_" name + print " || strcmp (ptr1->x_" name", ptr2->x_" name ")))"; + print " fprintf (file, \"%*s%s (%s/%s)\\n\","; + print " indent_to, \"\","; + print " \"" name "\","; + print " ptr1->x_" name ","; + print " ptr2->x_" name ");"; + print ""; +} + print "}"; @@ -766,32 +799,82 @@ for (i = 0; i < n_opt_val; i++) { if (!var_opt_hash[i]) continue; name = var_opt_val[i] - print " hstate.add_hwi (ptr->" name");"; + otype = var_opt_val_type[i]; + if (otype ~ "^const char \\**$") + { + print " if (ptr->" name")"; + print " hstate.add (ptr->" name", strlen (ptr->" name"));"; + print " else"; + print " hstate.add_int (0);"; + } + else + print " hstate.add_hwi (ptr->" name");"; } print " return hstate.end ();"; print "}"; +print ""; +print "/* Compare two optimization options */"; +print "bool"; +print "cl_optimization_option_eq (cl_optimization const *ptr1,"; +print " cl_optimization const *ptr2)"; +print "{"; +for (i = 0; i < n_opt_val; i++) { + if (!var_opt_hash[i]) + continue; + name = var_opt_val[i] + otype = var_opt_val_type[i]; + if (otype ~ "^const char \\**$") + { + print " if (ptr1->" name" != ptr2->" name; + print " && (!ptr1->" name" || !ptr2->" name + print " || strcmp (ptr1->" name", ptr2->" name ")))"; + print " return false;"; + } + else + { + print " if (ptr1->" name" != ptr2->" name ")"; + print " return false;"; + } +} +print " return true;"; +print "}"; + print ""; print "/* Stream out optimization options */"; print "void"; -print "cl_optimization_stream_out (struct bitpack_d *bp,"; +print "cl_optimization_stream_out (struct output_block *ob,"; +print " struct bitpack_d *bp,"; print " struct cl_optimization *ptr)"; print "{"; for (i = 0; i < n_opt_val; i++) { name = var_opt_val[i] - print " bp_pack_value (bp, ptr->" name", 64);"; + otype = var_opt_val_type[i]; + if (otype ~ "^const char \\**$") + print " bp_pack_string (ob, bp, ptr->" name", true);"; + else + print " bp_pack_value (bp, ptr->" name", 64);"; } print "}"; print ""; print "/* Stream in optimization options */"; print "void"; -print "cl_optimization_stream_in (struct bitpack_d *bp,"; -print " struct cl_optimization *ptr)"; +print "cl_optimization_stream_in (struct data_in *data_in ATTRIBUTE_UNUSED,"; +print " struct bitpack_d *bp ATTRIBUTE_UNUSED,"; +print " struct cl_optimization *ptr ATTRIBUTE_UNUSED)"; print "{"; for (i = 0; i < n_opt_val; i++) { name = var_opt_val[i] - print " ptr->" name" = (" var_opt_val_type[i] ") bp_unpack_value (bp, 64);"; + otype = var_opt_val_type[i]; + if (otype ~ "^const char \\**$") + { + print " ptr->" name" = bp_unpack_string (data_in, bp);"; + print " if (ptr->" name")"; + print " ptr->" name" = xstrdup (ptr->" name");"; + } + else + print " ptr->" name" = (" var_opt_val_type[i] ") bp_unpack_value (bp, 64);"; } print "}"; } diff --git a/gcc/opth-gen.awk b/gcc/opth-gen.awk index fecd4b8a0b5..8358b9b2b67 100644 --- a/gcc/opth-gen.awk +++ b/gcc/opth-gen.awk @@ -308,6 +308,9 @@ print ""; print "/* Hash optimization from a structure. */"; print "extern hashval_t cl_optimization_hash (const struct cl_optimization *);"; print ""; +print "/* Compare two optimization options. */"; +print "extern bool cl_optimization_option_eq (cl_optimization const *ptr1, cl_optimization const *ptr2);" +print ""; print "/* Generator files may not have access to location_t, and don't need these. */" print "#if defined(UNKNOWN_LOCATION)" print "bool " diff --git a/gcc/opts.c b/gcc/opts.c index 33efcc0d6e7..f5f0947faf3 100644 --- a/gcc/opts.c +++ b/gcc/opts.c @@ -1039,26 +1039,6 @@ finish_options (struct gcc_options *opts, struct gcc_options *opts_set, if ((opts->x_flag_sanitize & SANITIZE_KERNEL_ADDRESS) && opts->x_flag_tm) sorry ("transactional memory is not supported with " "%<-fsanitize=kernel-address%>"); - - /* Comes from final.c -- no real reason to change it. */ -#define MAX_CODE_ALIGN 16 -#define MAX_CODE_ALIGN_VALUE (1 << MAX_CODE_ALIGN) - - if (opts->x_align_loops > MAX_CODE_ALIGN_VALUE) - error_at (loc, "-falign-loops=%d is not between 0 and %d", - opts->x_align_loops, MAX_CODE_ALIGN_VALUE); - - if (opts->x_align_jumps > MAX_CODE_ALIGN_VALUE) - error_at (loc, "-falign-jumps=%d is not between 0 and %d", - opts->x_align_jumps, MAX_CODE_ALIGN_VALUE); - - if (opts->x_align_functions > MAX_CODE_ALIGN_VALUE) - error_at (loc, "-falign-functions=%d is not between 0 and %d", - opts->x_align_functions, MAX_CODE_ALIGN_VALUE); - - if (opts->x_align_labels > MAX_CODE_ALIGN_VALUE) - error_at (loc, "-falign-labels=%d is not between 0 and %d", - opts->x_align_labels, MAX_CODE_ALIGN_VALUE); } #define LEFT_COLUMN 27 @@ -1779,6 +1759,78 @@ parse_no_sanitize_attribute (char *value) return flags; } +/* Parse -falign-NAME format for a FLAG value. Return individual + parsed integer values into RESULT_VALUES array. If REPORT_ERROR is + set, print error message at LOC location. */ + +bool +parse_and_check_align_values (const char *flag, + const char *name, + auto_vec &result_values, + bool report_error, + location_t loc) +{ + char *str = xstrdup (flag); + for (char *p = strtok (str, ":"); p; p = strtok (NULL, ":")) + { + char *end; + int v = strtol (p, &end, 10); + if (*end != '\0' || v < 0) + { + if (report_error) + error_at (loc, "invalid arguments for %<-falign-%s%> option: %qs", + name, flag); + + return false; + } + + result_values.safe_push ((unsigned)v); + } + + free (str); + + /* Check that we have a correct number of values. */ +#ifdef SUBALIGN_LOG + unsigned max_valid_values = 4; +#else + unsigned max_valid_values = 2; +#endif + + if (result_values.is_empty () + || result_values.length () > max_valid_values) + { + if (report_error) + error_at (loc, "invalid number of arguments for %<-falign-%s%> " + "option: %qs", name, flag); + return false; + } + + /* Comes from final.c -- no real reason to change it. */ +#define MAX_CODE_ALIGN 16 +#define MAX_CODE_ALIGN_VALUE (1 << MAX_CODE_ALIGN) + + for (unsigned i = 0; i < result_values.length (); i++) + if (result_values[i] > MAX_CODE_ALIGN_VALUE) + { + if (report_error) + error_at (loc, "%<-falign-%s%> is not between 0 and %d", + name, MAX_CODE_ALIGN_VALUE); + return false; + } + + return true; +} + +/* Check that alignment value FLAG for -falign-NAME is valid at a given + location LOC. */ + +static void +check_alignment_argument (location_t loc, const char *flag, const char *name) +{ + auto_vec align_result; + parse_and_check_align_values (flag, name, align_result, true, loc); +} + /* Handle target- and language-independent options. Return zero to generate an "unknown option" message. Only options that need extra handling need to be listed here; if you simply want @@ -2498,6 +2550,22 @@ common_handle_option (struct gcc_options *opts, opts->x_flag_ipa_icf_variables = value; break; + case OPT_falign_loops_: + check_alignment_argument (loc, arg, "loops"); + break; + + case OPT_falign_jumps_: + check_alignment_argument (loc, arg, "jumps"); + break; + + case OPT_falign_labels_: + check_alignment_argument (loc, arg, "labels"); + break; + + case OPT_falign_functions_: + check_alignment_argument (loc, arg, "functions"); + break; + default: /* If the flag was handled in a standard way, assume the lack of processing here is intentional. */ diff --git a/gcc/opts.h b/gcc/opts.h index 484fc1c39d9..8a2ca5a06ab 100644 --- a/gcc/opts.h +++ b/gcc/opts.h @@ -439,4 +439,11 @@ extern const char *candidates_list_and_hint (const char *arg, char *&str, const auto_vec & candidates); + +extern bool parse_and_check_align_values (const char *flag, + const char *name, + auto_vec &result_values, + bool report_error, + location_t loc); + #endif diff --git a/gcc/testsuite/gcc.dg/pr84100.c b/gcc/testsuite/gcc.dg/pr84100.c index 86fbc4f7a3e..676d0c78dea 100644 --- a/gcc/testsuite/gcc.dg/pr84100.c +++ b/gcc/testsuite/gcc.dg/pr84100.c @@ -8,7 +8,7 @@ __attribute__((optimize ("align-loops=16", "align-jumps=16", "align-labels=16", "align-functions=16"))) void foo (void) -{ /* { dg-bogus "bad option" } */ +{ /* { dg-warning "bad option" } */ for (int i = 0; i < 1024; ++i) bar (); } diff --git a/gcc/testsuite/gcc.target/i386/falign-functions-2.c b/gcc/testsuite/gcc.target/i386/falign-functions-2.c new file mode 100644 index 00000000000..26d505e3bea --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/falign-functions-2.c @@ -0,0 +1,30 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -falign-functions=64:8" } */ + +void +a (void) +{ +} + +#pragma GCC push_options +#pragma GCC optimize "align-functions=128:100" +void b (void) +{ +} +#pragma GCC pop_options + +void +__attribute__((optimize("-falign-functions=88:88:32"))) +c (void) +{ +} + +void +d (void) +{ +} + +/* { dg-final { scan-assembler-times ".p2align 6,,7" 2 } } */ +/* { dg-final { scan-assembler-times ".p2align 7,,99" 1 } } */ +/* { dg-final { scan-assembler-times ".p2align 7,,87" 1 } } */ +/* { dg-final { scan-assembler-times ".p2align 5" 1 } } */ diff --git a/gcc/testsuite/gcc.target/i386/falign-functions.c b/gcc/testsuite/gcc.target/i386/falign-functions.c new file mode 100644 index 00000000000..27daa1d0e6b --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/falign-functions.c @@ -0,0 +1,8 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -falign-functions=64:8" } */ +/* { dg-final { scan-assembler ".p2align 6,,7" } } */ + +void +test_func (void) +{ +} diff --git a/gcc/toplev.c b/gcc/toplev.c index b066bcc7229..5d3b46f000e 100644 --- a/gcc/toplev.c +++ b/gcc/toplev.c @@ -1200,29 +1200,119 @@ target_supports_section_anchors_p (void) return true; } -/* Default the align_* variables to 1 if they're still unset, and - set up the align_*_log variables. */ +/* Parse "N[:M][:...]" into struct align_flags A. + VALUES contains parsed values (in reverse order), all processed + values are popped. */ + static void -init_alignments (void) +read_log_maxskip (auto_vec &values, align_flags_tuple *a) { - if (align_loops <= 0) - align_loops = 1; - if (align_loops_max_skip > align_loops) - align_loops_max_skip = align_loops - 1; - align_loops_log = floor_log2 (align_loops * 2 - 1); - if (align_jumps <= 0) - align_jumps = 1; - if (align_jumps_max_skip > align_jumps) - align_jumps_max_skip = align_jumps - 1; - align_jumps_log = floor_log2 (align_jumps * 2 - 1); - if (align_labels <= 0) - align_labels = 1; - align_labels_log = floor_log2 (align_labels * 2 - 1); - if (align_labels_max_skip > align_labels) - align_labels_max_skip = align_labels - 1; - if (align_functions <= 0) - align_functions = 1; - align_functions_log = floor_log2 (align_functions * 2 - 1); + unsigned n = values.pop (); + if (n != 0) + a->log = floor_log2 (n * 2 - 1); + if (values.is_empty ()) + a->maxskip = n ? n - 1 : 0; + else + { + unsigned m = values.pop (); + if (m > n) + m = n; + /* -falign-foo=N:M means M-1 max bytes of padding, not M. */ + if (m > 0) + m--; + a->maxskip = m; + } +} + +/* Parse "N[:M[:N2[:M2]]]" string FLAG into a pair of struct align_flags. */ + +static void +parse_N_M (const char *flag, align_flags &a, unsigned int min_align_log) +{ + if (flag) + { + static hash_map cache; + align_flags *entry = cache.get (flag); + if (entry) + { + a = *entry; + return; + } + + auto_vec result_values; + bool r = parse_and_check_align_values (flag, NULL, result_values, false, + UNKNOWN_LOCATION); + if (!r) + return; + + /* Reverse values for easier manipulation. */ + result_values.reverse (); + + read_log_maxskip (result_values, &a.levels[0]); + if (!result_values.is_empty ()) + read_log_maxskip (result_values, &a.levels[1]); +#ifdef SUBALIGN_LOG + else + { + /* N2[:M2] is not specified. This arch has a default for N2. + Before -falign-foo=N:M:N2:M2 was introduced, x86 had a tweak. + -falign-functions=N with N > 8 was adding secondary alignment. + -falign-functions=10 was emitting this before every function: + .p2align 4,,9 + .p2align 3 + Now this behavior (and more) can be explicitly requested: + -falign-functions=16:10:8 + Retain old behavior if N2 is missing: */ + + int align = 1 << a.levels[0].log; + int subalign = 1 << SUBALIGN_LOG; + + if (a.levels[0].log > SUBALIGN_LOG + && a.levels[0].maxskip >= subalign - 1) + { + /* Set N2 unless subalign can never have any effect. */ + if (align > a.levels[0].maxskip + 1) + a.levels[1].log = SUBALIGN_LOG; + } + } +#endif + + /* Cache seen value. */ + cache.put (flag, a); + } + else + { + /* Reset values to zero. */ + for (unsigned i = 0; i < 2; i++) + { + a.levels[i].log = 0; + a.levels[i].maxskip = 0; + } + } + + if ((unsigned int)a.levels[0].log < min_align_log) + { + a.levels[0].log = min_align_log; + a.levels[0].maxskip = (1 << min_align_log) - 1; + } +} + +/* Minimum alignment requirements, if arch has them. */ + +unsigned int min_align_loops_log = 0; +unsigned int min_align_jumps_log = 0; +unsigned int min_align_labels_log = 0; +unsigned int min_align_functions_log = 0; + +/* Process -falign-foo=N[:M[:N2[:M2]]] options. */ + +void +parse_alignment_opts (void) +{ + parse_N_M (str_align_loops, align_loops, min_align_loops_log); + parse_N_M (str_align_jumps, align_jumps, min_align_jumps_log); + parse_N_M (str_align_labels, align_labels, min_align_labels_log); + parse_N_M (str_align_functions, align_functions, min_align_functions_log); } /* Process the options that have been parsed. */ @@ -1768,9 +1858,6 @@ process_options (void) static void backend_init_target (void) { - /* Initialize alignment variables. */ - init_alignments (); - /* This depends on stack_pointer_rtx. */ init_fake_stack_mems (); diff --git a/gcc/toplev.h b/gcc/toplev.h index c97375b1ca1..98f3ceea872 100644 --- a/gcc/toplev.h +++ b/gcc/toplev.h @@ -93,6 +93,13 @@ extern bool set_src_pwd (const char *); extern HOST_WIDE_INT get_random_seed (bool); extern void set_random_seed (const char *); +extern unsigned int min_align_loops_log; +extern unsigned int min_align_jumps_log; +extern unsigned int min_align_labels_log; +extern unsigned int min_align_functions_log; + +extern void parse_alignment_opts (void); + extern void initialize_rtl (void); #endif /* ! GCC_TOPLEV_H */ diff --git a/gcc/tree-streamer-in.c b/gcc/tree-streamer-in.c index 912fa5f0f02..add3b32ba7b 100644 --- a/gcc/tree-streamer-in.c +++ b/gcc/tree-streamer-in.c @@ -531,7 +531,7 @@ streamer_read_tree_bitfields (struct lto_input_block *ib, unpack_ts_translation_unit_decl_value_fields (data_in, &bp, expr); if (CODE_CONTAINS_STRUCT (code, TS_OPTIMIZATION)) - cl_optimization_stream_in (&bp, TREE_OPTIMIZATION (expr)); + cl_optimization_stream_in (data_in, &bp, TREE_OPTIMIZATION (expr)); if (CODE_CONTAINS_STRUCT (code, TS_BINFO)) { diff --git a/gcc/tree-streamer-out.c b/gcc/tree-streamer-out.c index 03145b4cf58..f70d8215288 100644 --- a/gcc/tree-streamer-out.c +++ b/gcc/tree-streamer-out.c @@ -466,7 +466,7 @@ streamer_write_tree_bitfields (struct output_block *ob, tree expr) pack_ts_translation_unit_decl_value_fields (ob, &bp, expr); if (CODE_CONTAINS_STRUCT (code, TS_OPTIMIZATION)) - cl_optimization_stream_out (&bp, TREE_OPTIMIZATION (expr)); + cl_optimization_stream_out (ob, &bp, TREE_OPTIMIZATION (expr)); if (CODE_CONTAINS_STRUCT (code, TS_BINFO)) bp_pack_var_len_unsigned (&bp, vec_safe_length (BINFO_BASE_ACCESSES (expr))); diff --git a/gcc/tree.c b/gcc/tree.c index e8dc42557d0..966b6bd5e3c 100644 --- a/gcc/tree.c +++ b/gcc/tree.c @@ -11946,30 +11946,18 @@ cl_option_hasher::equal (tree x, tree y) { const_tree const xt = x; const_tree const yt = y; - const char *xp; - const char *yp; - size_t len; if (TREE_CODE (xt) != TREE_CODE (yt)) return 0; if (TREE_CODE (xt) == OPTIMIZATION_NODE) - { - xp = (const char *)TREE_OPTIMIZATION (xt); - yp = (const char *)TREE_OPTIMIZATION (yt); - len = sizeof (struct cl_optimization); - } - + return cl_optimization_option_eq (TREE_OPTIMIZATION (xt), + TREE_OPTIMIZATION (yt)); else if (TREE_CODE (xt) == TARGET_OPTION_NODE) - { - return cl_target_option_eq (TREE_TARGET_OPTION (xt), - TREE_TARGET_OPTION (yt)); - } - + return cl_target_option_eq (TREE_TARGET_OPTION (xt), + TREE_TARGET_OPTION (yt)); else gcc_unreachable (); - - return (memcmp (xp, yp, len) == 0); } /* Build an OPTIMIZATION_NODE based on the options in OPTS. */ diff --git a/gcc/varasm.c b/gcc/varasm.c index 6b9f87b203f..62ddf770077 100644 --- a/gcc/varasm.c +++ b/gcc/varasm.c @@ -1809,17 +1809,20 @@ assemble_start_function (tree decl, const char *fnname) && optimize_function_for_speed_p (cfun)) { #ifdef ASM_OUTPUT_MAX_SKIP_ALIGN - int align_log = align_functions_log; + int align_log = align_functions.levels[0].log; #endif - int max_skip = align_functions - 1; + int max_skip = align_functions.levels[0].maxskip; if (flag_limit_function_alignment && crtl->max_insn_address > 0 && max_skip >= crtl->max_insn_address) max_skip = crtl->max_insn_address - 1; #ifdef ASM_OUTPUT_MAX_SKIP_ALIGN ASM_OUTPUT_MAX_SKIP_ALIGN (asm_out_file, align_log, max_skip); + if (max_skip == align_functions.levels[0].maxskip) + ASM_OUTPUT_MAX_SKIP_ALIGN (asm_out_file, align_functions.levels[1].log, + align_functions.levels[1].maxskip); #else - ASM_OUTPUT_ALIGN (asm_out_file, align_functions_log); + ASM_OUTPUT_ALIGN (asm_out_file, align_functions.levels[0].log); #endif } --------------2.16.3--