re PR tree-optimization/16447 (out of ssa generates bloated code)

2004-11-01  Andrew MacLeod  <amacleod@redhat.com>

	PR tree-optimization/16447
	* tree-cfg.c (bsi_commit_one_edge_insert): Rename from
	bsi_commit_edge_inserts_1, and make funtion external.  Return new block.
	(bsi_commit_edge_inserts): Use renamed bsi_commit_one_edge_insert.
	* tree-optimize.c (pass_cleanup_cfg_post_optimizing): Enable listing.
	* tree-flow.h (bsi_commit_one_edge_insert): Extern decl.
	* tree-outof-ssa.c (rewrite_trees): Don't commit edges here.
	(same_stmt_list_p): New.  Return TRUE if edge is to be forwarded.
	(identical_copies_p): New.  Return true is two copies are the same.
	(identical_stmt_lists_p): New.  Return true if stmt lists are the same.
	(analyze_edges_for_bb): New.  Determine how best to insert edge stmts
	for a basic block.
	(perform_edge_inserts): New.  Determine what to do with all stmts that
	have been inserted on edges.
	(remove_ssa_form):  Analyze and commit edges from here.

From-SVN: r89970
This commit is contained in:
Andrew MacLeod 2004-11-02 00:23:04 +00:00 committed by Andrew Macleod
parent 8bf639fa5e
commit edfaf67510
5 changed files with 357 additions and 11 deletions

View File

@ -1,3 +1,21 @@
2004-11-01 Andrew MacLeod <amacleod@redhat.com>
PR tree-optimization/16447
* tree-cfg.c (bsi_commit_one_edge_insert): Rename from
bsi_commit_edge_inserts_1, and make funtion external. Return new block.
(bsi_commit_edge_inserts): Use renamed bsi_commit_one_edge_insert.
* tree-optimize.c (pass_cleanup_cfg_post_optimizing): Enable listing.
* tree-flow.h (bsi_commit_one_edge_insert): Extern decl.
* tree-outof-ssa.c (rewrite_trees): Don't commit edges here.
(same_stmt_list_p): New. Return TRUE if edge is to be forwarded.
(identical_copies_p): New. Return true is two copies are the same.
(identical_stmt_lists_p): New. Return true if stmt lists are the same.
(analyze_edges_for_bb): New. Determine how best to insert edge stmts
for a basic block.
(perform_edge_inserts): New. Determine what to do with all stmts that
have been inserted on edges.
(remove_ssa_form): Analyze and commit edges from here.
2004-11-01 Andrew Pinski <pinskia@physics.uc.edu>
PR bootstrap/18232

View File

@ -93,7 +93,6 @@ static int tree_verify_flow_info (void);
static void tree_make_forwarder_block (edge);
static bool thread_jumps (void);
static bool tree_forwarder_block_p (basic_block);
static void bsi_commit_edge_inserts_1 (edge e);
static void tree_cfg2vcg (FILE *);
/* Flowgraph optimization and cleanup. */
@ -2871,22 +2870,25 @@ bsi_commit_edge_inserts (int *new_blocks)
blocks = n_basic_blocks;
bsi_commit_edge_inserts_1 (EDGE_SUCC (ENTRY_BLOCK_PTR, 0));
bsi_commit_one_edge_insert (EDGE_SUCC (ENTRY_BLOCK_PTR, 0), NULL);
FOR_EACH_BB (bb)
FOR_EACH_EDGE (e, ei, bb->succs)
bsi_commit_edge_inserts_1 (e);
bsi_commit_one_edge_insert (e, NULL);
if (new_blocks)
*new_blocks = n_basic_blocks - blocks;
}
/* Commit insertions pending at edge E. */
/* Commit insertions pending at edge E. If a new block is created, set NEW_BB
to this block, otherwise set it to NULL. */
static void
bsi_commit_edge_inserts_1 (edge e)
void
bsi_commit_one_edge_insert (edge e, basic_block *new_bb)
{
if (new_bb)
*new_bb = NULL;
if (PENDING_STMT (e))
{
block_stmt_iterator bsi;
@ -2894,7 +2896,7 @@ bsi_commit_edge_inserts_1 (edge e)
PENDING_STMT (e) = NULL_TREE;
if (tree_find_edge_insert_loc (e, &bsi, NULL))
if (tree_find_edge_insert_loc (e, &bsi, new_bb))
bsi_insert_after (&bsi, stmt, BSI_NEW_STMT);
else
bsi_insert_before (&bsi, stmt, BSI_NEW_STMT);

View File

@ -479,6 +479,7 @@ extern basic_block label_to_block (tree);
extern void tree_optimize_tail_calls (bool, enum tree_dump_index);
extern void bsi_insert_on_edge (edge, tree);
extern basic_block bsi_insert_on_edge_immediate (edge, tree);
extern void bsi_commit_one_edge_insert (edge e, basic_block *);
extern void bsi_commit_edge_inserts (int *);
extern void notice_special_calls (tree);
extern void clear_special_calls (void);

View File

@ -118,7 +118,7 @@ execute_cleanup_cfg_post_optimizing (void)
static struct tree_opt_pass pass_cleanup_cfg_post_optimizing =
{
NULL, /* name */
"final_cleanup", /* name */
NULL, /* gate */
execute_cleanup_cfg_post_optimizing, /* execute */
NULL, /* sub */
@ -129,7 +129,7 @@ static struct tree_opt_pass pass_cleanup_cfg_post_optimizing =
0, /* properties_provided */
0, /* properties_destroyed */
0, /* todo_flags_start */
0, /* todo_flags_finish */
TODO_dump_func, /* todo_flags_finish */
0 /* letter */
};

View File

@ -1933,9 +1933,331 @@ rewrite_trees (var_map map, tree *values)
}
delete_elim_graph (g);
}
/* If any copies were inserted on edges, actually insert them now. */
bsi_commit_edge_inserts (NULL);
/* These are the local work structures used to determine the best place to
insert the copies that were placed on edges by the SSA->normal pass.. */
static varray_type edge_leader = NULL;
static varray_type GTY(()) stmt_list = NULL;
static bitmap leader_has_match = NULL;
static edge leader_match = NULL;
/* Pass this function to make_forwarder_block so that all the edges with
matching PENDING_STMT lists to 'curr_stmt_list' get redirected. */
static bool
same_stmt_list_p (edge e)
{
return (e->aux == (PTR) leader_match) ? true : false;
}
/* Return TRUE if S1 and S2 are equivalent copies. */
static inline bool
identical_copies_p (tree s1, tree s2)
{
#ifdef ENABLE_CHECKING
gcc_assert (TREE_CODE (s1) == MODIFY_EXPR);
gcc_assert (TREE_CODE (s2) == MODIFY_EXPR);
gcc_assert (DECL_P (TREE_OPERAND (s1, 0)));
gcc_assert (DECL_P (TREE_OPERAND (s2, 0)));
#endif
if (TREE_OPERAND (s1, 0) != TREE_OPERAND (s2, 0))
return false;
s1 = TREE_OPERAND (s1, 1);
s2 = TREE_OPERAND (s2, 1);
if (s1 != s2)
return false;
return true;
}
/* Compare the PENDING_STMT list for two edges, and return true if the lists
contain the same sequence of copies. */
static inline bool
identical_stmt_lists_p (edge e1, edge e2)
{
tree t1 = PENDING_STMT (e1);
tree t2 = PENDING_STMT (e2);
tree_stmt_iterator tsi1, tsi2;
gcc_assert (TREE_CODE (t1) == STATEMENT_LIST);
gcc_assert (TREE_CODE (t2) == STATEMENT_LIST);
for (tsi1 = tsi_start (t1), tsi2 = tsi_start (t2);
!tsi_end_p (tsi1) && !tsi_end_p (tsi2);
tsi_next (&tsi1), tsi_next (&tsi2))
{
if (!identical_copies_p (tsi_stmt (tsi1), tsi_stmt (tsi2)))
break;
}
if (!tsi_end_p (tsi1) || ! tsi_end_p (tsi2))
return false;
return true;
}
/* Look at all the incoming edges to block BB, and decide where the best place
to insert the stmts on each edge are, and perform those insertions. Output
any debug information to DEBUG_FILE. Return true if anything other than a
standard edge insertion is done. */
static bool
analyze_edges_for_bb (basic_block bb, FILE *debug_file)
{
edge e;
edge_iterator ei;
int count;
unsigned int x;
bool have_opportunity;
block_stmt_iterator bsi;
tree stmt;
edge single_edge = NULL;
bool is_label;
count = 0;
/* Find out how many edges there are with interesting pending stmts on them.
Commit the stmts on edges we are not interested in. */
FOR_EACH_EDGE (e, ei, bb->preds)
{
if (PENDING_STMT (e))
{
gcc_assert (!(e->flags & EDGE_ABNORMAL));
if (e->flags & EDGE_FALLTHRU)
{
bsi = bsi_start (e->src);
if (!bsi_end_p (bsi))
{
stmt = bsi_stmt (bsi);
bsi_next (&bsi);
gcc_assert (stmt != NULL_TREE);
is_label = (TREE_CODE (stmt) == LABEL_EXPR);
/* Punt if it has non-label stmts, or isn't local. */
if (!is_label || DECL_NONLOCAL (TREE_OPERAND (stmt, 0))
|| !bsi_end_p (bsi))
{
bsi_commit_one_edge_insert (e, NULL);
continue;
}
}
}
single_edge = e;
count++;
}
}
/* If there aren't at least 2 edges, no sharing will happen. */
if (count < 2)
{
if (single_edge)
bsi_commit_one_edge_insert (single_edge, NULL);
return false;
}
/* Ensure that we have empty worklists. */
if (edge_leader == NULL)
{
VARRAY_EDGE_INIT (edge_leader, 25, "edge_leader");
VARRAY_TREE_INIT (stmt_list, 25, "stmt_list");
leader_has_match = BITMAP_XMALLOC ();
}
else
{
#ifdef ENABLE_CHECKING
gcc_assert (VARRAY_ACTIVE_SIZE (edge_leader) == 0);
gcc_assert (VARRAY_ACTIVE_SIZE (stmt_list) == 0);
gcc_assert (bitmap_first_set_bit (leader_has_match) == -1);
#endif
}
/* Find the "leader" block for each set of unique stmt lists. Preference is
given to FALLTHRU blocks since they would need a GOTO to arrive at another
block. The leader edge destination is the block which all the other edges
with the same stmt list will be redirected to. */
have_opportunity = false;
FOR_EACH_EDGE (e, ei, bb->preds)
{
if (PENDING_STMT (e))
{
bool found = false;
/* Look for the same stmt list in edge leaders list. */
for (x = 0; x < VARRAY_ACTIVE_SIZE (edge_leader); x++)
{
edge leader = VARRAY_EDGE (edge_leader, x);
if (identical_stmt_lists_p (leader, e))
{
/* Give this edge the same stmt list pointer. */
PENDING_STMT (e) = NULL;
e->aux = leader;
bitmap_set_bit (leader_has_match, x);
have_opportunity = found = true;
break;
}
}
/* If no similar stmt list, add this edge to the leader list. */
if (!found)
{
VARRAY_PUSH_EDGE (edge_leader, e);
VARRAY_PUSH_TREE (stmt_list, PENDING_STMT (e));
}
}
}
/* If there are no similar lists, just issue the stmts. */
if (!have_opportunity)
{
for (x = 0; x < VARRAY_ACTIVE_SIZE (edge_leader); x++)
bsi_commit_one_edge_insert (VARRAY_EDGE (edge_leader, x), NULL);
VARRAY_POP_ALL (edge_leader);
VARRAY_POP_ALL (stmt_list);
bitmap_clear (leader_has_match);
return false;
}
if (debug_file)
fprintf (debug_file, "\nOpportunities in BB %d for stmt/block reduction:\n",
bb->index);
/* For each common list, create a forwarding block and issue the stmt's
in that block. */
for (x = 0 ; x < VARRAY_ACTIVE_SIZE (edge_leader); x++)
if (bitmap_bit_p (leader_has_match, x))
{
edge new_edge, leader_edge;
block_stmt_iterator bsi;
tree curr_stmt_list;
leader_match = leader_edge = VARRAY_EDGE (edge_leader, x);
/* The tree_* cfg manipulation routines use the PENDING_EDGE field
for various PHI manipulations, so it gets cleared whhen calls are
made to make_forwarder_block(). So make sure the edge is clear,
and use the saved stmt list. */
PENDING_STMT (leader_edge) = NULL;
leader_edge->aux = leader_edge;
curr_stmt_list = VARRAY_TREE (stmt_list, x);
new_edge = make_forwarder_block (leader_edge->dest, same_stmt_list_p,
NULL);
bb = new_edge->dest;
if (debug_file)
{
fprintf (debug_file, "Splitting BB %d for Common stmt list. ",
leader_edge->dest->index);
fprintf (debug_file, "Original block is now BB%d.\n", bb->index);
print_generic_stmt (debug_file, curr_stmt_list, TDF_VOPS);
}
FOR_EACH_EDGE (e, ei, new_edge->src->preds)
{
e->aux = NULL;
if (debug_file)
fprintf (debug_file, " Edge (%d->%d) lands here.\n",
e->src->index, e->dest->index);
}
bsi = bsi_last (leader_edge->dest);
bsi_insert_after (&bsi, curr_stmt_list, BSI_NEW_STMT);
leader_match = NULL;
/* We should never get a new block now. */
}
else
{
e = VARRAY_EDGE (edge_leader, x);
PENDING_STMT (e) = VARRAY_TREE (stmt_list, x);
bsi_commit_one_edge_insert (e, NULL);
}
/* Clear the working data structures. */
VARRAY_POP_ALL (edge_leader);
VARRAY_POP_ALL (stmt_list);
bitmap_clear (leader_has_match);
return true;
}
/* This function will analyze the insertions which were performed on edges,
and decide whether they should be left on that edge, or whether it is more
efficient to emit some subset of them in a single block. All stmts are
inserted somewhere, and if non-NULL, debug information is printed via
DUMP_FILE. */
static void
perform_edge_inserts (FILE *dump_file)
{
basic_block bb;
bool changed = false;
if (dump_file)
fprintf(dump_file, "Analyzing Edge Insertions.\n");
FOR_EACH_BB (bb)
changed |= analyze_edges_for_bb (bb, dump_file);
changed |= analyze_edges_for_bb (EXIT_BLOCK_PTR, dump_file);
/* Clear out any tables which were created. */
edge_leader = NULL;
if (leader_has_match != NULL)
{
free (leader_has_match);
leader_has_match = NULL;
}
if (changed)
{
free_dominance_info (CDI_DOMINATORS);
free_dominance_info (CDI_POST_DOMINATORS);
}
#ifdef ENABLE_CHECKING
{
edge_iterator ei;
edge e;
FOR_EACH_BB (bb)
{
FOR_EACH_EDGE (e, ei, bb->preds)
{
if (PENDING_STMT (e))
error (" Pending stmts not issued on PRED edge (%d, %d)\n",
e->src->index, e->dest->index);
}
FOR_EACH_EDGE (e, ei, bb->succs)
{
if (PENDING_STMT (e))
error (" Pending stmts not issued on SUCC edge (%d, %d)\n",
e->src->index, e->dest->index);
}
}
FOR_EACH_EDGE (e, ei, ENTRY_BLOCK_PTR->succs)
{
if (PENDING_STMT (e))
error (" Pending stmts not issued on ENTRY edge (%d, %d)\n",
e->src->index, e->dest->index);
}
FOR_EACH_EDGE (e, ei, EXIT_BLOCK_PTR->preds)
{
if (PENDING_STMT (e))
error (" Pending stmts not issued on EXIT edge (%d, %d)\n",
e->src->index, e->dest->index);
}
}
#endif
}
@ -2022,6 +2344,9 @@ remove_ssa_form (FILE *dump, var_map map, int flags)
}
}
/* If any copies were inserted on edges, analyze and insert them now. */
perform_edge_inserts (dump_file);
dump_file = save;
}