Commit 963acd6f by Kenneth Zadeck Committed by Kenneth Zadeck

re PR tree-optimization/26854 (Inordinate compile times on large routines)

2008-01-22  Kenneth Zadeck <zadeck@naturalbridge.com>

	PR rtl-optimization/26854
	PR rtl-optimization/34400
	PR rtl-optimization/34884
	* ddg.c (create_ddg_dep_from_intra_loop_link): Use
	DF_RD->gen.
	* df.h (df_changeable_flags.DF_RD_NO_TRIM): Deleted
	(df_rd_bb_info.expanded_lr_out): Deleted
	* loop_invariant.c (find_defs): Deleted DF_RD_NO_TRIM flag.
	* loop_iv.c (iv_analysis_loop_init): Ditto.  * df-problems.c
	(df_rd_free_bb_info, df_rd_alloc, df_rd_confluence_n,
	df_rd_bb_local_compute, df_rd_transfer_function, df_rd_free):
	Removed code to allocate, initialize or free expanded_lr_out.
	(df_rd_bb_local_compute_process_def): Restructured to make more
	understandable.
	(df_rd_confluence_n): Removed code to no apply invalidate_by_call
	sets if the sets are being trimmed.

From-SVN: r131719
parent 115e6e55
2008-01-22 Kenneth Zadeck <zadeck@naturalbridge.com>
PR rtl-optimization/26854
PR rtl-optimization/34400
PR rtl-optimization/34884
* ddg.c (create_ddg_dep_from_intra_loop_link): Use
DF_RD->gen.
* df.h (df_changeable_flags.DF_RD_NO_TRIM): Deleted
(df_rd_bb_info.expanded_lr_out): Deleted
* loop_invariant.c (find_defs): Deleted DF_RD_NO_TRIM flag.
* loop_iv.c (iv_analysis_loop_init): Ditto. * df-problems.c
(df_rd_free_bb_info, df_rd_alloc, df_rd_confluence_n,
df_rd_bb_local_compute, df_rd_transfer_function, df_rd_free):
Removed code to allocate, initialize or free expanded_lr_out.
(df_rd_bb_local_compute_process_def): Restructured to make more
understandable.
(df_rd_confluence_n): Removed code to no apply invalidate_by_call
sets if the sets are being trimmed.
2008-01-22 H.J. Lu <hongjiu.lu@intel.com> 2008-01-22 H.J. Lu <hongjiu.lu@intel.com>
PR bootstrap/32287 PR bootstrap/32287
......
...@@ -184,13 +184,12 @@ create_ddg_dep_from_intra_loop_link (ddg_ptr g, ddg_node_ptr src_node, ...@@ -184,13 +184,12 @@ create_ddg_dep_from_intra_loop_link (ddg_ptr g, ddg_node_ptr src_node,
{ {
int regno = REGNO (SET_DEST (set)); int regno = REGNO (SET_DEST (set));
struct df_ref *first_def; struct df_ref *first_def;
struct df_ref *last_def; struct df_rd_bb_info *bb_info = DF_RD_BB_INFO (g->bb);
first_def = df_bb_regno_first_def_find (g->bb, regno); first_def = df_bb_regno_first_def_find (g->bb, regno);
gcc_assert (first_def); gcc_assert (first_def);
last_def = df_bb_regno_last_def_find (g->bb, regno); if (bitmap_bit_p (bb_info->gen, first_def->id))
if (first_def == last_def)
return; return;
} }
} }
......
...@@ -245,8 +245,6 @@ df_rd_free_bb_info (basic_block bb ATTRIBUTE_UNUSED, ...@@ -245,8 +245,6 @@ df_rd_free_bb_info (basic_block bb ATTRIBUTE_UNUSED,
struct df_rd_bb_info *bb_info = (struct df_rd_bb_info *) vbb_info; struct df_rd_bb_info *bb_info = (struct df_rd_bb_info *) vbb_info;
if (bb_info) if (bb_info)
{ {
if (bb_info->expanded_lr_out)
BITMAP_FREE (bb_info->expanded_lr_out);
BITMAP_FREE (bb_info->kill); BITMAP_FREE (bb_info->kill);
BITMAP_FREE (bb_info->sparse_kill); BITMAP_FREE (bb_info->sparse_kill);
BITMAP_FREE (bb_info->gen); BITMAP_FREE (bb_info->gen);
...@@ -300,8 +298,6 @@ df_rd_alloc (bitmap all_blocks) ...@@ -300,8 +298,6 @@ df_rd_alloc (bitmap all_blocks)
struct df_rd_bb_info *bb_info = df_rd_get_bb_info (bb_index); struct df_rd_bb_info *bb_info = df_rd_get_bb_info (bb_index);
if (bb_info) if (bb_info)
{ {
if (bb_info->expanded_lr_out)
bitmap_clear (bb_info->expanded_lr_out);
bitmap_clear (bb_info->kill); bitmap_clear (bb_info->kill);
bitmap_clear (bb_info->sparse_kill); bitmap_clear (bb_info->sparse_kill);
bitmap_clear (bb_info->gen); bitmap_clear (bb_info->gen);
...@@ -310,10 +306,6 @@ df_rd_alloc (bitmap all_blocks) ...@@ -310,10 +306,6 @@ df_rd_alloc (bitmap all_blocks)
{ {
bb_info = (struct df_rd_bb_info *) pool_alloc (df_rd->block_pool); bb_info = (struct df_rd_bb_info *) pool_alloc (df_rd->block_pool);
df_rd_set_bb_info (bb_index, bb_info); df_rd_set_bb_info (bb_index, bb_info);
if (df->changeable_flags & DF_RD_NO_TRIM)
bb_info->expanded_lr_out = NULL;
else
bb_info->expanded_lr_out = BITMAP_ALLOC (&problem_data->rd_bitmaps);
bb_info->kill = BITMAP_ALLOC (&problem_data->rd_bitmaps); bb_info->kill = BITMAP_ALLOC (&problem_data->rd_bitmaps);
bb_info->sparse_kill = BITMAP_ALLOC (&problem_data->rd_bitmaps); bb_info->sparse_kill = BITMAP_ALLOC (&problem_data->rd_bitmaps);
bb_info->gen = BITMAP_ALLOC (&problem_data->rd_bitmaps); bb_info->gen = BITMAP_ALLOC (&problem_data->rd_bitmaps);
...@@ -328,53 +320,56 @@ df_rd_alloc (bitmap all_blocks) ...@@ -328,53 +320,56 @@ df_rd_alloc (bitmap all_blocks)
/* Process a list of DEFs for df_rd_bb_local_compute. */ /* Process a list of DEFs for df_rd_bb_local_compute. */
static void static void
df_rd_bb_local_compute_process_def (struct df_rd_bb_info *bb_info, df_rd_bb_local_compute_process_def (struct df_rd_bb_info *bb_info,
struct df_ref **def_rec, struct df_ref **def_rec,
enum df_ref_flags top_flag) enum df_ref_flags top_flag)
{ {
for (; *def_rec; def_rec++) while (*def_rec)
{ {
struct df_ref *def = *def_rec; struct df_ref *def = *def_rec;
unsigned int regno = DF_REF_REGNO (def); if (top_flag == (DF_REF_FLAGS (def) & DF_REF_AT_TOP))
/* This makes sure we do the artificial defs in the right order
since they are all in the same list. */
if (top_flag != (DF_REF_FLAGS (def) & DF_REF_AT_TOP))
continue;
/* Skip over the hard regs if we do not care about them. */
if ((df->changeable_flags & DF_NO_HARD_REGS) &&
(regno < FIRST_PSEUDO_REGISTER))
continue;
/* Only the last def(s) for a regno in the block has any
effect. */
if (bitmap_bit_p (seen_in_block, regno))
continue;
/* The first def for regno in insn gets to knock out the
defs from other instructions. */
if ((!bitmap_bit_p (seen_in_insn, regno))
/* If the def is to only part of the reg, it does
not kill the other defs that reach here. */
&& (!(DF_REF_FLAGS (def) &
(DF_REF_PARTIAL | DF_REF_CONDITIONAL | DF_REF_MAY_CLOBBER))))
{ {
unsigned int regno = DF_REF_REGNO (def);
unsigned int begin = DF_DEFS_BEGIN (regno); unsigned int begin = DF_DEFS_BEGIN (regno);
unsigned int n_defs = DF_DEFS_COUNT (regno); unsigned int n_defs = DF_DEFS_COUNT (regno);
if (n_defs > DF_SPARSE_THRESHOLD)
bitmap_set_bit (bb_info->sparse_kill, regno); if ((!(df->changeable_flags & DF_NO_HARD_REGS))
else || (regno >= FIRST_PSEUDO_REGISTER))
bitmap_set_range (bb_info->kill, begin, n_defs); {
bitmap_clear_range(bb_info->gen, begin, n_defs); /* Only the last def(s) for a regno in the block has any
effect. */
if (!bitmap_bit_p (seen_in_block, regno))
{
/* The first def for regno in insn gets to knock out the
defs from other instructions. */
if ((!bitmap_bit_p (seen_in_insn, regno))
/* If the def is to only part of the reg, it does
not kill the other defs that reach here. */
&& (!(DF_REF_FLAGS (def) &
(DF_REF_PARTIAL | DF_REF_CONDITIONAL | DF_REF_MAY_CLOBBER))))
{
if (n_defs > DF_SPARSE_THRESHOLD)
{
bitmap_set_bit (bb_info->sparse_kill, regno);
bitmap_clear_range(bb_info->gen, begin, n_defs);
}
else
{
bitmap_set_range (bb_info->kill, begin, n_defs);
bitmap_clear_range (bb_info->gen, begin, n_defs);
}
}
bitmap_set_bit (seen_in_insn, regno);
/* All defs for regno in the instruction may be put into
the gen set. */
if (!(DF_REF_FLAGS (def)
& (DF_REF_MUST_CLOBBER | DF_REF_MAY_CLOBBER)))
bitmap_set_bit (bb_info->gen, DF_REF_ID (def));
}
}
} }
def_rec++;
bitmap_set_bit (seen_in_insn, regno);
/* All defs for regno in the instruction may be put into
the gen set. */
if (!(DF_REF_FLAGS (def)
& (DF_REF_MUST_CLOBBER | DF_REF_MAY_CLOBBER)))
bitmap_set_bit (bb_info->gen, DF_REF_ID (def));
} }
} }
...@@ -385,28 +380,14 @@ df_rd_bb_local_compute (unsigned int bb_index) ...@@ -385,28 +380,14 @@ df_rd_bb_local_compute (unsigned int bb_index)
{ {
basic_block bb = BASIC_BLOCK (bb_index); basic_block bb = BASIC_BLOCK (bb_index);
struct df_rd_bb_info *bb_info = df_rd_get_bb_info (bb_index); struct df_rd_bb_info *bb_info = df_rd_get_bb_info (bb_index);
struct df_lr_bb_info *lr_bb_info = df_lr_get_bb_info (bb_index);
rtx insn; rtx insn;
bitmap_clear (seen_in_block); bitmap_clear (seen_in_block);
bitmap_clear (seen_in_insn); bitmap_clear (seen_in_insn);
if (!(df->changeable_flags & DF_RD_NO_TRIM))
{
unsigned int regno;
bitmap_iterator bi;
int first_reg = (df->changeable_flags & DF_NO_HARD_REGS) ? FIRST_PSEUDO_REGISTER : 0;
EXECUTE_IF_SET_IN_BITMAP (lr_bb_info->out, first_reg, regno, bi)
{
unsigned int begin = DF_DEFS_BEGIN (regno);
unsigned int n_defs = DF_DEFS_COUNT (regno);
bitmap_set_range (bb_info->expanded_lr_out, begin, n_defs);
}
}
/* Artificials are only hard regs. */ /* Artificials are only hard regs. */
if (!(df->changeable_flags & DF_NO_HARD_REGS)) if (!(df->changeable_flags & DF_NO_HARD_REGS))
df_rd_bb_local_compute_process_def (bb_info, df_rd_bb_local_compute_process_def (bb_info,
df_get_artificial_defs (bb_index), df_get_artificial_defs (bb_index),
0); 0);
...@@ -504,10 +485,7 @@ df_rd_confluence_n (edge e) ...@@ -504,10 +485,7 @@ df_rd_confluence_n (edge e)
if (e->flags & EDGE_FAKE) if (e->flags & EDGE_FAKE)
return; return;
/* If we are trimming the solution, the invalidated_by_call code in if (e->flags & EDGE_EH)
the lr problem makes this unnecessary. However, if we do not
trim, we must take this into account. */
if ((df->changeable_flags & DF_RD_NO_TRIM) && e->flags & EDGE_EH)
{ {
struct df_rd_problem_data *problem_data struct df_rd_problem_data *problem_data
= (struct df_rd_problem_data *) df_rd->problem_data; = (struct df_rd_problem_data *) df_rd->problem_data;
...@@ -515,7 +493,7 @@ df_rd_confluence_n (edge e) ...@@ -515,7 +493,7 @@ df_rd_confluence_n (edge e)
bitmap dense_invalidated = problem_data->dense_invalidated_by_call; bitmap dense_invalidated = problem_data->dense_invalidated_by_call;
bitmap_iterator bi; bitmap_iterator bi;
unsigned int regno; unsigned int regno;
bitmap tmp = BITMAP_ALLOC (&problem_data->rd_bitmaps); bitmap tmp = BITMAP_ALLOC (&df_bitmap_obstack);
bitmap_copy (tmp, op2); bitmap_copy (tmp, op2);
bitmap_and_compl_into (tmp, dense_invalidated); bitmap_and_compl_into (tmp, dense_invalidated);
...@@ -547,13 +525,13 @@ df_rd_transfer_function (int bb_index) ...@@ -547,13 +525,13 @@ df_rd_transfer_function (int bb_index)
bitmap gen = bb_info->gen; bitmap gen = bb_info->gen;
bitmap kill = bb_info->kill; bitmap kill = bb_info->kill;
bitmap sparse_kill = bb_info->sparse_kill; bitmap sparse_kill = bb_info->sparse_kill;
bool changed = false;
if ((df->changeable_flags & DF_RD_NO_TRIM) && bitmap_empty_p (sparse_kill)) if (bitmap_empty_p (sparse_kill))
changed = bitmap_ior_and_compl (out, gen, in, kill); return bitmap_ior_and_compl (out, gen, in, kill);
else else
{ {
struct df_rd_problem_data *problem_data; struct df_rd_problem_data *problem_data;
bool changed = false;
bitmap tmp; bitmap tmp;
/* Note that TMP is _not_ a temporary bitmap if we end up replacing /* Note that TMP is _not_ a temporary bitmap if we end up replacing
...@@ -570,8 +548,6 @@ df_rd_transfer_function (int bb_index) ...@@ -570,8 +548,6 @@ df_rd_transfer_function (int bb_index)
} }
bitmap_and_compl_into (tmp, kill); bitmap_and_compl_into (tmp, kill);
bitmap_ior_into (tmp, gen); bitmap_ior_into (tmp, gen);
if (!(df->changeable_flags & DF_RD_NO_TRIM))
bitmap_and_into (tmp, bb_info->expanded_lr_out);
changed = !bitmap_equal_p (tmp, out); changed = !bitmap_equal_p (tmp, out);
if (changed) if (changed)
{ {
...@@ -579,10 +555,9 @@ df_rd_transfer_function (int bb_index) ...@@ -579,10 +555,9 @@ df_rd_transfer_function (int bb_index)
bb_info->out = tmp; bb_info->out = tmp;
} }
else else
BITMAP_FREE (tmp); BITMAP_FREE (tmp);
return changed;
} }
return changed;
} }
...@@ -602,8 +577,6 @@ df_rd_free (void) ...@@ -602,8 +577,6 @@ df_rd_free (void)
struct df_rd_bb_info *bb_info = df_rd_get_bb_info (i); struct df_rd_bb_info *bb_info = df_rd_get_bb_info (i);
if (bb_info) if (bb_info)
{ {
if (bb_info->expanded_lr_out)
BITMAP_FREE (bb_info->expanded_lr_out);
BITMAP_FREE (bb_info->kill); BITMAP_FREE (bb_info->kill);
BITMAP_FREE (bb_info->sparse_kill); BITMAP_FREE (bb_info->sparse_kill);
BITMAP_FREE (bb_info->gen); BITMAP_FREE (bb_info->gen);
......
...@@ -405,27 +405,20 @@ enum df_changeable_flags ...@@ -405,27 +405,20 @@ enum df_changeable_flags
DF_LR_RUN_DCE = 1 << 0, /* Run DCE. */ DF_LR_RUN_DCE = 1 << 0, /* Run DCE. */
DF_NO_HARD_REGS = 1 << 1, /* Skip hard registers in RD and CHAIN Building. */ DF_NO_HARD_REGS = 1 << 1, /* Skip hard registers in RD and CHAIN Building. */
/* Do not trim the solution using the LR result. This can make the DF_EQ_NOTES = 1 << 2, /* Build chains with uses present in EQUIV/EQUAL notes. */
solution take much longer and take more memory. This is DF_NO_REGS_EVER_LIVE = 1 << 3, /* Do not compute the regs_ever_live. */
necessary for the loop optimizations, but has a very small time
and space penalty because the loop optimizations process only a
single loop at a time. Any pass that looks at the entire
function should not set this flag. */
DF_RD_NO_TRIM = 1 << 2,
DF_EQ_NOTES = 1 << 3, /* Build chains with uses present in EQUIV/EQUAL notes. */
DF_NO_REGS_EVER_LIVE = 1 << 4, /* Do not compute the regs_ever_live. */
/* Cause df_insn_rescan df_notes_rescan and df_insn_delete, to /* Cause df_insn_rescan df_notes_rescan and df_insn_delete, to
return immediately. This is used by passes that know how to update return immediately. This is used by passes that know how to update
the scanning them selves. */ the scanning them selves. */
DF_NO_INSN_RESCAN = 1 << 5, DF_NO_INSN_RESCAN = 1 << 4,
/* Cause df_insn_rescan df_notes_rescan and df_insn_delete, to /* Cause df_insn_rescan df_notes_rescan and df_insn_delete, to
return after marking the insn for later processing. This allows all return after marking the insn for later processing. This allows all
rescans to be batched. */ rescans to be batched. */
DF_DEFER_INSN_RESCAN = 1 << 6, DF_DEFER_INSN_RESCAN = 1 << 5,
DF_VERIFY_SCHEDULED = 1 << 7 DF_VERIFY_SCHEDULED = 1 << 6
}; };
/* Two of these structures are inline in df, one for the uses and one /* Two of these structures are inline in df, one for the uses and one
...@@ -719,37 +712,9 @@ struct df_rd_bb_info ...@@ -719,37 +712,9 @@ struct df_rd_bb_info
/* Local sets to describe the basic blocks. */ /* Local sets to describe the basic blocks. */
bitmap kill; bitmap kill;
bitmap sparse_kill; bitmap sparse_kill;
bitmap gen; /* The set of defs generated in this block. */
/* Expanded version of the DF_LT->out bitmap to match the positions /* The results of the dataflow problem. */
of gen, in and out here. Only allocated if DF_RD_NO_TRIM is
false. */
bitmap expanded_lr_out;
/* The set of defs generated in this block. This is not set unless
the def reaches the end of the block. */
bitmap gen;
/* The results of the dataflow problem.
If DF_RD_NO_TRIM is not set, these sets are SOMEWHAT trimmed by
the output of the DF_LR problem. The out set is precisely
trimmed during propagation which means that the result is also
trimmed when the propagation terminates. The in set is not
explicitly trimmed, because this is expensive (adding about 5% to
the cost of a bootstrap). However since the out sets are trimmed
and the in sets are built from the out of the pred, the in set is
MOSTLY trimmed.
The counter case happens at a branch where the variable V is in
DF_LR->in the true branch but not the false branch. If V is
defined before the branch, RD will propagate that into the
DF_RD_in sets of both branches. When the block is processed, the
DF_RD->out set will have V trimmed out of it but it will still be
left in DF_RD->in.
If this not a problem for the current optimizers since they were
designed before any trimming was available. This can be fixed by
checking the DF_LR->in set directly. */
bitmap in; /* At the top of the block. */ bitmap in; /* At the top of the block. */
bitmap out; /* At the bottom of the block. */ bitmap out; /* At the bottom of the block. */
}; };
......
...@@ -639,7 +639,6 @@ find_defs (struct loop *loop, basic_block *body) ...@@ -639,7 +639,6 @@ find_defs (struct loop *loop, basic_block *body)
df_remove_problem (df_chain); df_remove_problem (df_chain);
df_process_deferred_rescans (); df_process_deferred_rescans ();
df_chain_add_problem (DF_UD_CHAIN); df_chain_add_problem (DF_UD_CHAIN);
df_set_flags (DF_RD_NO_TRIM);
df_set_blocks (blocks); df_set_blocks (blocks);
df_analyze (); df_analyze ();
......
...@@ -278,7 +278,6 @@ iv_analysis_loop_init (struct loop *loop) ...@@ -278,7 +278,6 @@ iv_analysis_loop_init (struct loop *loop)
df_remove_problem (df_chain); df_remove_problem (df_chain);
df_process_deferred_rescans (); df_process_deferred_rescans ();
df_chain_add_problem (DF_UD_CHAIN); df_chain_add_problem (DF_UD_CHAIN);
df_set_flags (DF_RD_NO_TRIM);
df_set_blocks (blocks); df_set_blocks (blocks);
df_analyze (); df_analyze ();
if (dump_file) if (dump_file)
......
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