-
- /* Replace PHI nodes with any required copies. */
- g = new_elim_graph (map->num_partitions);
- g->map = map;
- FOR_EACH_BB (bb)
- {
- for (si = bsi_start (bb); !bsi_end_p (si); )
- {
- tree stmt = bsi_stmt (si);
- use_operand_p use_p, copy_use_p;
- def_operand_p def_p;
- bool remove = false, is_copy = false;
- int num_uses = 0;
- stmt_ann_t ann;
- ssa_op_iter iter;
-
- ann = stmt_ann (stmt);
- changed = false;
-
- if (TREE_CODE (stmt) == GIMPLE_MODIFY_STMT
- && (TREE_CODE (GIMPLE_STMT_OPERAND (stmt, 1)) == SSA_NAME))
- is_copy = true;
-
- copy_use_p = NULL_USE_OPERAND_P;
- FOR_EACH_SSA_USE_OPERAND (use_p, stmt, iter, SSA_OP_USE)
- {
- if (replace_use_variable (map, use_p, values))
- changed = true;
- copy_use_p = use_p;
- num_uses++;
- }
-
- if (num_uses != 1)
- is_copy = false;
-
- def_p = SINGLE_SSA_DEF_OPERAND (stmt, SSA_OP_DEF);
-
- if (def_p != NULL)
- {
- /* Mark this stmt for removal if it is the list of replaceable
- expressions. */
- if (values && values[SSA_NAME_VERSION (DEF_FROM_PTR (def_p))])
- remove = true;
- else
- {
- if (replace_def_variable (map, def_p, NULL))
- changed = true;
- /* If both SSA_NAMEs coalesce to the same variable,
- mark the now redundant copy for removal. */
- if (is_copy)
- {
- gcc_assert (copy_use_p != NULL_USE_OPERAND_P);
- if (DEF_FROM_PTR (def_p) == USE_FROM_PTR (copy_use_p))
- remove = true;
- }
- }
- }
- else
- FOR_EACH_SSA_DEF_OPERAND (def_p, stmt, iter, SSA_OP_DEF)
- if (replace_def_variable (map, def_p, NULL))
- changed = true;
-
- /* Remove any stmts marked for removal. */
- if (remove)
- bsi_remove (&si, true);
- else
- bsi_next (&si);
- }
-
- phi = phi_nodes (bb);
- if (phi)
- {
- edge_iterator ei;
- FOR_EACH_EDGE (e, ei, bb->preds)
- eliminate_phi (e, g);
- }
- }
-
- delete_elim_graph (g);
-}
-
-/* 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 VEC(edge,heap) *edge_leader;
-static VEC(tree,heap) *stmt_list;
-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. E is the
- edge to test for a match. */
-
-static inline 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 (const_tree s1, const_tree s2)
-{
-#ifdef ENABLE_CHECKING
- gcc_assert (TREE_CODE (s1) == GIMPLE_MODIFY_STMT);
- gcc_assert (TREE_CODE (s2) == GIMPLE_MODIFY_STMT);
- gcc_assert (DECL_P (GIMPLE_STMT_OPERAND (s1, 0)));
- gcc_assert (DECL_P (GIMPLE_STMT_OPERAND (s2, 0)));
-#endif
-
- if (GIMPLE_STMT_OPERAND (s1, 0) != GIMPLE_STMT_OPERAND (s2, 0))
- return false;
-
- s1 = GIMPLE_STMT_OPERAND (s1, 1);
- s2 = GIMPLE_STMT_OPERAND (s2, 1);
-
- if (s1 != s2)
- return false;
-
- return true;
-}
-
-
-/* Compare the PENDING_STMT list for edges E1 and E2. Return true if the lists
- contain the same sequence of copies. */
-
-static inline bool
-identical_stmt_lists_p (const_edge e1, const_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;
-}
-
-
-/* Allocate data structures used in analyze_edges_for_bb. */
-
-static void
-init_analyze_edges_for_bb (void)
-{
- edge_leader = VEC_alloc (edge, heap, 25);
- stmt_list = VEC_alloc (tree, heap, 25);
- leader_has_match = BITMAP_ALLOC (NULL);
-}
-
-
-/* Free data structures used in analyze_edges_for_bb. */
-
-static void
-fini_analyze_edges_for_bb (void)
-{
- VEC_free (edge, heap, edge_leader);
- VEC_free (tree, heap, stmt_list);
- BITMAP_FREE (leader_has_match);
-}
-
-
-/* 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. */
-
-static void
-analyze_edges_for_bb (basic_block bb)
-{
- 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;
- edge leader;
-
- count = 0;
-
- /* Blocks which contain at least one abnormal edge cannot use
- make_forwarder_block. Look for these blocks, and commit any PENDING_STMTs
- found on edges in these block. */
- have_opportunity = true;
- FOR_EACH_EDGE (e, ei, bb->preds)
- if (e->flags & EDGE_ABNORMAL)
- {
- have_opportunity = false;
- break;
- }
-
- if (!have_opportunity)
- {
- FOR_EACH_EDGE (e, ei, bb->preds)
- if (PENDING_STMT (e))
- bsi_commit_one_edge_insert (e, NULL);
- return;
- }
-
- /* 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;
- }
-
- /* Ensure that we have empty worklists. */
-#ifdef ENABLE_CHECKING
- gcc_assert (VEC_length (edge, edge_leader) == 0);
- gcc_assert (VEC_length (tree, stmt_list) == 0);
- gcc_assert (bitmap_empty_p (leader_has_match));
-#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; VEC_iterate (edge, edge_leader, x, 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)
- {
- VEC_safe_push (edge, heap, edge_leader, e);
- VEC_safe_push (tree, heap, stmt_list, PENDING_STMT (e));
- }
- }
- }
-
- /* If there are no similar lists, just issue the stmts. */
- if (!have_opportunity)
- {
- for (x = 0; VEC_iterate (edge, edge_leader, x, leader); x++)
- bsi_commit_one_edge_insert (leader, NULL);
- VEC_truncate (edge, edge_leader, 0);
- VEC_truncate (tree, stmt_list, 0);
- bitmap_clear (leader_has_match);
- return;
- }
-
- if (dump_file)
- fprintf (dump_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; VEC_iterate (edge, edge_leader, x, leader); x++)
- if (bitmap_bit_p (leader_has_match, x))
- {
- edge new_edge;
- block_stmt_iterator bsi;
- tree curr_stmt_list;
-
- leader_match = leader;
-
- /* The tree_* cfg manipulation routines use the PENDING_EDGE field
- for various PHI manipulations, so it gets cleared when calls are
- made to make_forwarder_block(). So make sure the edge is clear,
- and use the saved stmt list. */
- PENDING_STMT (leader) = NULL;
- leader->aux = leader;
- curr_stmt_list = VEC_index (tree, stmt_list, x);
-
- new_edge = make_forwarder_block (leader->dest, same_stmt_list_p,
- NULL);
- bb = new_edge->dest;
- if (dump_file)
- {
- fprintf (dump_file, "Splitting BB %d for Common stmt list. ",
- leader->dest->index);
- fprintf (dump_file, "Original block is now BB%d.\n", bb->index);
- print_generic_stmt (dump_file, curr_stmt_list, TDF_VOPS);
- }
-
- FOR_EACH_EDGE (e, ei, new_edge->src->preds)
- {
- e->aux = NULL;
- if (dump_file)
- fprintf (dump_file, " Edge (%d->%d) lands here.\n",
- e->src->index, e->dest->index);
- }
-
- bsi = bsi_last (leader->dest);
- bsi_insert_after (&bsi, curr_stmt_list, BSI_NEW_STMT);
-
- leader_match = NULL;
- /* We should never get a new block now. */
- }
- else
- {
- PENDING_STMT (leader) = VEC_index (tree, stmt_list, x);
- bsi_commit_one_edge_insert (leader, NULL);
- }
-
-
- /* Clear the working data structures. */
- VEC_truncate (edge, edge_leader, 0);
- VEC_truncate (tree, stmt_list, 0);
- bitmap_clear (leader_has_match);