diff options
Diffstat (limited to 'gcc/toplev.c')
-rw-r--r-- | gcc/toplev.c | 136 |
1 files changed, 112 insertions, 24 deletions
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 (); |