- return NULL_TREE;
-}
-
-
-/* Mark BB as the basic block holding statement T. */
-
-void
-set_bb_for_stmt (tree t, basic_block bb)
-{
- if (TREE_CODE (t) == PHI_NODE)
- PHI_BB (t) = bb;
- else if (TREE_CODE (t) == STATEMENT_LIST)
- {
- tree_stmt_iterator i;
- for (i = tsi_start (t); !tsi_end_p (i); tsi_next (&i))
- set_bb_for_stmt (tsi_stmt (i), bb);
- }
- else
- {
- stmt_ann_t ann = get_stmt_ann (t);
- ann->bb = bb;
-
- /* If the statement is a label, add the label to block-to-labels map
- so that we can speed up edge creation for GOTO_EXPRs. */
- if (TREE_CODE (t) == LABEL_EXPR)
- {
- int uid;
-
- t = LABEL_EXPR_LABEL (t);
- uid = LABEL_DECL_UID (t);
- if (uid == -1)
- {
- unsigned old_len = VEC_length (basic_block, label_to_block_map);
- LABEL_DECL_UID (t) = uid = cfun->cfg->last_label_uid++;
- if (old_len <= (unsigned) uid)
- {
- unsigned new_len = 3 * uid / 2;
-
- VEC_safe_grow_cleared (basic_block, gc, label_to_block_map,
- new_len);
- }
- }
- else
- /* We're moving an existing label. Make sure that we've
- removed it from the old block. */
- gcc_assert (!bb
- || !VEC_index (basic_block, label_to_block_map, uid));
- VEC_replace (basic_block, label_to_block_map, uid, bb);
- }
- }
-}
-
-/* Faster version of set_bb_for_stmt that assume that statement is being moved
- from one basic block to another.
- For BB splitting we can run into quadratic case, so performance is quite
- important and knowing that the tables are big enough, change_bb_for_stmt
- can inline as leaf function. */
-static inline void
-change_bb_for_stmt (tree t, basic_block bb)
-{
- get_stmt_ann (t)->bb = bb;
- if (TREE_CODE (t) == LABEL_EXPR)
- VEC_replace (basic_block, label_to_block_map,
- LABEL_DECL_UID (LABEL_EXPR_LABEL (t)), bb);
-}
-
-/* Finds iterator for STMT. */
-
-extern block_stmt_iterator
-bsi_for_stmt (tree stmt)
-{
- block_stmt_iterator bsi;
-
- for (bsi = bsi_start (bb_for_stmt (stmt)); !bsi_end_p (bsi); bsi_next (&bsi))
- if (bsi_stmt (bsi) == stmt)
- return bsi;
-
- gcc_unreachable ();
-}
-
-/* Mark statement T as modified, and update it. */
-static inline void
-update_modified_stmts (tree t)
-{
- if (!ssa_operands_active ())
- return;
- if (TREE_CODE (t) == STATEMENT_LIST)
- {
- tree_stmt_iterator i;
- tree stmt;
- for (i = tsi_start (t); !tsi_end_p (i); tsi_next (&i))
- {
- stmt = tsi_stmt (i);
- update_stmt_if_modified (stmt);
- }
- }
- else
- update_stmt_if_modified (t);
-}
-
-/* Insert statement (or statement list) T before the statement
- pointed-to by iterator I. M specifies how to update iterator I
- after insertion (see enum bsi_iterator_update). */
-
-void
-bsi_insert_before (block_stmt_iterator *i, tree t, enum bsi_iterator_update m)
-{
- set_bb_for_stmt (t, i->bb);
- update_modified_stmts (t);
- tsi_link_before (&i->tsi, t, m);
-}
-
-
-/* Insert statement (or statement list) T after the statement
- pointed-to by iterator I. M specifies how to update iterator I
- after insertion (see enum bsi_iterator_update). */
-
-void
-bsi_insert_after (block_stmt_iterator *i, tree t, enum bsi_iterator_update m)
-{
- set_bb_for_stmt (t, i->bb);
- update_modified_stmts (t);
- tsi_link_after (&i->tsi, t, m);
-}
-
-
-/* Remove the statement pointed to by iterator I. The iterator is updated
- to the next statement.
-
- When REMOVE_EH_INFO is true we remove the statement pointed to by
- iterator I from the EH tables. Otherwise we do not modify the EH
- tables.
-
- Generally, REMOVE_EH_INFO should be true when the statement is going to
- be removed from the IL and not reinserted elsewhere. */
-
-void
-bsi_remove (block_stmt_iterator *i, bool remove_eh_info)
-{
- tree t = bsi_stmt (*i);
- set_bb_for_stmt (t, NULL);
- delink_stmt_imm_use (t);
- tsi_delink (&i->tsi);
- mark_stmt_modified (t);
- if (remove_eh_info)
- {
- remove_stmt_from_eh_region (t);
- gimple_remove_stmt_histograms (cfun, t);
- }
-}
-
-
-/* Move the statement at FROM so it comes right after the statement at TO. */
-
-void
-bsi_move_after (block_stmt_iterator *from, block_stmt_iterator *to)
-{
- tree stmt = bsi_stmt (*from);
- bsi_remove (from, false);
- /* We must have BSI_NEW_STMT here, as bsi_move_after is sometimes used to
- move statements to an empty block. */
- bsi_insert_after (to, stmt, BSI_NEW_STMT);
-}
-
-
-/* Move the statement at FROM so it comes right before the statement at TO. */
-
-void
-bsi_move_before (block_stmt_iterator *from, block_stmt_iterator *to)
-{
- tree stmt = bsi_stmt (*from);
- bsi_remove (from, false);
- /* For consistency with bsi_move_after, it might be better to have
- BSI_NEW_STMT here; however, that breaks several places that expect
- that TO does not change. */
- bsi_insert_before (to, stmt, BSI_SAME_STMT);
-}
-
-
-/* Move the statement at FROM to the end of basic block BB. */
-
-void
-bsi_move_to_bb_end (block_stmt_iterator *from, basic_block bb)
-{
- block_stmt_iterator last = bsi_last (bb);
-
- /* Have to check bsi_end_p because it could be an empty block. */
- if (!bsi_end_p (last) && is_ctrl_stmt (bsi_stmt (last)))
- bsi_move_before (from, &last);
- else
- bsi_move_after (from, &last);
-}
-
-
-/* Replace the contents of the statement pointed to by iterator BSI
- with STMT. If UPDATE_EH_INFO is true, the exception handling
- information of the original statement is moved to the new statement. */
-
-void
-bsi_replace (const block_stmt_iterator *bsi, tree stmt, bool update_eh_info)
-{
- int eh_region;
- tree orig_stmt = bsi_stmt (*bsi);
-
- if (stmt == orig_stmt)
- return;
- SET_EXPR_LOCUS (stmt, EXPR_LOCUS (orig_stmt));
- set_bb_for_stmt (stmt, bsi->bb);
-
- /* Preserve EH region information from the original statement, if
- requested by the caller. */
- if (update_eh_info)
- {
- eh_region = lookup_stmt_eh_region (orig_stmt);
- if (eh_region >= 0)
- {
- remove_stmt_from_eh_region (orig_stmt);
- add_stmt_to_eh_region (stmt, eh_region);
- }
- }
-
- gimple_duplicate_stmt_histograms (cfun, stmt, cfun, orig_stmt);
- gimple_remove_stmt_histograms (cfun, orig_stmt);
- delink_stmt_imm_use (orig_stmt);
- *bsi_stmt_ptr (*bsi) = stmt;
- mark_stmt_modified (stmt);
- update_modified_stmts (stmt);
-}
-
-
-/* Insert the statement pointed-to by BSI into edge E. Every attempt
- is made to place the statement in an existing basic block, but
- sometimes that isn't possible. When it isn't possible, the edge is
- split and the statement is added to the new block.
-
- In all cases, the returned *BSI points to the correct location. The
- return value is true if insertion should be done after the location,
- or false if it should be done before the location. If new basic block
- has to be created, it is stored in *NEW_BB. */
-
-static bool
-tree_find_edge_insert_loc (edge e, block_stmt_iterator *bsi,
- basic_block *new_bb)
-{
- basic_block dest, src;
- tree tmp;
-
- dest = e->dest;
- restart:
-
- /* If the destination has one predecessor which has no PHI nodes,
- insert there. Except for the exit block.
-
- The requirement for no PHI nodes could be relaxed. Basically we
- would have to examine the PHIs to prove that none of them used
- the value set by the statement we want to insert on E. That
- hardly seems worth the effort. */
- if (single_pred_p (dest)
- && ! phi_nodes (dest)
- && dest != EXIT_BLOCK_PTR)
- {
- *bsi = bsi_start (dest);
- if (bsi_end_p (*bsi))
- return true;
-
- /* Make sure we insert after any leading labels. */
- tmp = bsi_stmt (*bsi);
- while (TREE_CODE (tmp) == LABEL_EXPR)
- {
- bsi_next (bsi);
- if (bsi_end_p (*bsi))
- break;
- tmp = bsi_stmt (*bsi);
- }
-
- if (bsi_end_p (*bsi))
- {
- *bsi = bsi_last (dest);
- return true;
- }
- else
- return false;
- }
-
- /* If the source has one successor, the edge is not abnormal and
- the last statement does not end a basic block, insert there.
- Except for the entry block. */
- src = e->src;
- if ((e->flags & EDGE_ABNORMAL) == 0
- && single_succ_p (src)
- && src != ENTRY_BLOCK_PTR)
- {
- *bsi = bsi_last (src);
- if (bsi_end_p (*bsi))
- return true;
-
- tmp = bsi_stmt (*bsi);
- if (!stmt_ends_bb_p (tmp))
- return true;
-
- /* Insert code just before returning the value. We may need to decompose
- the return in the case it contains non-trivial operand. */
- if (TREE_CODE (tmp) == RETURN_EXPR)
- {
- tree op = TREE_OPERAND (tmp, 0);
- if (op && !is_gimple_val (op))
- {
- gcc_assert (TREE_CODE (op) == GIMPLE_MODIFY_STMT);
- bsi_insert_before (bsi, op, BSI_NEW_STMT);
- TREE_OPERAND (tmp, 0) = GIMPLE_STMT_OPERAND (op, 0);
- }
- bsi_prev (bsi);
- return true;
- }
- }
-
- /* Otherwise, create a new basic block, and split this edge. */
- dest = split_edge (e);
- if (new_bb)
- *new_bb = dest;
- e = single_pred_edge (dest);
- goto restart;
-}
-
-
-/* This routine will commit all pending edge insertions, creating any new
- basic blocks which are necessary. */
-
-void
-bsi_commit_edge_inserts (void)
-{
- basic_block bb;
- edge e;
- edge_iterator ei;
-
- bsi_commit_one_edge_insert (single_succ_edge (ENTRY_BLOCK_PTR), NULL);
-
- FOR_EACH_BB (bb)
- FOR_EACH_EDGE (e, ei, bb->succs)
- bsi_commit_one_edge_insert (e, NULL);
-}
-
-
-/* Commit insertions pending at edge E. If a new block is created, set NEW_BB
- to this block, otherwise set it to NULL. */
-
-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;
- tree stmt = PENDING_STMT (e);
-
- PENDING_STMT (e) = NULL_TREE;
-
- 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);
- }
-}
-
-
-/* Add STMT to the pending list of edge E. No actual insertion is
- made until a call to bsi_commit_edge_inserts () is made. */
-
-void
-bsi_insert_on_edge (edge e, tree stmt)
-{
- append_to_statement_list (stmt, &PENDING_STMT (e));
-}
-
-/* Similar to bsi_insert_on_edge+bsi_commit_edge_inserts. If a new
- block has to be created, it is returned. */
-
-basic_block
-bsi_insert_on_edge_immediate (edge e, tree stmt)
-{
- block_stmt_iterator bsi;
- basic_block new_bb = NULL;
-
- gcc_assert (!PENDING_STMT (e));
-
- 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);
-
- return new_bb;