diff options
44 files changed, 861 insertions, 347 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 362ef15..f644bef 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,4 +1,123 @@ 2018-07-04 Denys Vlasenko <dvlasenk@redhat.com> + Martin Liska <mliska@suse.cz> + + 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/ia64/ia64.c (ia64_option_override): Set default values + for alignment options. + * config/m68k/m68k.c: Handle new str_align_* options. + * config/mips/mips.c (mips_set_compression_mode): Change + type of constants. + (mips_option_override): Set default values for options. + * config/powerpcspe/powerpcspe.c (rs6000_option_override_internal): + Likewise. + * 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/s390/s390.c (s390_asm_output_function_label): Use new + macros. + * config/sh/sh.c (sh_override_options_after_change): + Change type of constants. + * config/spu/spu.c (spu_sched_init): Likewise. + * config/sparc/sparc.c (sparc_option_override): Set default + values for options. + * config/visium/visium.c (visium_option_override): Likewise. + * config/visium/visium.h (ASM_OUTPUT_MAX_SKIP_ALIGN): Do not + emit p2align format with last argument if it's not needed. + * 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. + (align_loops_value): New macro. + (align_jumps_value): New macro. + (align_labels_value): New macro. + (align_functions_value): New macro. + * 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. + +2018-07-04 Denys Vlasenko <dvlasenk@redhat.com> * config/i386/dragonfly.h: (ASM_OUTPUT_MAX_SKIP_ALIGN): Use a simpler align directive also if MAXSKIP = ALIGN-1. diff --git a/gcc/common.opt b/gcc/common.opt index 5a50bc27..963c37f 100644 --- a/gcc/common.opt +++ b/gcc/common.opt @@ -959,35 +959,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 664240e..277ee55 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) +/* 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 514ddc4..bc11a78 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 d75d45f..143f9d0 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. */ @@ -844,9 +844,9 @@ static const struct tune_params thunderx_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. */ @@ -924,9 +924,9 @@ static const struct tune_params saphira_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. */ @@ -950,9 +950,9 @@ static const struct tune_params thunderx2t99_tunings = 4, /* issue_rate. */ (AARCH64_FUSE_CMP_BRANCH | AARCH64_FUSE_AES_AESMC | AARCH64_FUSE_ALU_BRANCH), /* fusible_ops */ - 16, /* function_align. */ - 8, /* jump_align. */ - 16, /* loop_align. */ + "16", /* function_align. */ + "8", /* jump_align. */ + "16", /* loop_align. */ 3, /* int_reassoc_width. */ 2, /* fp_reassoc_width. */ 2, /* vec_reassoc_width. */ @@ -10572,12 +10572,12 @@ aarch64_override_options_after_change_1 (struct gcc_options *opts) alignment to what the target wants. */ if (!opts->x_optimize_size) { - if (opts->x_align_loops <= 0) - opts->x_align_loops = aarch64_tune_params.loop_align; - if (opts->x_align_jumps <= 0) - opts->x_align_jumps = aarch64_tune_params.jump_align; - if (opts->x_align_functions <= 0) - opts->x_align_functions = aarch64_tune_params.function_align; + if (opts->x_flag_align_loops && !opts->x_str_align_loops) + opts->x_str_align_loops = aarch64_tune_params.loop_align; + if (opts->x_flag_align_jumps && !opts->x_str_align_jumps) + opts->x_str_align_jumps = aarch64_tune_params.jump_align; + if (opts->x_flag_align_functions && !opts->x_str_align_functions) + opts->x_str_align_functions = aarch64_tune_params.function_align; } /* We default to no pc-relative literal loads. */ diff --git a/gcc/config/alpha/alpha.c b/gcc/config/alpha/alpha.c index 26d89f3..9adfe15 100644 --- a/gcc/config/alpha/alpha.c +++ b/gcc/config/alpha/alpha.c @@ -67,6 +67,7 @@ along with GCC; see the file COPYING3. If not see #include "params.h" #include "builtins.h" #include "rtl-iter.h" +#include "flags.h" /* This file should be included last. */ #include "target-def.h" @@ -614,13 +615,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. */ @@ -9268,10 +9269,11 @@ alpha_align_insns_1 (unsigned int max_align, /* Let shorten branches care for assigning alignments to code labels. */ shorten_branches (get_insns ()); - if (align_functions < 4) + unsigned int option_alignment = align_functions_max_skip + 1; + if (option_alignment < 4) align = 4; - else if ((unsigned int) align_functions < max_align) - align = align_functions; + else if ((unsigned int) option_alignment < max_align) + align = option_alignment; else align = max_align; diff --git a/gcc/config/arm/arm.c b/gcc/config/arm/arm.c index f1a9958..8d5897c 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 41461d5..9e46b7b 100644 --- a/gcc/config/i386/i386.c +++ b/gcc/config/i386/i386.c @@ -834,53 +834,58 @@ 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}, - {"tremont", &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"}, + {"tremont", &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 @@ -3365,20 +3370,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/ia64/ia64.c b/gcc/config/ia64/ia64.c index 7488871..f121cee 100644 --- a/gcc/config/ia64/ia64.c +++ b/gcc/config/ia64/ia64.c @@ -6107,10 +6107,10 @@ ia64_option_override (void) init_machine_status = ia64_init_machine_status; - if (align_functions <= 0) - align_functions = 64; - if (align_loops <= 0) - align_loops = 32; + if (flag_align_functions && !str_align_functions) + str_align_functions = "64"; + if (flag_align_loops && !str_align_loops) + str_align_loops = "32"; if (TARGET_ABI_OPEN_VMS) flag_no_common = 1; diff --git a/gcc/config/m68k/m68k.c b/gcc/config/m68k/m68k.c index 495a80b..cea5c0e 100644 --- a/gcc/config/m68k/m68k.c +++ b/gcc/config/m68k/m68k.c @@ -65,6 +65,7 @@ along with GCC; see the file COPYING3. If not see #include "optabs.h" #include "builtins.h" #include "rtl-iter.h" +#include "toplev.h" /* This file should be included last. */ #include "target-def.h" @@ -651,15 +652,17 @@ m68k_option_override (void) } #ifndef ASM_OUTPUT_ALIGN_WITH_NOP - if (align_labels > 2) + parse_alignment_opts (); + if (align_labels_value > 2) { - warning (0, "-falign-labels=%d is not supported", align_labels); - align_labels = 0; + warning (0, "-falign-labels=%d is not supported", align_labels_value); + str_align_labels = "1"; } - if (align_loops > 2) + + if (align_loops_value > 2) { - warning (0, "-falign-loops=%d is not supported", align_loops); - align_loops = 0; + warning (0, "-falign-loops=%d is not supported", align_loops_value); + str_align_loops = "1"; } #endif diff --git a/gcc/config/mips/mips.c b/gcc/config/mips/mips.c index ad39304..75ee834 100644 --- a/gcc/config/mips/mips.c +++ b/gcc/config/mips/mips.c @@ -501,9 +501,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]; @@ -19517,9 +19517,9 @@ mips_set_compression_mode (unsigned int compression_mode) flag_schedule_insns = mips_base_schedule_insns; flag_reorder_blocks_and_partition = mips_base_reorder_blocks_and_partition; flag_move_loop_invariants = mips_base_move_loop_invariants; - align_loops = mips_base_align_loops; - align_jumps = mips_base_align_jumps; - align_functions = mips_base_align_functions; + str_align_loops = mips_base_align_loops; + str_align_jumps = mips_base_align_jumps; + str_align_functions = mips_base_align_functions; target_flags &= ~(MASK_MIPS16 | MASK_MICROMIPS); target_flags |= compression_mode; @@ -19589,12 +19589,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; @@ -20278,9 +20278,9 @@ mips_option_override (void) mips_base_schedule_insns = flag_schedule_insns; mips_base_reorder_blocks_and_partition = flag_reorder_blocks_and_partition; mips_base_move_loop_invariants = flag_move_loop_invariants; - mips_base_align_loops = align_loops; - mips_base_align_jumps = align_jumps; - mips_base_align_functions = align_functions; + mips_base_align_loops = str_align_loops; + mips_base_align_jumps = str_align_jumps; + mips_base_align_functions = str_align_functions; /* Now select the ISA mode. diff --git a/gcc/config/powerpcspe/powerpcspe.c b/gcc/config/powerpcspe/powerpcspe.c index f67505a..80f67de 100644 --- a/gcc/config/powerpcspe/powerpcspe.c +++ b/gcc/config/powerpcspe/powerpcspe.c @@ -5406,29 +5406,30 @@ rs6000_option_override_internal (bool global_init_p) if (rs6000_cpu == PROCESSOR_TITAN || rs6000_cpu == 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; + + if (flag_align_jumps && !str_align_jumps) + str_align_jumps = "16"; + if (flag_align_loops && !str_align_loops) + str_align_loops = "16"; } /* Arrange to save and restore machine status around nested functions. */ diff --git a/gcc/config/rs6000/rs6000.c b/gcc/config/rs6000/rs6000.c index e61c9ce..f815221 100644 --- a/gcc/config/rs6000/rs6000.c +++ b/gcc/config/rs6000/rs6000.c @@ -4958,29 +4958,30 @@ 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; + + if (flag_align_jumps && !str_align_jumps) + str_align_jumps = "16"; + if (flag_align_loops && !str_align_loops) + str_align_loops = "16"; } /* 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 fe467f7..af97bef 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 a2aa392..2f5a0e9 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/s390/s390.c b/gcc/config/s390/s390.c index 5add598..23c3f3d 100644 --- a/gcc/config/s390/s390.c +++ b/gcc/config/s390/s390.c @@ -7543,9 +7543,9 @@ s390_asm_output_function_label (FILE *asm_out_file, const char *fname, function_alignment = MAX (8, DECL_ALIGN (decl) / BITS_PER_UNIT); if (! DECL_USER_ALIGN (decl)) function_alignment = MAX (function_alignment, - (unsigned int) align_functions); + (unsigned int) align_functions_max_skip + 1); fputs ("\t# alignment for hotpatch\n", asm_out_file); - ASM_OUTPUT_ALIGN (asm_out_file, floor_log2 (function_alignment)); + ASM_OUTPUT_ALIGN (asm_out_file, align_functions_log); } if (S390_USE_TARGET_ATTRIBUTE && TARGET_DEBUG_ARG) diff --git a/gcc/config/sh/sh.c b/gcc/config/sh/sh.c index 5f6fbb3..a1cad42 100644 --- a/gcc/config/sh/sh.c +++ b/gcc/config/sh/sh.c @@ -66,6 +66,7 @@ along with GCC; see the file COPYING3. If not see #include "builtins.h" #include "rtl-iter.h" #include "regs.h" +#include "toplev.h" /* This file should be included last. */ #include "target-def.h" @@ -1007,29 +1008,37 @@ 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; + /* Parse values so that we can compare for current value. */ + parse_alignment_opts (); + if (flag_align_jumps && !str_align_jumps) + str_align_jumps = "2"; + else if (align_jumps_value < 2) + str_align_jumps = "2"; - 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 values so that we can compare for current value. */ + parse_alignment_opts (); + int min_align = MAX (align_loops_value, align_jumps_value); /* 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 (align_functions_value < min_align) + { + char *r = XNEWVEC (char, 16); + sprintf (r, "%d", min_align); + str_align_functions = r; + } } } diff --git a/gcc/config/sparc/sparc.c b/gcc/config/sparc/sparc.c index 6b6f155..d90a260 100644 --- a/gcc/config/sparc/sparc.c +++ b/gcc/config/sparc/sparc.c @@ -1906,7 +1906,7 @@ sparc_option_override (void) target_flags &= ~MASK_FSMULD; /* Supply a default value for align_functions. */ - if (align_functions == 0) + if (flag_align_functions && !str_align_functions) { if (sparc_cpu == PROCESSOR_ULTRASPARC || sparc_cpu == PROCESSOR_ULTRASPARC3 @@ -1914,10 +1914,10 @@ sparc_option_override (void) || sparc_cpu == PROCESSOR_NIAGARA2 || sparc_cpu == PROCESSOR_NIAGARA3 || sparc_cpu == PROCESSOR_NIAGARA4) - align_functions = 32; + str_align_functions = "32"; else if (sparc_cpu == PROCESSOR_NIAGARA7 || sparc_cpu == PROCESSOR_M8) - align_functions = 64; + str_align_functions = "64"; } /* Validate PCC_STRUCT_RETURN. */ diff --git a/gcc/config/spu/spu.c b/gcc/config/spu/spu.c index 5393579..fe2a2a3 100644 --- a/gcc/config/spu/spu.c +++ b/gcc/config/spu/spu.c @@ -58,6 +58,8 @@ #include "dumpfile.h" #include "builtins.h" #include "rtl-iter.h" +#include "flags.h" +#include "toplev.h" /* This file should be included last. */ #include "target-def.h" @@ -238,8 +240,9 @@ spu_option_override (void) flag_omit_frame_pointer = 1; /* Functions must be 8 byte aligned so we correctly handle dual issue */ - if (align_functions < 8) - align_functions = 8; + parse_alignment_opts (); + if (align_functions_value < 8) + str_align_functions = "8"; spu_hint_dist = 8*4 - spu_max_nops*4; if (spu_hint_dist < 0) @@ -2769,7 +2772,7 @@ 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) + if (align_labels_value > 4 || align_loops_value > 4 || align_jumps_value > 4) { /* 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/spu/spu.h b/gcc/config/spu/spu.h index c979750..e846f1c 100644 --- a/gcc/config/spu/spu.h +++ b/gcc/config/spu/spu.h @@ -107,7 +107,7 @@ extern GTY(()) int spu_tune; (GET_CODE (X) == SYMBOL_REF \ && (SYMBOL_REF_FLAGS (X) & SYMBOL_FLAG_ALIGN1) == 0 \ && (! SYMBOL_REF_FUNCTION_P (X) \ - || align_functions >= 16)) + || align_functions_value >= 16)) #define PCC_BITFIELD_TYPE_MATTERS 1 diff --git a/gcc/config/visium/visium.c b/gcc/config/visium/visium.c index 106cdaf..37de624 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/config/visium/visium.h b/gcc/config/visium/visium.h index ebac7f1..dac9a45 100644 --- a/gcc/config/visium/visium.h +++ b/gcc/config/visium/visium.h @@ -1501,7 +1501,8 @@ do \ expression of type `int'. */ #define ASM_OUTPUT_MAX_SKIP_ALIGN(STREAM,LOG,MAX_SKIP) \ if ((LOG) != 0) { \ - if ((MAX_SKIP) == 0) fprintf ((STREAM), "\t.p2align %d\n", (LOG)); \ + if ((MAX_SKIP) == 0 || (MAX_SKIP) >= (1<<(LOG))-1) \ + fprintf ((STREAM), "\t.p2align %d\n", (LOG)); \ else { \ fprintf ((STREAM), "\t.p2align %d,,%d\n", (LOG), (MAX_SKIP)); \ /* Make sure that we have at least 8-byte alignment if > 8-byte \ diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi index 31d4f10..e0e59f6 100644 --- a/gcc/doc/invoke.texi +++ b/gcc/doc/invoke.texi @@ -365,9 +365,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 @@ -9240,19 +9242,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. @@ -9266,12 +9285,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. @@ -9286,12 +9306,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. @@ -9302,12 +9325,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 a17a3a6..ea23865 100644 --- a/gcc/final.c +++ b/gcc/final.c @@ -2528,6 +2528,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, state_align_labels.levels[1].log, + state_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 d5d4d78..bfd645b 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,26 @@ 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 state_align_loops (this_target_flag_state->x_align_loops) +#define state_align_jumps (this_target_flag_state->x_align_jumps) +#define state_align_labels (this_target_flag_state->x_align_labels) +#define state_align_functions (this_target_flag_state->x_align_functions) +#define align_loops_log (state_align_loops.levels[0].log) +#define align_jumps_log (state_align_jumps.levels[0].log) +#define align_labels_log (state_align_labels.levels[0].log) +#define align_functions_log (state_align_functions.levels[0].log) +#define align_loops_max_skip (state_align_loops.levels[0].maxskip) +#define align_jumps_max_skip (state_align_jumps.levels[0].maxskip) +#define align_labels_max_skip (state_align_labels.levels[0].maxskip) +#define align_functions_max_skip (state_align_functions.levels[0].maxskip) +#define align_loops_value (align_loops_max_skip + 1) +#define align_jumps_value (align_jumps_max_skip + 1) +#define align_labels_value (align_labels_max_skip + 1) +#define align_functions_value (align_functions_max_skip + 1) + +/* 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 47232a2..142cdae 100644 --- a/gcc/function.c +++ b/gcc/function.c @@ -4609,6 +4609,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 90d1e17..39b96ba 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 236fcc4..dd279f6 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/ChangeLog b/gcc/lto/ChangeLog index 2059bec..daaf92f4 100644 --- a/gcc/lto/ChangeLog +++ b/gcc/lto/ChangeLog @@ -1,3 +1,11 @@ +2018-07-04 Martin Liska <mliska@suse.cz> + + PR middle-end/66240 + PR target/45996 + PR c/84100 + * lto.c (compare_tree_sccs_1): Use cl_optimization_option_eq + instead of memcmp. + 2018-06-20 Martin Liska <mliska@suse.cz> * lto-symtab.c (lto_symtab_merge_p): Remove not valid diff --git a/gcc/lto/lto.c b/gcc/lto/lto.c index 3b57c12..6f10dab 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 1a365fc..6e33a43 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 fecd4b8..8358b9b 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 " @@ -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<unsigned> &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<unsigned> 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 @@ -2501,6 +2553,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. */ @@ -442,4 +442,11 @@ extern const char *candidates_list_and_hint (const char *arg, char *&str, const auto_vec <const char *> & candidates); + +extern bool parse_and_check_align_values (const char *flag, + const char *name, + auto_vec<unsigned> &result_values, + bool report_error, + location_t loc); + #endif diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 736f01b..930215d 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,5 +1,14 @@ 2018-07-04 Martin Liska <mliska@suse.cz> + 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. + +2018-07-04 Martin Liska <mliska@suse.cz> + * gcc.dg/pr47793.c: Remove. 2018-07-04 Richard Sandiford <richard.sandiford@arm.com> diff --git a/gcc/testsuite/gcc.dg/pr84100.c b/gcc/testsuite/gcc.dg/pr84100.c index 86fbc4f..676d0c7 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 0000000..26d505e --- /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 0000000..27daa1d --- /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 d108096..cf7bab6 100644 --- a/gcc/toplev.c +++ b/gcc/toplev.c @@ -1197,29 +1197,120 @@ 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<unsigned> &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 <nofree_string_hash, align_flags> cache; + align_flags *entry = cache.get (flag); + if (entry) + { + a = *entry; + return; + } + + auto_vec<unsigned> 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, state_align_loops, min_align_loops_log); + parse_N_M (str_align_jumps, state_align_jumps, min_align_jumps_log); + parse_N_M (str_align_labels, state_align_labels, min_align_labels_log); + parse_N_M (str_align_functions, state_align_functions, + min_align_functions_log); } /* Process the options that have been parsed. */ @@ -1722,9 +1813,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 c97375b..98f3cee 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 da3a7ef..4bb420c 100644 --- a/gcc/tree-streamer-in.c +++ b/gcc/tree-streamer-in.c @@ -530,7 +530,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_CONSTRUCTOR)) { diff --git a/gcc/tree-streamer-out.c b/gcc/tree-streamer-out.c index 59db3b9..8b20f0a 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_CONSTRUCTOR)) bp_pack_var_len_unsigned (&bp, CONSTRUCTOR_NELTS (expr)); @@ -11972,30 +11972,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 5769bc6..81f4606 100644 --- a/gcc/varasm.c +++ b/gcc/varasm.c @@ -1805,17 +1805,21 @@ 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 = state_align_functions.levels[0].log; #endif - int max_skip = align_functions - 1; + int max_skip = state_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 == state_align_functions.levels[0].maxskip) + ASM_OUTPUT_MAX_SKIP_ALIGN (asm_out_file, + state_align_functions.levels[1].log, + state_align_functions.levels[1].maxskip); #else - ASM_OUTPUT_ALIGN (asm_out_file, align_functions_log); + ASM_OUTPUT_ALIGN (asm_out_file, state_align_functions.levels[0].log); #endif } |