#include "cfglayout.h"
#include "hashtab.h"
#include "tree-ssa-propagate.h"
+#include "value-prof.h"
/* This file contains functions for building the Control Flow Graph (CFG)
for a function tree. */
}
/* 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. */
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);
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;
}
else
replace_uses_by (def, use);
- remove_phi_node (phi, NULL);
+ remove_phi_node (phi, NULL, false);
}
/* 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);
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)
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);
+ }
}
{
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);
}
}
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)))
{
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;
}
}
+/* 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;
+}
+
/* Verify the GIMPLE statement chain. */
void
{
tree stmt = bsi_stmt (bsi);
+ err |= verify_gimple_tuples (stmt);
+
if (bb_for_stmt (stmt) != bb)
{
error ("bb_for_stmt (stmt) is set to a wrong basic block");
internal_error ("verify_stmts failed");
htab_delete (htab);
+ 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))
{
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)
{
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);
}
}
}
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;
}