/* Control flow functions for trees.
- Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006
+ Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006, 2007
Free Software Foundation, Inc.
Contributed by Diego Novillo <dnovillo@redhat.com>
#include "except.h"
#include "cfgloop.h"
#include "cfglayout.h"
-#include "hashtab.h"
#include "tree-ssa-propagate.h"
+#include "value-prof.h"
+#include "pointer-set.h"
/* This file contains functions for building the Control Flow Graph (CFG)
for a function tree. */
more persistent. The key is getting notification of changes to
the CFG (particularly edge removal, creation and redirection). */
-struct edge_to_cases_elt
-{
- /* The edge itself. Necessary for hashing and equality tests. */
- edge e;
-
- /* The case labels associated with this edge. We link these up via
- their TREE_CHAIN field, then we wipe out the TREE_CHAIN fields
- when we destroy the hash table. This prevents problems when copying
- SWITCH_EXPRs. */
- tree case_labels;
-};
-
-static htab_t edge_to_cases;
+static struct pointer_map_t *edge_to_cases;
/* CFG statistics. */
struct cfg_stats_d
n_basic_blocks = NUM_FIXED_BLOCKS;
last_basic_block = NUM_FIXED_BLOCKS;
basic_block_info = VEC_alloc (basic_block, gc, initial_cfg_capacity);
- VEC_safe_grow (basic_block, gc, basic_block_info, initial_cfg_capacity);
- memset (VEC_address (basic_block, basic_block_info), 0,
- sizeof (basic_block) * initial_cfg_capacity);
+ VEC_safe_grow_cleared (basic_block, gc, basic_block_info,
+ initial_cfg_capacity);
/* Build a mapping of labels to their associated blocks. */
label_to_block_map = VEC_alloc (basic_block, gc, initial_cfg_capacity);
- VEC_safe_grow (basic_block, gc, label_to_block_map, initial_cfg_capacity);
- memset (VEC_address (basic_block, label_to_block_map),
- 0, sizeof (basic_block) * initial_cfg_capacity);
+ VEC_safe_grow_cleared (basic_block, gc, label_to_block_map,
+ initial_cfg_capacity);
SET_BASIC_BLOCK (ENTRY_BLOCK, ENTRY_BLOCK_PTR);
SET_BASIC_BLOCK (EXIT_BLOCK, EXIT_BLOCK_PTR);
/* Adjust the size of the array. */
if (VEC_length (basic_block, basic_block_info) < (size_t) n_basic_blocks)
- {
- size_t old_size = VEC_length (basic_block, basic_block_info);
- basic_block *p;
- VEC_safe_grow (basic_block, gc, basic_block_info, n_basic_blocks);
- p = VEC_address (basic_block, basic_block_info);
- memset (&p[old_size], 0,
- sizeof (basic_block) * (n_basic_blocks - old_size));
- }
+ VEC_safe_grow_cleared (basic_block, gc, basic_block_info, n_basic_blocks);
/* To speed up statement iterator walks, we first purge dead labels. */
cleanup_dead_labels ();
PROP_cfg, /* properties_provided */
0, /* properties_destroyed */
0, /* todo_flags_start */
- TODO_verify_stmts, /* todo_flags_finish */
+ TODO_verify_stmts | TODO_cleanup_cfg, /* todo_flags_finish */
0 /* letter */
};
}
/* Copy the original computed goto's destination into VAR. */
- assignment = build2 (MODIFY_EXPR, ptr_type_node,
- var, GOTO_DESTINATION (last));
+ assignment = build2_gimple (GIMPLE_MODIFY_STMT,
+ var, GOTO_DESTINATION (last));
bsi_insert_before (&bsi, assignment, BSI_SAME_STMT);
/* And re-vector the computed goto to the new destination. */
/* Grow the basic block array if needed. */
if ((size_t) last_basic_block == VEC_length (basic_block, basic_block_info))
{
- size_t old_size = VEC_length (basic_block, basic_block_info);
size_t new_size = last_basic_block + (last_basic_block + 3) / 4;
- basic_block *p;
- VEC_safe_grow (basic_block, gc, basic_block_info, new_size);
- p = VEC_address (basic_block, basic_block_info);
- memset (&p[old_size], 0, sizeof (basic_block) * (new_size - old_size));
+ VEC_safe_grow_cleared (basic_block, gc, basic_block_info, new_size);
}
/* Add the newly created block to the array. */
break;
case MODIFY_EXPR:
+ gcc_unreachable ();
+
+ case GIMPLE_MODIFY_STMT:
if (is_ctrl_altering_stmt (last))
{
- /* A MODIFY_EXPR may have a CALL_EXPR on its RHS and the
- CALL_EXPR may have an abnormal edge. Search the RHS for
- this case and create any required edges. */
+ /* A GIMPLE_MODIFY_STMT may have a CALL_EXPR on its RHS and
+ the CALL_EXPR may have an abnormal edge. Search the RHS
+ for this case and create any required edges. */
if (tree_can_make_abnormal_goto (last))
make_abnormal_goto_edges (bb, true);
/* Fold COND_EXPR_COND of each COND_EXPR. */
fold_cond_expr_cond ();
-
- /* Clean up the graph and warn for unreachable code. */
- cleanup_tree_cfg ();
}
}
}
-/* Hashing routine for EDGE_TO_CASES. */
-
-static hashval_t
-edge_to_cases_hash (const void *p)
-{
- edge e = ((struct edge_to_cases_elt *)p)->e;
-
- /* Hash on the edge itself (which is a pointer). */
- return htab_hash_pointer (e);
-}
-
-/* Equality routine for EDGE_TO_CASES, edges are unique, so testing
- for equality is just a pointer comparison. */
-
-static int
-edge_to_cases_eq (const void *p1, const void *p2)
-{
- edge e1 = ((struct edge_to_cases_elt *)p1)->e;
- edge e2 = ((struct edge_to_cases_elt *)p2)->e;
-
- return e1 == e2;
-}
/* Called for each element in the hash table (P) as we delete the
edge to cases hash table.
SWITCH_EXPRs and structure sharing rules, then free the hash table
element. */
-static void
-edge_to_cases_cleanup (void *p)
+static bool
+edge_to_cases_cleanup (void *key ATTRIBUTE_UNUSED, void **value,
+ void *data ATTRIBUTE_UNUSED)
{
- struct edge_to_cases_elt *elt = (struct edge_to_cases_elt *) p;
tree t, next;
- for (t = elt->case_labels; t; t = next)
+ for (t = (tree) *value; t; t = next)
{
next = TREE_CHAIN (t);
TREE_CHAIN (t) = NULL;
}
- free (p);
+
+ *value = NULL;
+ return false;
}
/* Start recording information mapping edges to case labels. */
start_recording_case_labels (void)
{
gcc_assert (edge_to_cases == NULL);
-
- edge_to_cases = htab_create (37,
- edge_to_cases_hash,
- edge_to_cases_eq,
- edge_to_cases_cleanup);
+ edge_to_cases = pointer_map_create ();
}
/* Return nonzero if we are recording information for case labels. */
void
end_recording_case_labels (void)
{
- htab_delete (edge_to_cases);
+ pointer_map_traverse (edge_to_cases, edge_to_cases_cleanup, NULL);
+ pointer_map_destroy (edge_to_cases);
edge_to_cases = NULL;
}
-/* Record that CASE_LABEL (a CASE_LABEL_EXPR) references edge E. */
-
-static void
-record_switch_edge (edge e, tree case_label)
-{
- struct edge_to_cases_elt *elt;
- void **slot;
-
- /* Build a hash table element so we can see if E is already
- in the table. */
- elt = XNEW (struct edge_to_cases_elt);
- elt->e = e;
- elt->case_labels = case_label;
-
- slot = htab_find_slot (edge_to_cases, elt, INSERT);
-
- if (*slot == NULL)
- {
- /* E was not in the hash table. Install E into the hash table. */
- *slot = (void *)elt;
- }
- else
- {
- /* E was already in the hash table. Free ELT as we do not need it
- anymore. */
- free (elt);
-
- /* Get the entry stored in the hash table. */
- elt = (struct edge_to_cases_elt *) *slot;
-
- /* Add it to the chain of CASE_LABEL_EXPRs referencing E. */
- TREE_CHAIN (case_label) = elt->case_labels;
- elt->case_labels = case_label;
- }
-}
-
/* If we are inside a {start,end}_recording_cases block, then return
a chain of CASE_LABEL_EXPRs from T which reference E.
static tree
get_cases_for_edge (edge e, tree t)
{
- struct edge_to_cases_elt elt, *elt_p;
void **slot;
size_t i, n;
tree vec;
if (!recording_case_labels_p ())
return NULL;
-restart:
- elt.e = e;
- elt.case_labels = NULL;
- slot = htab_find_slot (edge_to_cases, &elt, NO_INSERT);
-
+ slot = pointer_map_contains (edge_to_cases, e);
if (slot)
- {
- elt_p = (struct edge_to_cases_elt *)*slot;
- return elt_p->case_labels;
- }
+ return (tree) *slot;
/* If we did not find E in the hash table, then this must be the first
time we have been queried for information about E & T. Add all the
n = TREE_VEC_LENGTH (vec);
for (i = 0; i < n; i++)
{
- tree lab = CASE_LABEL (TREE_VEC_ELT (vec, i));
+ tree elt = TREE_VEC_ELT (vec, i);
+ tree lab = CASE_LABEL (elt);
basic_block label_bb = label_to_block (lab);
- record_switch_edge (find_edge (e->src, label_bb), TREE_VEC_ELT (vec, i));
+ edge this_edge = find_edge (e->src, label_bb);
+
+ /* Add it to the chain of CASE_LABEL_EXPRs referencing E, or create
+ a new chain. */
+ slot = pointer_map_insert (edge_to_cases, this_edge);
+ TREE_CHAIN (elt) = (tree) *slot;
+ *slot = elt;
}
- goto restart;
+
+ return (tree) *pointer_map_contains (edge_to_cases, e);
}
/* Create the edges for a SWITCH_EXPR starting at block BB.
return false;
/* It must be possible to eliminate all phi nodes in B. If ssa form
- is not up-to-date, we cannot eliminate any phis. */
+ is not up-to-date, we cannot eliminate any phis; however, if only
+ some symbols as whole are marked for renaming, this is not a problem,
+ as phi nodes for those symbols are irrelevant in updating anyway. */
phi = phi_nodes (b);
if (phi)
{
- if (need_ssa_update_p ())
+ if (name_mappings_registered_p ())
return false;
for (; phi; phi = PHI_CHAIN (phi))
use_operand_p use;
tree stmt;
edge e;
- unsigned i;
-
FOR_EACH_IMM_USE_STMT (stmt, imm_iter, name)
{
+ if (TREE_CODE (stmt) != PHI_NODE)
+ push_stmt_changes (&stmt);
+
FOR_EACH_IMM_USE_ON_STMT (use, imm_iter)
{
replace_exp (use, val);
}
}
}
+
if (TREE_CODE (stmt) != PHI_NODE)
{
tree rhs;
fold_stmt_inplace (stmt);
+
+ /* FIXME. This should go in pop_stmt_changes. */
rhs = get_rhs (stmt);
if (TREE_CODE (rhs) == ADDR_EXPR)
recompute_tree_invariant_for_addr_expr (rhs);
maybe_clean_or_replace_eh_stmt (stmt, stmt);
- mark_new_vars_to_rename (stmt);
+
+ pop_stmt_changes (&stmt);
}
}
- gcc_assert (num_imm_uses (name) == 0);
+ gcc_assert (zero_imm_uses_p (name));
/* Also update the trees stored in loop structures. */
if (current_loops)
{
struct loop *loop;
+ loop_iterator li;
- for (i = 0; i < current_loops->num; i++)
+ FOR_EACH_LOOP (li, loop, 0)
{
- loop = current_loops->parray[i];
- if (loop)
- substitute_in_loop_info (loop, name, val);
+ substitute_in_loop_info (loop, name, val);
}
}
}
with ordering of phi nodes. This is because A is the single
predecessor of B, therefore results of the phi nodes cannot
appear as arguments of the phi nodes. */
- copy = build2 (MODIFY_EXPR, void_type_node, def, use);
+ copy = build2_gimple (GIMPLE_MODIFY_STMT, def, use);
bsi_insert_after (&bsi, copy, BSI_NEW_STMT);
- SET_PHI_RESULT (phi, NULL_TREE);
SSA_NAME_DEF_STMT (def) = copy;
+ remove_phi_node (phi, NULL, false);
}
else
- replace_uses_by (def, use);
-
- remove_phi_node (phi, NULL);
+ {
+ replace_uses_by (def, use);
+ remove_phi_node (phi, NULL, true);
+ }
}
/* Ensure that B follows A. */
else if (TREE_CODE (cond) == VAR_DECL || TREE_CODE (cond) == PARM_DECL)
{
if (else_stmt
- && TREE_CODE (else_stmt) == MODIFY_EXPR
- && TREE_OPERAND (else_stmt, 0) == cond
- && integer_zerop (TREE_OPERAND (else_stmt, 1)))
+ && TREE_CODE (else_stmt) == GIMPLE_MODIFY_STMT
+ && GIMPLE_STMT_OPERAND (else_stmt, 0) == cond
+ && integer_zerop (GIMPLE_STMT_OPERAND (else_stmt, 1)))
COND_EXPR_ELSE (*stmt_p) = alloc_stmt_list ();
}
else if ((TREE_CODE (cond) == EQ_EXPR || TREE_CODE (cond) == NE_EXPR)
: &COND_EXPR_ELSE (*stmt_p));
if (stmt
- && TREE_CODE (stmt) == MODIFY_EXPR
- && TREE_OPERAND (stmt, 0) == TREE_OPERAND (cond, 0)
- && TREE_OPERAND (stmt, 1) == TREE_OPERAND (cond, 1))
+ && TREE_CODE (stmt) == GIMPLE_MODIFY_STMT
+ && GIMPLE_STMT_OPERAND (stmt, 0) == TREE_OPERAND (cond, 0)
+ && GIMPLE_STMT_OPERAND (stmt, 1) == TREE_OPERAND (cond, 1))
*location = alloc_stmt_list ();
}
}
break;
case MODIFY_EXPR:
+ gcc_unreachable ();
+
+ case GIMPLE_MODIFY_STMT:
data->last_goto = NULL;
fold_stmt (tp);
op = get_call_expr_in (t);
while (phi)
{
tree next = PHI_CHAIN (phi);
- remove_phi_node (phi, NULL_TREE);
+ remove_phi_node (phi, NULL_TREE, true);
phi = next;
}
}
}
- /* If we remove the header or the latch of a loop, mark the loop for
- removal by setting its header and latch to NULL. */
if (current_loops)
{
struct loop *loop = bb->loop_father;
+ /* If a loop gets removed, clean up the information associated
+ with it. */
if (loop->latch == bb
|| loop->header == bb)
- {
- loop->latch = NULL;
- loop->header = NULL;
-
- /* Also clean up the information associated with the loop. Updating
- it would waste time. More importantly, it may refer to ssa
- names that were defined in other removed basic block -- these
- ssa names are now removed and invalid. */
- free_numbers_of_iterations_estimates_loop (loop);
- }
+ free_numbers_of_iterations_estimates_loop (loop);
}
/* Remove all the instructions in the block. */
may be called when not in SSA. For example,
final_cleanup calls this function via
cleanup_tree_cfg. */
- if (in_ssa_p)
+ if (gimple_in_ssa_p (cfun))
release_defs (stmt);
bsi_remove (&i, true);
extract_true_false_edges_from_block (bb, &true_edge, &false_edge);
gcc_assert (TREE_CODE (val) == INTEGER_CST);
- return (zero_p (val) ? false_edge : true_edge);
+ return (integer_zerop (val) ? false_edge : true_edge);
}
/* Given an INTEGER_CST VAL and the entry block BB to a SWITCH_EXPR
void
tree_dump_bb (basic_block bb, FILE *outf, int indent)
{
- dump_generic_bb (outf, bb, indent, TDF_VOPS);
+ dump_generic_bb (outf, bb, indent, TDF_VOPS|TDF_MEMSYMS);
}
{
if (computed_goto_p (t))
return true;
- if (TREE_CODE (t) == MODIFY_EXPR)
- t = TREE_OPERAND (t, 1);
+ if (TREE_CODE (t) == GIMPLE_MODIFY_STMT)
+ t = GIMPLE_STMT_OPERAND (t, 1);
if (TREE_CODE (t) == WITH_SIZE_EXPR)
t = TREE_OPERAND (t, 0);
if (TREE_CODE (t) == CALL_EXPR)
void
delete_tree_cfg_annotations (void)
{
+ basic_block bb;
+ block_stmt_iterator bsi;
+
+ /* Remove annotations from every tree in the function. */
+ FOR_EACH_BB (bb)
+ for (bsi = bsi_start (bb); !bsi_end_p (bsi); bsi_next (&bsi))
+ {
+ tree stmt = bsi_stmt (bsi);
+ ggc_free (stmt->base.ann);
+ stmt->base.ann = NULL;
+ }
label_to_block_map = NULL;
}
}
-/* Return a pointer to the last statement in block BB. */
-
-tree *
-last_stmt_ptr (basic_block bb)
-{
- block_stmt_iterator last = bsi_last (bb);
- return !bsi_end_p (last) ? bsi_stmt_ptr (last) : NULL;
-}
-
-
/* Return the last statement of an otherwise empty block. Return NULL
if the block is totally empty, or if it contains more than one
statement. */
LABEL_DECL_UID (t) = uid = cfun->last_label_uid++;
if (old_len <= (unsigned) uid)
{
- basic_block *addr;
unsigned new_len = 3 * uid / 2;
- VEC_safe_grow (basic_block, gc, label_to_block_map,
- new_len);
- addr = VEC_address (basic_block, label_to_block_map);
- memset (&addr[old_len],
- 0, sizeof (basic_block) * (new_len - old_len));
+ VEC_safe_grow_cleared (basic_block, gc, label_to_block_map,
+ new_len);
}
}
else
static inline void
update_modified_stmts (tree t)
{
+ if (!ssa_operands_active ())
+ return;
if (TREE_CODE (t) == STATEMENT_LIST)
{
tree_stmt_iterator i;
tsi_delink (&i->tsi);
mark_stmt_modified (t);
if (remove_eh_info)
- remove_stmt_from_eh_region (t);
+ {
+ remove_stmt_from_eh_region (t);
+ gimple_remove_stmt_histograms (cfun, t);
+ }
}
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);
}
}
+ 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);
tree op = TREE_OPERAND (tmp, 0);
if (op && !is_gimple_val (op))
{
- gcc_assert (TREE_CODE (op) == MODIFY_EXPR);
+ gcc_assert (TREE_CODE (op) == GIMPLE_MODIFY_STMT);
bsi_insert_before (bsi, op, BSI_NEW_STMT);
- TREE_OPERAND (tmp, 0) = TREE_OPERAND (op, 0);
+ TREE_OPERAND (tmp, 0) = GIMPLE_STMT_OPERAND (op, 0);
}
bsi_prev (bsi);
return true;
break;
case MODIFY_EXPR:
- x = TREE_OPERAND (t, 0);
+ gcc_unreachable ();
+
+ case GIMPLE_MODIFY_STMT:
+ x = GIMPLE_STMT_OPERAND (t, 0);
if (TREE_CODE (x) == BIT_FIELD_REF
&& is_gimple_reg (TREE_OPERAND (x, 0)))
{
case NOP_EXPR:
case CONVERT_EXPR:
case FIX_TRUNC_EXPR:
- case FIX_CEIL_EXPR:
- case FIX_FLOOR_EXPR:
- case FIX_ROUND_EXPR:
case FLOAT_EXPR:
case NEGATE_EXPR:
case ABS_EXPR:
CHECK_OP (1, "invalid operand to binary operator");
break;
+ case CONSTRUCTOR:
+ if (TREE_CONSTANT (t) && TREE_CODE (TREE_TYPE (t)) == VECTOR_TYPE)
+ *walk_subtrees = 0;
+ break;
+
default:
break;
}
static tree
verify_node_sharing (tree * tp, int *walk_subtrees, void *data)
{
- htab_t htab = (htab_t) data;
- void **slot;
+ struct pointer_set_t *visited = (struct pointer_set_t *) data;
if (tree_node_can_be_shared (*tp))
{
return NULL;
}
- slot = htab_find_slot (htab, *tp, INSERT);
- if (*slot)
- return (tree) *slot;
- *slot = *tp;
+ if (pointer_set_insert (visited, *tp))
+ return *tp;
return NULL;
}
+/* Helper function for verify_gimple_tuples. */
+
+static tree
+verify_gimple_tuples_1 (tree *tp, int *walk_subtrees ATTRIBUTE_UNUSED,
+ void *data ATTRIBUTE_UNUSED)
+{
+ switch (TREE_CODE (*tp))
+ {
+ case MODIFY_EXPR:
+ error ("unexpected non-tuple");
+ debug_tree (*tp);
+ gcc_unreachable ();
+ return NULL_TREE;
+
+ default:
+ return NULL_TREE;
+ }
+}
+
+/* Verify that there are no trees that should have been converted to
+ gimple tuples. Return true if T contains a node that should have
+ been converted to a gimple tuple, but hasn't. */
+
+static bool
+verify_gimple_tuples (tree t)
+{
+ return walk_tree (&t, verify_gimple_tuples_1, NULL, NULL) != NULL;
+}
+
+static bool eh_error_found;
+static int
+verify_eh_throw_stmt_node (void **slot, void *data)
+{
+ struct throw_stmt_node *node = (struct throw_stmt_node *)*slot;
+ struct pointer_set_t *visited = (struct pointer_set_t *) data;
+
+ if (!pointer_set_contains (visited, node->stmt))
+ {
+ error ("Dead STMT in EH table");
+ debug_generic_stmt (node->stmt);
+ eh_error_found = true;
+ }
+ return 0;
+}
+
/* Verify the GIMPLE statement chain. */
void
basic_block bb;
block_stmt_iterator bsi;
bool err = false;
- htab_t htab;
+ struct pointer_set_t *visited, *visited_stmts;
tree addr;
timevar_push (TV_TREE_STMT_VERIFY);
- htab = htab_create (37, htab_hash_pointer, htab_eq_pointer, NULL);
+ visited = pointer_set_create ();
+ visited_stmts = pointer_set_create ();
FOR_EACH_BB (bb)
{
{
int phi_num_args = PHI_NUM_ARGS (phi);
+ pointer_set_insert (visited_stmts, phi);
if (bb_for_stmt (phi) != bb)
{
error ("bb_for_stmt (phi) is set to a wrong basic block");
err |= true;
}
- addr = walk_tree (&t, verify_node_sharing, htab, NULL);
+ addr = walk_tree (&t, verify_node_sharing, visited, NULL);
if (addr)
{
error ("incorrect sharing of tree nodes");
{
tree stmt = bsi_stmt (bsi);
+ pointer_set_insert (visited_stmts, stmt);
+ err |= verify_gimple_tuples (stmt);
+
if (bb_for_stmt (stmt) != bb)
{
error ("bb_for_stmt (stmt) is set to a wrong basic block");
bsi_next (&bsi);
err |= verify_stmt (stmt, bsi_end_p (bsi));
- addr = walk_tree (&stmt, verify_node_sharing, htab, NULL);
+ addr = walk_tree (&stmt, verify_node_sharing, visited, NULL);
if (addr)
{
error ("incorrect sharing of tree nodes");
}
}
}
+ eh_error_found = false;
+ if (get_eh_throw_stmt_table (cfun))
+ htab_traverse (get_eh_throw_stmt_table (cfun),
+ verify_eh_throw_stmt_node,
+ visited_stmts);
- if (err)
+ if (err | eh_error_found)
internal_error ("verify_stmts failed");
- htab_delete (htab);
+ pointer_set_destroy (visited);
+ pointer_set_destroy (visited_stmts);
+ verify_histograms ();
timevar_pop (TV_TREE_STMT_VERIFY);
}
if (single_pred_p (bb))
return;
- /* If we redirected a branch we must create new phi nodes at the
+ /* If we redirected a branch we must create new PHI nodes at the
start of BB. */
for (phi = phi_nodes (dummy); phi; phi = PHI_CHAIN (phi))
{
return e;
}
+/* Returns true if it is possible to remove edge E by redirecting
+ it to the destination of the other edge from E->src. */
+
+static bool
+tree_can_remove_branch_p (edge e)
+{
+ if (e->flags & EDGE_ABNORMAL)
+ return false;
+
+ return true;
+}
/* Simple wrapper, as we can always redirect fallthru edges. */
region = lookup_stmt_eh_region (stmt);
if (region >= 0)
add_stmt_to_eh_region (copy, region);
+ gimple_duplicate_stmt_histograms (cfun, copy, cfun, stmt);
/* Create new names for all the definitions created by COPY and
add replacement mappings for each new name. */
struct move_stmt_d *p = (struct move_stmt_d *) data;
tree t = *tp;
- if (p->block && IS_EXPR_CODE_CLASS (TREE_CODE_CLASS (TREE_CODE (t))))
+ if (p->block
+ && (EXPR_P (t) || GIMPLE_STMT_P (t)))
TREE_BLOCK (t) = p->block;
if (OMP_DIRECTIVE_P (t)
block_stmt_iterator si;
struct move_stmt_d d;
unsigned old_len, new_len;
- basic_block *addr;
/* Link BB to the new linked list. */
move_block_after (bb, after);
if ((unsigned) cfg->x_last_basic_block >= old_len)
{
new_len = cfg->x_last_basic_block + (cfg->x_last_basic_block + 3) / 4;
- VEC_safe_grow (basic_block, gc, cfg->x_basic_block_info, new_len);
- addr = VEC_address (basic_block, cfg->x_basic_block_info);
- memset (&addr[old_len], 0, sizeof (basic_block) * (new_len - old_len));
+ VEC_safe_grow_cleared (basic_block, gc, cfg->x_basic_block_info,
+ new_len);
}
VEC_replace (basic_block, cfg->x_basic_block_info,
if (old_len <= (unsigned) uid)
{
new_len = 3 * uid / 2;
- VEC_safe_grow (basic_block, gc, cfg->x_label_to_block_map,
- new_len);
- addr = VEC_address (basic_block, cfg->x_label_to_block_map);
- memset (&addr[old_len], 0,
- sizeof (basic_block) * (new_len - old_len));
+ VEC_safe_grow_cleared (basic_block, gc,
+ cfg->x_label_to_block_map, new_len);
}
VEC_replace (basic_block, cfg->x_label_to_block_map, uid, bb);
{
add_stmt_to_eh_region_fn (dest_cfun, stmt, region + eh_offset);
remove_stmt_from_eh_region (stmt);
+ gimple_duplicate_stmt_histograms (dest_cfun, stmt, cfun, stmt);
+ gimple_remove_stmt_histograms (cfun, stmt);
}
}
}
create_bb, /* create_basic_block */
tree_redirect_edge_and_branch,/* redirect_edge_and_branch */
tree_redirect_edge_and_branch_force,/* redirect_edge_and_branch_force */
+ tree_can_remove_branch_p, /* can_remove_branch_p */
remove_bb, /* delete_basic_block */
tree_split_block, /* split_block */
tree_move_block_after, /* move_block_after */
return exp;
t = make_rename_temp (type, NULL);
- new_stmt = build2 (MODIFY_EXPR, type, t, exp);
+ new_stmt = build2_gimple (GIMPLE_MODIFY_STMT, t, exp);
orig_stmt = bsi_stmt (*bsi);
SET_EXPR_LOCUS (new_stmt, EXPR_LOCUS (orig_stmt));
TREE_BLOCK (new_stmt) = TREE_BLOCK (orig_stmt);
bsi_insert_before (bsi, new_stmt, BSI_SAME_STMT);
- if (in_ssa_p)
- mark_new_vars_to_rename (new_stmt);
+ if (gimple_in_ssa_p (cfun))
+ mark_symbols_for_renaming (new_stmt);
return t;
}