/* Iterator routines for GIMPLE statements.
- Copyright (C) 2007, 2008, 2010 Free Software Foundation, Inc.
+ Copyright (C) 2007-2015 Free Software Foundation, Inc.
Contributed by Aldy Hernandez <aldy@quesejoda.com>
This file is part of GCC.
#include "system.h"
#include "coretypes.h"
#include "tm.h"
+#include "alias.h"
+#include "symtab.h"
#include "tree.h"
+#include "fold-const.h"
+#include "predict.h"
+#include "hard-reg-set.h"
+#include "function.h"
+#include "dominance.h"
+#include "cfg.h"
+#include "basic-block.h"
+#include "tree-ssa-alias.h"
+#include "internal-fn.h"
+#include "tree-eh.h"
+#include "gimple-expr.h"
#include "gimple.h"
-#include "tree-flow.h"
+#include "gimple-iterator.h"
+#include "gimple-ssa.h"
+#include "cgraph.h"
+#include "tree-cfg.h"
+#include "tree-phinodes.h"
+#include "ssa-iterators.h"
+#include "tree-ssa.h"
#include "value-prof.h"
/* Mark the statements in SEQ as modified, and update them. */
-static void
+void
update_modified_stmts (gimple_seq seq)
{
gimple_stmt_iterator gsi;
{
gimple_seq_node n;
- for (n = first; n; n = n->gsbase.next)
+ for (n = first; n; n = n->next)
{
gimple_set_bb (n, bb);
if (n == last)
int bb_freq = 0;
gimple_seq_node n;
- for (n = first; n ; n = n->gsbase.next)
+ for (n = first; n ; n = n->next)
if (is_gimple_call (n))
{
struct cgraph_edge *e;
to avoid calling them if we never see any calls. */
if (cfun_node == NULL)
{
- cfun_node = cgraph_get_node (current_function_decl);
+ cfun_node = cgraph_node::get (current_function_decl);
bb_freq = (compute_call_stmt_bb_frequency
(current_function_decl, bb));
}
- e = cgraph_edge (cfun_node, n);
+ e = cfun_node->get_edge (n);
if (e != NULL)
e->frequency = bb_freq;
}
basic_block bb;
gimple_seq_node cur = i->ptr;
- gcc_assert (!cur || cur->gsbase.prev);
+ gcc_assert (!cur || cur->prev);
if ((bb = gsi_bb (*i)) != NULL)
update_bb_for_stmts (first, last, bb);
/* Link SEQ before CUR in the sequence. */
if (cur)
{
- first->gsbase.prev = cur->gsbase.prev;
- if (first->gsbase.prev->gsbase.next)
- first->gsbase.prev->gsbase.next = first;
+ first->prev = cur->prev;
+ if (first->prev->next)
+ first->prev->next = first;
else
gimple_seq_set_first (i->seq, first);
- last->gsbase.next = cur;
- cur->gsbase.prev = last;
+ last->next = cur;
+ cur->prev = last;
}
else
{
labels, so it returns an iterator after the end of the block, and
we need to insert before it; it might be cleaner to add a flag to the
iterator saying whether we are at the start or end of the list). */
- last->gsbase.next = NULL;
+ last->next = NULL;
if (itlast)
{
- first->gsbase.prev = itlast;
- itlast->gsbase.next = first;
+ first->prev = itlast;
+ itlast->next = first;
}
else
gimple_seq_set_first (i->seq, first);
basic_block bb;
gimple_seq_node cur = i->ptr;
- gcc_assert (!cur || cur->gsbase.prev);
+ gcc_assert (!cur || cur->prev);
/* If the iterator is inside a basic block, we need to update the
basic block information for all the nodes between FIRST and LAST. */
/* Link SEQ after CUR. */
if (cur)
{
- last->gsbase.next = cur->gsbase.next;
- if (last->gsbase.next)
+ last->next = cur->next;
+ if (last->next)
{
- last->gsbase.next->gsbase.prev = last;
+ last->next->prev = last;
}
else
gimple_seq_set_last (i->seq, last);
- first->gsbase.prev = cur;
- cur->gsbase.next = first;
+ first->prev = cur;
+ cur->next = first;
}
else
{
gcc_assert (!gimple_seq_last (*i->seq));
- last->gsbase.next = NULL;
+ last->next = NULL;
gimple_seq_set_first (i->seq, first);
gimple_seq_set_last (i->seq, last);
}
cur = i.ptr;
/* How can we possibly split after the end, or before the beginning? */
- gcc_assert (cur && cur->gsbase.next);
- next = cur->gsbase.next;
+ gcc_assert (cur && cur->next);
+ next = cur->next;
pold_seq = i.seq;
gimple_seq_set_first (&new_seq, next);
gimple_seq_set_last (&new_seq, gimple_seq_last (*pold_seq));
gimple_seq_set_last (pold_seq, cur);
- cur->gsbase.next = NULL;
+ cur->next = NULL;
return new_seq;
}
gimple orig_stmt = gsi_stmt (*gsi);
gimple prev, next;
- stmt->gsbase.next = next = orig_stmt->gsbase.next;
- stmt->gsbase.prev = prev = orig_stmt->gsbase.prev;
+ stmt->next = next = orig_stmt->next;
+ stmt->prev = prev = orig_stmt->prev;
/* Note how we don't clear next/prev of orig_stmt. This is so that
copies of *GSI our callers might still hold (to orig_stmt)
can be advanced as if they too were replaced. */
- if (prev->gsbase.next)
- prev->gsbase.next = stmt;
+ if (prev->next)
+ prev->next = stmt;
else
gimple_seq_set_first (gsi->seq, stmt);
if (next)
- next->gsbase.prev = stmt;
+ next->prev = stmt;
else
gimple_seq_set_last (gsi->seq, stmt);
/* How can we possibly split after the end? */
gcc_assert (cur);
- prev = cur->gsbase.prev;
+ prev = cur->prev;
old_seq = *i->seq;
- if (!prev->gsbase.next)
+ if (!prev->next)
*i->seq = NULL;
i->seq = pnew_seq;
/* Cut OLD_SEQ before I. */
gimple_seq_set_last (&old_seq, prev);
- if (prev->gsbase.next)
- prev->gsbase.next = NULL;
+ if (prev->next)
+ prev->next = NULL;
}
/* Replace the statement pointed-to by GSI to STMT. If UPDATE_EH_INFO
is true, the exception handling information of the original
statement is moved to the new statement. Assignments must only be
- replaced with assignments to the same LHS. */
+ replaced with assignments to the same LHS. Returns whether EH edge
+ cleanup is required. */
-void
+bool
gsi_replace (gimple_stmt_iterator *gsi, gimple stmt, bool update_eh_info)
{
gimple orig_stmt = gsi_stmt (*gsi);
+ bool require_eh_edge_purge = false;
if (stmt == orig_stmt)
- return;
+ return false;
gcc_assert (!gimple_has_lhs (orig_stmt) || !gimple_has_lhs (stmt)
|| gimple_get_lhs (orig_stmt) == gimple_get_lhs (stmt));
/* Preserve EH region information from the original statement, if
requested by the caller. */
if (update_eh_info)
- maybe_clean_or_replace_eh_stmt (orig_stmt, stmt);
+ require_eh_edge_purge = maybe_clean_or_replace_eh_stmt (orig_stmt, stmt);
gimple_duplicate_stmt_histograms (cfun, stmt, cfun, orig_stmt);
gsi_set_stmt (gsi, stmt);
gimple_set_modified (stmt, true);
update_modified_stmt (stmt);
+ return require_eh_edge_purge;
}
/* Update the iterator and re-wire the links in I->SEQ. */
cur = i->ptr;
- next = cur->gsbase.next;
- prev = cur->gsbase.prev;
+ next = cur->next;
+ prev = cur->prev;
/* See gsi_set_stmt for why we don't reset prev/next of STMT. */
if (next)
/* Cur is not last. */
- next->gsbase.prev = prev;
- else if (prev->gsbase.next)
+ next->prev = prev;
+ else if (prev->next)
/* Cur is last but not first. */
gimple_seq_set_last (i->seq, prev);
- if (prev->gsbase.next)
+ if (prev->next)
/* Cur is not first. */
- prev->gsbase.next = next;
+ prev->next = next;
else
/* Cur is first. */
*i->seq = next;
return i;
}
+/* Finds iterator for PHI. */
+
+gphi_iterator
+gsi_for_phi (gphi *phi)
+{
+ gphi_iterator i;
+ basic_block bb = gimple_bb (phi);
+
+ i = gsi_start_phis (bb);
+ i.ptr = phi;
+
+ return i;
+}
/* Move the statement at FROM so it comes right after the statement at TO. */
gimple_seq_add_seq (&PENDING_STMT (e), seq);
}
+/* Return a new iterator pointing to the first statement in sequence of
+ statements on edge E. Such statements need to be subsequently moved into a
+ basic block by calling gsi_commit_edge_inserts. */
+
+gimple_stmt_iterator
+gsi_start_edge (edge e)
+{
+ return gsi_start (PENDING_STMT (e));
+}
/* Insert the statement pointed-to by GSI into edge E. Every attempt
is made to place the statement in an existing basic block, but
restart:
if (single_pred_p (dest)
&& gimple_seq_empty_p (phi_nodes (dest))
- && dest != EXIT_BLOCK_PTR)
+ && dest != EXIT_BLOCK_PTR_FOR_FN (cfun))
{
*gsi = gsi_start_bb (dest);
if (gsi_end_p (*gsi))
src = e->src;
if ((e->flags & EDGE_ABNORMAL) == 0
&& single_succ_p (src)
- && src != ENTRY_BLOCK_PTR)
+ && src != ENTRY_BLOCK_PTR_FOR_FN (cfun))
{
*gsi = gsi_last_bb (src);
if (gsi_end_p (*gsi))
edge e;
edge_iterator ei;
- gsi_commit_one_edge_insert (single_succ_edge (ENTRY_BLOCK_PTR), NULL);
+ gsi_commit_one_edge_insert (single_succ_edge (ENTRY_BLOCK_PTR_FOR_FN (cfun)),
+ NULL);
- FOR_EACH_BB (bb)
+ FOR_EACH_BB_FN (bb, cfun)
FOR_EACH_EDGE (e, ei, bb->succs)
gsi_commit_one_edge_insert (e, NULL);
}
/* Returns iterator at the start of the list of phi nodes of BB. */
-gimple_stmt_iterator
+gphi_iterator
gsi_start_phis (basic_block bb)
{
gimple_seq *pseq = phi_nodes_ptr (bb);
- return gsi_start_1 (pseq);
+
+ /* Adapted from gsi_start_1. */
+ gphi_iterator i;
+
+ i.ptr = gimple_seq_first (*pseq);
+ i.seq = pseq;
+ i.bb = i.ptr ? gimple_bb (i.ptr) : NULL;
+
+ return i;
}