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>
PR bootstrap/32287
......
......@@ -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));
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);
gcc_assert (first_def);
last_def = df_bb_regno_last_def_find (g->bb, regno);
if (first_def == last_def)
if (bitmap_bit_p (bb_info->gen, first_def->id))
return;
}
}
......
......@@ -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;
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->sparse_kill);
BITMAP_FREE (bb_info->gen);
......@@ -300,8 +298,6 @@ df_rd_alloc (bitmap all_blocks)
struct df_rd_bb_info *bb_info = df_rd_get_bb_info (bb_index);
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->sparse_kill);
bitmap_clear (bb_info->gen);
......@@ -310,10 +306,6 @@ df_rd_alloc (bitmap all_blocks)
{
bb_info = (struct df_rd_bb_info *) pool_alloc (df_rd->block_pool);
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->sparse_kill = 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)
/* Process a list of DEFs for df_rd_bb_local_compute. */
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,
enum df_ref_flags top_flag)
{
for (; *def_rec; def_rec++)
while (*def_rec)
{
struct df_ref *def = *def_rec;
unsigned int regno = DF_REF_REGNO (def);
/* 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))))
if (top_flag == (DF_REF_FLAGS (def) & DF_REF_AT_TOP))
{
unsigned int regno = DF_REF_REGNO (def);
unsigned int begin = DF_DEFS_BEGIN (regno);
unsigned int n_defs = DF_DEFS_COUNT (regno);
if (n_defs > DF_SPARSE_THRESHOLD)
bitmap_set_bit (bb_info->sparse_kill, regno);
else
bitmap_set_range (bb_info->kill, begin, n_defs);
bitmap_clear_range(bb_info->gen, begin, n_defs);
if ((!(df->changeable_flags & DF_NO_HARD_REGS))
|| (regno >= FIRST_PSEUDO_REGISTER))
{
/* 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));
}
}
}
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++;
}
}
......@@ -385,28 +380,14 @@ df_rd_bb_local_compute (unsigned int 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_lr_bb_info *lr_bb_info = df_lr_get_bb_info (bb_index);
rtx insn;
bitmap_clear (seen_in_block);
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. */
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),
0);
......@@ -504,10 +485,7 @@ df_rd_confluence_n (edge e)
if (e->flags & EDGE_FAKE)
return;
/* If we are trimming the solution, the invalidated_by_call code in
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)
if (e->flags & EDGE_EH)
{
struct df_rd_problem_data *problem_data
= (struct df_rd_problem_data *) df_rd->problem_data;
......@@ -515,7 +493,7 @@ df_rd_confluence_n (edge e)
bitmap dense_invalidated = problem_data->dense_invalidated_by_call;
bitmap_iterator bi;
unsigned int regno;
bitmap tmp = BITMAP_ALLOC (&problem_data->rd_bitmaps);
bitmap tmp = BITMAP_ALLOC (&df_bitmap_obstack);
bitmap_copy (tmp, op2);
bitmap_and_compl_into (tmp, dense_invalidated);
......@@ -547,13 +525,13 @@ df_rd_transfer_function (int bb_index)
bitmap gen = bb_info->gen;
bitmap kill = bb_info->kill;
bitmap sparse_kill = bb_info->sparse_kill;
bool changed = false;
if ((df->changeable_flags & DF_RD_NO_TRIM) && bitmap_empty_p (sparse_kill))
changed = bitmap_ior_and_compl (out, gen, in, kill);
if (bitmap_empty_p (sparse_kill))
return bitmap_ior_and_compl (out, gen, in, kill);
else
{
struct df_rd_problem_data *problem_data;
bool changed = false;
bitmap tmp;
/* Note that TMP is _not_ a temporary bitmap if we end up replacing
......@@ -570,8 +548,6 @@ df_rd_transfer_function (int bb_index)
}
bitmap_and_compl_into (tmp, kill);
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);
if (changed)
{
......@@ -579,10 +555,9 @@ df_rd_transfer_function (int bb_index)
bb_info->out = tmp;
}
else
BITMAP_FREE (tmp);
BITMAP_FREE (tmp);
return changed;
}
return changed;
}
......@@ -602,8 +577,6 @@ df_rd_free (void)
struct df_rd_bb_info *bb_info = df_rd_get_bb_info (i);
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->sparse_kill);
BITMAP_FREE (bb_info->gen);
......
......@@ -405,27 +405,20 @@ enum df_changeable_flags
DF_LR_RUN_DCE = 1 << 0, /* Run DCE. */
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
solution take much longer and take more memory. This is
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. */
DF_EQ_NOTES = 1 << 2, /* Build chains with uses present in EQUIV/EQUAL notes. */
DF_NO_REGS_EVER_LIVE = 1 << 3, /* Do not compute the regs_ever_live. */
/* Cause df_insn_rescan df_notes_rescan and df_insn_delete, to
return immediately. This is used by passes that know how to update
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
return after marking the insn for later processing. This allows all
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
......@@ -719,37 +712,9 @@ struct df_rd_bb_info
/* Local sets to describe the basic blocks. */
bitmap 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
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. */
/* The results of the dataflow problem. */
bitmap in; /* At the top of the block. */
bitmap out; /* At the bottom of the block. */
};
......
......@@ -639,7 +639,6 @@ find_defs (struct loop *loop, basic_block *body)
df_remove_problem (df_chain);
df_process_deferred_rescans ();
df_chain_add_problem (DF_UD_CHAIN);
df_set_flags (DF_RD_NO_TRIM);
df_set_blocks (blocks);
df_analyze ();
......
......@@ -278,7 +278,6 @@ iv_analysis_loop_init (struct loop *loop)
df_remove_problem (df_chain);
df_process_deferred_rescans ();
df_chain_add_problem (DF_UD_CHAIN);
df_set_flags (DF_RD_NO_TRIM);
df_set_blocks (blocks);
df_analyze ();
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