diff options
author | Jan Hubicka <jh@suse.cz> | 2001-08-20 01:46:10 +0200 |
---|---|---|
committer | Jan Hubicka <hubicka@gcc.gnu.org> | 2001-08-19 23:46:10 +0000 |
commit | 247a370b4f2f91d4b82c66902d46649e57b1ec91 (patch) | |
tree | 41105a8a5becd86725e0db5742de2ed66c51ad55 /gcc/final.c | |
parent | 13fac94a68a4da815faa73d6a457c3d9d3bf94f5 (diff) | |
download | gcc-247a370b4f2f91d4b82c66902d46649e57b1ec91.zip gcc-247a370b4f2f91d4b82c66902d46649e57b1ec91.tar.gz gcc-247a370b4f2f91d4b82c66902d46649e57b1ec91.tar.bz2 |
final.c (compute_alignments): New function.
* final.c (compute_alignments): New function.
(init_insn_lengths): Do not care label_align.
(LABEL_ALIGN_AFTER_BARRIER): Default to 1.
(LABEL_ALIGN_AFTER_BARRIER_MAX_SKIP): Default to 0.
(JUMP_ALIGN, JUMP_ALIGN_MAX_SKIP): New.
(shorted_branches): Realloc label_align array; do
not call init_insn_lengths; Do not care about loop alignments.
* output.h (compute_alignments): Declare.
* toplev.c (rest_of_compilation): Call compute_alignments.
* tm.texi (JUMP_ALIGN, JUMP_ALIGN_MAX_SKIP): Document.
* predict.c (block_info_def): Add npredecesors, remove nvisited;
change visited to tovisit.
(propagate_freq): Use faster traversing algorithm.
(estimate_loops_at_level, estimate_bb_frequencies): Change visited
to tovisit; reverse meaning.
* predict.c (struct block_info_def): Remove nvisited.
(propagate_freq): Use EDGE_DFS_BACK to detect irreducible regions.
(estimate_bb_frequencies): Call mark_dfs_back_edges.
From-SVN: r45042
Diffstat (limited to 'gcc/final.c')
-rw-r--r-- | gcc/final.c | 175 |
1 files changed, 123 insertions, 52 deletions
diff --git a/gcc/final.c b/gcc/final.c index ec57842..ed4b6ff 100644 --- a/gcc/final.c +++ b/gcc/final.c @@ -643,11 +643,6 @@ static struct label_alignment *label_align; void init_insn_lengths () { - if (label_align) - { - free (label_align); - label_align = 0; - } if (uid_shuid) { free (uid_shuid); @@ -791,11 +786,19 @@ get_attr_length (insn) #endif #ifndef LABEL_ALIGN_AFTER_BARRIER -#define LABEL_ALIGN_AFTER_BARRIER(LABEL) align_jumps_log +#define LABEL_ALIGN_AFTER_BARRIER(LABEL) 1 #endif #ifndef LABEL_ALIGN_AFTER_BARRIER_MAX_SKIP -#define LABEL_ALIGN_AFTER_BARRIER_MAX_SKIP (align_jumps-1) +#define LABEL_ALIGN_AFTER_BARRIER_MAX_SKIP 0 +#endif + +#ifndef JUMP_ALIGN +#define JUMP_ALIGN(LABEL) align_jumps_log +#endif + +#ifndef JUMP_ALIGN_MAX_SKIP +#define JUMP_ALIGN_MAX_SKIP (align_jumps-1) #endif #ifndef ADDR_VEC_ALIGN @@ -946,6 +949,88 @@ insn_current_reference_address (branch) } #endif /* HAVE_ATTR_length */ +void +compute_alignments () +{ + int i; + int log, max_skip, max_log; + + if (label_align) + { + free (label_align); + label_align = 0; + } + + max_labelno = max_label_num (); + min_labelno = get_first_label_num (); + label_align = (struct label_alignment *) + xcalloc (max_labelno - min_labelno + 1, sizeof (struct label_alignment)); + + /* If not optimizing or optimizing for size, don't assign any alignments. */ + if (optimize || optimize_size) + return; + + for (i = 0; i < n_basic_blocks; i++) + { + basic_block bb = BASIC_BLOCK (i); + rtx label = bb->head; + int fallthru_frequency = 0, branch_frequency = 0, has_fallthru = 0; + edge e; + + if (GET_CODE (label) != CODE_LABEL) + continue; + max_log = LABEL_ALIGN (label); + max_skip = LABEL_ALIGN_MAX_SKIP; + + for (e = bb->pred; e; e = e->pred_next) + { + if (e->flags & EDGE_FALLTHRU) + has_fallthru = 1, fallthru_frequency += EDGE_FREQUENCY (e); + else + branch_frequency += EDGE_FREQUENCY (e); + } + + /* There are two purposes to align block with no fallthru incomming edge: + 1) to avoid fetch stalls when branch destination is near cache boundary + 2) to improve cache effciency in case the previous block is not executed + (so it does not need to be in the cache). + + We to catch first case, we align frequently executed blocks. + To catch the second, we align blocks that are executed more frequently + than the predecesor and the predecesor is likely to not be executed + when function is called. */ + + if (!has_fallthru + && (branch_frequency > BB_FREQ_MAX / 10 + || (bb->frequency > BASIC_BLOCK (i - 1)->frequency * 10 + && (BASIC_BLOCK (i - 1)->frequency + <= ENTRY_BLOCK_PTR->frequency / 2)))) + { + log = JUMP_ALIGN (label); + if (max_log < log) + { + max_log = log; + max_skip = JUMP_ALIGN_MAX_SKIP; + } + } + /* In case block is frequent and reached mostly by non-fallthru edge, + align it. It is most likely an first block of loop. */ + if (has_fallthru + && branch_frequency + fallthru_frequency > BB_FREQ_MAX / 10 + && branch_frequency > fallthru_frequency * 5) + { + log = LOOP_ALIGN (label); + if (max_log < log) + { + max_log = log; + max_skip = LOOP_ALIGN_MAX_SKIP; + } + } + LABEL_TO_ALIGNMENT (label) = max_log; + LABEL_TO_MAX_SKIP (label) = max_skip; + } +} + /* Make a pass over all insns and compute their actual lengths by shortening any branches of variable length if possible. */ @@ -983,21 +1068,34 @@ shorten_branches (first) #endif - /* We must do some computations even when not actually shortening, in - order to get the alignment information for the labels. */ - - init_insn_lengths (); - /* Compute maximum UID and allocate label_align / uid_shuid. */ max_uid = get_max_uid (); - max_labelno = max_label_num (); - min_labelno = get_first_label_num (); - label_align = (struct label_alignment *) - xcalloc ((max_labelno - min_labelno + 1), sizeof (struct label_alignment)); - uid_shuid = (int *) xmalloc (max_uid * sizeof *uid_shuid); + if (max_labelno != max_label_num ()) + { + int old = max_labelno; + int n_labels; + int n_old_labels; + + max_labelno = max_label_num (); + + n_labels = max_labelno - min_labelno + 1; + n_old_labels = old - min_labelno + 1; + + label_align = (struct label_alignment *) xrealloc + (label_align, n_labels * sizeof (struct label_alignment)); + + /* Range of labels grows monotonically in the function. Abort here + means that the initialization of array got lost. */ + if (n_old_labels > n_labels) + abort (); + + memset (label_align + n_old_labels, 0, + (n_labels - n_old_labels) * sizeof (struct label_alignment)); + } + /* Initialize label_align and set up uid_shuid to be strictly monotonically rising with insn order. */ /* We use max_log here to keep track of the maximum alignment we want to @@ -1023,6 +1121,14 @@ shorten_branches (first) else if (GET_CODE (insn) == CODE_LABEL) { rtx next; + + /* Merge in alignments computed by compute_alignments. */ + log = LABEL_TO_ALIGNMENT (insn); + if (max_log < log) + { + max_log = log; + max_skip = LABEL_TO_MAX_SKIP (insn); + } log = LABEL_ALIGN (insn); if (max_log < log) @@ -1074,41 +1180,6 @@ shorten_branches (first) break; } } - /* Again, we allow NOTE_INSN_LOOP_BEG - INSN - CODE_LABEL - sequences in order to handle reorg output efficiently. */ - else if (GET_CODE (insn) == NOTE - && NOTE_LINE_NUMBER (insn) == NOTE_INSN_LOOP_BEG) - { - rtx label; - int nest = 0; - - /* Search for the label that starts the loop. - Don't skip past the end of the loop, since that could - lead to putting an alignment where it does not belong. - However, a label after a nested (non-)loop would be OK. */ - for (label = insn; label; label = NEXT_INSN (label)) - { - if (GET_CODE (label) == NOTE - && NOTE_LINE_NUMBER (label) == NOTE_INSN_LOOP_BEG) - nest++; - else if (GET_CODE (label) == NOTE - && NOTE_LINE_NUMBER (label) == NOTE_INSN_LOOP_END - && --nest == 0) - break; - else if (GET_CODE (label) == CODE_LABEL) - { - log = LOOP_ALIGN (label); - if (max_log < log) - { - max_log = log; - max_skip = LOOP_ALIGN_MAX_SKIP; - } - break; - } - } - } - else - continue; } #ifdef HAVE_ATTR_length |