aboutsummaryrefslogtreecommitdiff
path: root/gcc/toplev.c
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/toplev.c')
-rw-r--r--gcc/toplev.c136
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 ();