+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):
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
#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
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_:
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_:
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_:
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;
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. */
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. */
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. */
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. */
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. */
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. */
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. */
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. */
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. */
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. */
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. */
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. */
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. */
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. */
#include "params.h"
#include "builtins.h"
#include "rtl-iter.h"
+#include "flags.h"
/* This file should be included last. */
#include "target-def.h"
/* ??? 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";
}
\f
/* Returns 1 if VALUE is a mask that contains full bytes of zero or ones. */
/* 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;
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. */
{
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"}
};
\f
static unsigned int
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. */
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;
#include "optabs.h"
#include "builtins.h"
#include "rtl-iter.h"
+#include "toplev.h"
/* This file should be included last. */
#include "target-def.h"
}
#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
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];
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;
/* 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;
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.
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. */
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. */
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");
+ }
}
\f
/* 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) \
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)
#include "builtins.h"
#include "rtl-iter.h"
#include "regs.h"
+#include "toplev.h"
/* This file should be included last. */
#include "target-def.h"
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;
+ }
}
}
\f
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
|| 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. */
#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"
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)
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
(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
/* 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
}
/* 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
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 \
@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
@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.
@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.
@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.
@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.
{
#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);
\f
/* 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;
#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)
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);
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))
{
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 *);
+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
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))
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";
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;
}
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 "";
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 "}";
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 "";
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 "}";
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 "}";
}
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 "
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
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
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. */
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
+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.
"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 ();
}
--- /dev/null
+/* { 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 } } */
--- /dev/null
+/* { dg-do compile } */
+/* { dg-options "-O2 -falign-functions=64:8" } */
+/* { dg-final { scan-assembler ".p2align 6,,7" } } */
+
+void
+test_func (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. */
static void
backend_init_target (void)
{
- /* Initialize alignment variables. */
- init_alignments ();
-
/* This depends on stack_pointer_rtx. */
init_fake_stack_mems ();
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 */
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))
{
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));
{
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. */
&& 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
}