Commit 247a370b by Jan Hubicka Committed by Jan Hubicka

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
parent 13fac94a
Mon Aug 20 01:44:50 CEST 2001 Jan Hubicka <jh@suse.cz>
* 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.
2001-08-19 Geoffrey Keating <geoffk@redhat.com> 2001-08-19 Geoffrey Keating <geoffk@redhat.com>
* doc/invoke.texi (MIPS Options): Document -mfused-madd. * doc/invoke.texi (MIPS Options): Document -mfused-madd.
......
...@@ -7226,10 +7226,10 @@ the target supports DWARF 2 frame unwind information. ...@@ -7226,10 +7226,10 @@ the target supports DWARF 2 frame unwind information.
This describes commands for alignment. This describes commands for alignment.
@table @code @table @code
@findex LABEL_ALIGN_AFTER_BARRIER @findex JUMP_ALIGN
@item LABEL_ALIGN_AFTER_BARRIER (@var{label}) @item JUMP_ALIGN (@var{label})
The alignment (log base 2) to put in front of @var{label}, which follows The alignment (log base 2) to put in front of @var{label}, which is
a @code{BARRIER}. a common destination of jumps and has no fallthru incomming edge.
This macro need not be defined if you don't want any special alignment This macro need not be defined if you don't want any special alignment
to be done at such a time. Most machine descriptions do not currently to be done at such a time. Most machine descriptions do not currently
...@@ -7238,8 +7238,16 @@ define the macro. ...@@ -7238,8 +7238,16 @@ define the macro.
Unless it's necessary to inspect the @var{label} parameter, it is better Unless it's necessary to inspect the @var{label} parameter, it is better
to set the variable @var{align_jumps} in the target's to set the variable @var{align_jumps} in the target's
@code{OVERRIDE_OPTIONS}. Otherwise, you should try to honour the user's @code{OVERRIDE_OPTIONS}. Otherwise, you should try to honour the user's
selection in @var{align_jumps} in a @code{LABEL_ALIGN_AFTER_BARRIER} selection in @var{align_jumps} in a @code{JUMP_ALIGN} implementation.
implementation.
@findex LABEL_ALIGN_AFTER_BARRIER
@item LABEL_ALIGN_AFTER_BARRIER (@var{label})
The alignment (log base 2) to put in front of @var{label}, which follows
a @code{BARRIER}.
This macro need not be defined if you don't want any special alignment
to be done at such a time. Most machine descriptions do not currently
define the macro.
@findex LABEL_ALIGN_AFTER_BARRIER_MAX_SKIP @findex LABEL_ALIGN_AFTER_BARRIER_MAX_SKIP
@item LABEL_ALIGN_AFTER_BARRIER_MAX_SKIP @item LABEL_ALIGN_AFTER_BARRIER_MAX_SKIP
......
...@@ -643,11 +643,6 @@ static struct label_alignment *label_align; ...@@ -643,11 +643,6 @@ static struct label_alignment *label_align;
void void
init_insn_lengths () init_insn_lengths ()
{ {
if (label_align)
{
free (label_align);
label_align = 0;
}
if (uid_shuid) if (uid_shuid)
{ {
free (uid_shuid); free (uid_shuid);
...@@ -791,11 +786,19 @@ get_attr_length (insn) ...@@ -791,11 +786,19 @@ get_attr_length (insn)
#endif #endif
#ifndef LABEL_ALIGN_AFTER_BARRIER #ifndef LABEL_ALIGN_AFTER_BARRIER
#define LABEL_ALIGN_AFTER_BARRIER(LABEL) align_jumps_log #define LABEL_ALIGN_AFTER_BARRIER(LABEL) 1
#endif #endif
#ifndef LABEL_ALIGN_AFTER_BARRIER_MAX_SKIP #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 #endif
#ifndef ADDR_VEC_ALIGN #ifndef ADDR_VEC_ALIGN
...@@ -946,6 +949,88 @@ insn_current_reference_address (branch) ...@@ -946,6 +949,88 @@ insn_current_reference_address (branch)
} }
#endif /* HAVE_ATTR_length */ #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 /* Make a pass over all insns and compute their actual lengths by shortening
any branches of variable length if possible. */ any branches of variable length if possible. */
...@@ -983,20 +1068,33 @@ shorten_branches (first) ...@@ -983,20 +1068,33 @@ shorten_branches (first)
#endif #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. */ /* Compute maximum UID and allocate label_align / uid_shuid. */
max_uid = get_max_uid (); max_uid = get_max_uid ();
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 (); 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); 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 /* Initialize label_align and set up uid_shuid to be strictly
monotonically rising with insn order. */ monotonically rising with insn order. */
...@@ -1024,6 +1122,14 @@ shorten_branches (first) ...@@ -1024,6 +1122,14 @@ shorten_branches (first)
{ {
rtx next; 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); log = LABEL_ALIGN (insn);
if (max_log < log) if (max_log < log)
{ {
...@@ -1074,41 +1180,6 @@ shorten_branches (first) ...@@ -1074,41 +1180,6 @@ shorten_branches (first)
break; 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 #ifdef HAVE_ATTR_length
......
...@@ -20,6 +20,9 @@ along with GNU CC; see the file COPYING. If not, write to ...@@ -20,6 +20,9 @@ along with GNU CC; see the file COPYING. If not, write to
the Free Software Foundation, 59 Temple Place - Suite 330, the Free Software Foundation, 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */ Boston, MA 02111-1307, USA. */
/* Compute branch alignments based on frequency information in the CFG. */
extern void compute_alignments PARAMS ((void));
/* Initialize data in final at the beginning of a compilation. */ /* Initialize data in final at the beginning of a compilation. */
extern void init_final PARAMS ((const char *)); extern void init_final PARAMS ((const char *));
......
...@@ -606,8 +606,11 @@ typedef struct block_info_def ...@@ -606,8 +606,11 @@ typedef struct block_info_def
/* To keep queue of basic blocks to process. */ /* To keep queue of basic blocks to process. */
basic_block next; basic_block next;
/* True if block already converted. */ /* True if block needs to be visited in prop_freqency. */
int visited:1; int tovisit:1;
/* Number of predecesors we need to visit first. */
int npredecesors;
} *block_info; } *block_info;
/* Similar information for edges. */ /* Similar information for edges. */
...@@ -634,6 +637,27 @@ propagate_freq (head) ...@@ -634,6 +637,27 @@ propagate_freq (head)
basic_block last = bb; basic_block last = bb;
edge e; edge e;
basic_block nextbb; basic_block nextbb;
int n;
/* For each basic block we need to visit count number of his predecesors
we need to visit first. */
for (n = 0; n < n_basic_blocks; n++)
{
basic_block bb = BASIC_BLOCK (n);
if (BLOCK_INFO (bb)->tovisit)
{
int count = 0;
for (e = bb->pred; e; e = e->pred_next)
if (BLOCK_INFO (e->src)->tovisit && !(e->flags & EDGE_DFS_BACK))
count++;
else if (BLOCK_INFO (e->src)->tovisit
&& rtl_dump_file && !EDGE_INFO (e)->back_edge)
fprintf (rtl_dump_file,
"Irreducible region hit, ignoring edge to %i->%i\n",
e->src->index, bb->index);
BLOCK_INFO (bb)->npredecesors = count;
}
}
BLOCK_INFO (head)->frequency = 1; BLOCK_INFO (head)->frequency = 1;
for (; bb; bb = nextbb) for (; bb; bb = nextbb)
...@@ -646,31 +670,16 @@ propagate_freq (head) ...@@ -646,31 +670,16 @@ propagate_freq (head)
/* Compute frequency of basic block. */ /* Compute frequency of basic block. */
if (bb != head) if (bb != head)
{ {
#ifdef ENABLE_CHECKING
for (e = bb->pred; e; e = e->pred_next) for (e = bb->pred; e; e = e->pred_next)
if (!BLOCK_INFO (e->src)->visited && !(e->flags & EDGE_DFS_BACK)) if (BLOCK_INFO (e->src)->tovisit && !(e->flags & EDGE_DFS_BACK))
break; abort ();
#endif
/* We haven't proceeded all predecessors of edge e yet. */
if (e)
{
if (!nextbb)
nextbb = e->dest;
else
BLOCK_INFO (last)->next = e->dest;
last = e->dest;
continue;
}
if (rtl_dump_file)
for (e = bb->pred; e; e = e->pred_next)
if (!BLOCK_INFO (e->src)->visited && !EDGE_INFO (e)->back_edge)
fprintf (rtl_dump_file,
"Irreducible region hit, ignoring edge to %i->%i\n",
e->src->index, bb->index);
for (e = bb->pred; e; e = e->pred_next) for (e = bb->pred; e; e = e->pred_next)
if (EDGE_INFO (e)->back_edge) if (EDGE_INFO (e)->back_edge)
cyclic_probability += EDGE_INFO (e)->back_edge_prob; cyclic_probability += EDGE_INFO (e)->back_edge_prob;
else if (BLOCK_INFO (e->src)->visited) else if (!(e->flags & EDGE_DFS_BACK))
frequency += (e->probability frequency += (e->probability
* BLOCK_INFO (e->src)->frequency / * BLOCK_INFO (e->src)->frequency /
REG_BR_PROB_BASE); REG_BR_PROB_BASE);
...@@ -681,7 +690,7 @@ propagate_freq (head) ...@@ -681,7 +690,7 @@ propagate_freq (head)
BLOCK_INFO (bb)->frequency = frequency / (1 - cyclic_probability); BLOCK_INFO (bb)->frequency = frequency / (1 - cyclic_probability);
} }
BLOCK_INFO (bb)->visited = 1; BLOCK_INFO (bb)->tovisit = 0;
/* Compute back edge frequencies. */ /* Compute back edge frequencies. */
for (e = bb->succ; e; e = e->succ_next) for (e = bb->succ; e; e = e->succ_next)
...@@ -692,9 +701,11 @@ propagate_freq (head) ...@@ -692,9 +701,11 @@ propagate_freq (head)
/* Propagate to successor blocks. */ /* Propagate to successor blocks. */
for (e = bb->succ; e; e = e->succ_next) for (e = bb->succ; e; e = e->succ_next)
if (!EDGE_INFO (e)->back_edge if (!(e->flags & EDGE_DFS_BACK)
&& !BLOCK_INFO (e->dest)->visited && BLOCK_INFO (e->dest)->npredecesors)
&& !BLOCK_INFO (e->dest)->next && e->dest != last) {
BLOCK_INFO (e->dest)->npredecesors--;
if (!BLOCK_INFO (e->dest)->npredecesors)
{ {
if (!nextbb) if (!nextbb)
nextbb = e->dest; nextbb = e->dest;
...@@ -703,6 +714,7 @@ propagate_freq (head) ...@@ -703,6 +714,7 @@ propagate_freq (head)
last = e->dest; last = e->dest;
} }
} }
}
} }
/* Estimate probabilities of loopback edges in loops at same nest level. */ /* Estimate probabilities of loopback edges in loops at same nest level. */
...@@ -739,8 +751,8 @@ estimate_loops_at_level (first_loop) ...@@ -739,8 +751,8 @@ estimate_loops_at_level (first_loop)
for (l = loop->shared ? first_loop : loop; l != loop->next; l = l->next) for (l = loop->shared ? first_loop : loop; l != loop->next; l = l->next)
if (loop->header == l->header) if (loop->header == l->header)
EXECUTE_IF_SET_IN_SBITMAP (l->nodes, 0, n, EXECUTE_IF_SET_IN_SBITMAP (l->nodes, 0, n,
BLOCK_INFO (BASIC_BLOCK (n))->visited = BLOCK_INFO (BASIC_BLOCK (n))->tovisit = 1
0); );
propagate_freq (loop->header); propagate_freq (loop->header);
} }
} }
...@@ -848,7 +860,7 @@ estimate_bb_frequencies (loops) ...@@ -848,7 +860,7 @@ estimate_bb_frequencies (loops)
else else
bb = BASIC_BLOCK (i); bb = BASIC_BLOCK (i);
bb->aux = bi + i + 2; bb->aux = bi + i + 2;
BLOCK_INFO (bb)->visited = 1; BLOCK_INFO (bb)->tovisit = 0;
for (e = bb->succ; e; e = e->succ_next) for (e = bb->succ; e; e = e->succ_next)
{ {
e->aux = ei + edgenum, edgenum++; e->aux = ei + edgenum, edgenum++;
...@@ -862,9 +874,9 @@ estimate_bb_frequencies (loops) ...@@ -862,9 +874,9 @@ estimate_bb_frequencies (loops)
/* Now fake loop around whole function to finalize probabilities. */ /* Now fake loop around whole function to finalize probabilities. */
for (i = 0; i < n_basic_blocks; i++) for (i = 0; i < n_basic_blocks; i++)
BLOCK_INFO (BASIC_BLOCK (i))->visited = 0; BLOCK_INFO (BASIC_BLOCK (i))->tovisit = 1;
BLOCK_INFO (ENTRY_BLOCK_PTR)->visited = 0; BLOCK_INFO (ENTRY_BLOCK_PTR)->tovisit = 1;
BLOCK_INFO (EXIT_BLOCK_PTR)->visited = 0; BLOCK_INFO (EXIT_BLOCK_PTR)->tovisit = 1;
propagate_freq (ENTRY_BLOCK_PTR); propagate_freq (ENTRY_BLOCK_PTR);
for (i = 0; i < n_basic_blocks; i++) for (i = 0; i < n_basic_blocks; i++)
......
...@@ -3608,6 +3608,7 @@ rest_of_compilation (decl) ...@@ -3608,6 +3608,7 @@ rest_of_compilation (decl)
close_dump_file (DFI_bbro, print_rtl_with_bb, insns); close_dump_file (DFI_bbro, print_rtl_with_bb, insns);
timevar_pop (TV_REORDER_BLOCKS); timevar_pop (TV_REORDER_BLOCKS);
} }
compute_alignments ();
/* If a machine dependent reorganization is needed, call it. */ /* If a machine dependent reorganization is needed, call it. */
#ifdef MACHINE_DEPENDENT_REORG #ifdef MACHINE_DEPENDENT_REORG
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment