#include "tree-inline.h"
#include "varray.h"
#include "timevar.h"
-#include "tree-alias-common.h"
#include "hashtab.h"
#include "tree-dump.h"
#include "tree-pass.h"
{
error ("SSA_NAME_DEF_STMT is wrong");
fprintf (stderr, "Expected definition statement:\n");
- debug_generic_stmt (SSA_NAME_DEF_STMT (ssa_name));
+ print_generic_stmt (stderr, SSA_NAME_DEF_STMT (ssa_name), TDF_VOPS);
fprintf (stderr, "\nActual definition statement:\n");
- debug_generic_stmt (stmt);
+ print_generic_stmt (stderr, stmt, TDF_VOPS);
goto err;
}
fprintf (stderr, "while verifying SSA_NAME ");
print_generic_expr (stderr, ssa_name, 0);
fprintf (stderr, " in statement\n");
- debug_generic_stmt (stmt);
+ print_generic_stmt (stderr, stmt, TDF_VOPS);
return true;
}
arguments).
IS_VIRTUAL is true if SSA_NAME is created by a V_MAY_DEF or a
- V_MUST_DEF. */
+ V_MUST_DEF.
+
+ If NAMES_DEFINED_IN_BB is not NULL, it contains a bitmap of ssa names
+ that are defined before STMT in basic block BB. */
static bool
verify_use (basic_block bb, basic_block def_bb, tree ssa_name,
- tree stmt, bool check_abnormal, bool is_virtual)
+ tree stmt, bool check_abnormal, bool is_virtual,
+ bitmap names_defined_in_bb)
{
bool err = false;
def_bb->index, bb->index);
err = true;
}
+ else if (bb == def_bb
+ && names_defined_in_bb != NULL
+ && !bitmap_bit_p (names_defined_in_bb, SSA_NAME_VERSION (ssa_name)))
+ {
+ error ("Definition in block %i follows the use", def_bb->index);
+ err = true;
+ }
if (check_abnormal
&& !SSA_NAME_OCCURS_IN_ABNORMAL_PHI (ssa_name))
if (err)
{
fprintf (stderr, "for SSA_NAME: ");
- debug_generic_expr (ssa_name);
+ print_generic_expr (stderr, ssa_name, TDF_VOPS);
fprintf (stderr, "in statement:\n");
- debug_generic_stmt (stmt);
+ print_generic_stmt (stderr, stmt, TDF_VOPS);
}
return err;
if (TREE_CODE (op) == SSA_NAME)
err = verify_use (e->src, definition_block[SSA_NAME_VERSION (op)], op,
phi, e->flags & EDGE_ABNORMAL,
- !is_gimple_reg (PHI_RESULT (phi)));
+ !is_gimple_reg (PHI_RESULT (phi)),
+ NULL);
if (e->dest != bb)
{
if (err)
{
fprintf (stderr, "PHI argument\n");
- debug_generic_stmt (op);
+ print_generic_stmt (stderr, op, TDF_VOPS);
goto error;
}
if (err)
{
fprintf (stderr, "for PHI node\n");
- debug_generic_stmt (phi);
+ print_generic_stmt (stderr, phi, TDF_VOPS);
}
struct ptr_info_def *pi;
ptr = ssa_name (i);
+ if (!ptr)
+ continue;
ann = var_ann (SSA_NAME_VAR (ptr));
pi = SSA_NAME_PTR_INFO (ptr);
goto err;
}
- if (pi->pt_anything && (pi->pt_malloc || pi->pt_vars))
- {
- error ("Pointers that point to anything should not point to malloc or other vars");
- goto err;
- }
-
- if (pi->pt_malloc && pi->pt_vars)
- {
- error ("Pointers pointing to malloc get a unique tag and cannot point to other vars");
- goto err;
- }
-
if (pi->name_mem_tag
&& !pi->pt_malloc
&& (pi->pt_vars == NULL
size_t j;
for (j = i + 1; j < num_ssa_names; j++)
- {
- tree ptr2 = ssa_name (j);
- struct ptr_info_def *pi2 = SSA_NAME_PTR_INFO (ptr2);
-
- if (!POINTER_TYPE_P (TREE_TYPE (ptr2)))
- continue;
-
- if (pi2
- && pi2->name_mem_tag
- && pi2->pt_vars
- && bitmap_first_set_bit (pi2->pt_vars) >= 0
- && pi->name_mem_tag != pi2->name_mem_tag
- && bitmap_equal_p (pi->pt_vars, pi2->pt_vars))
- {
- error ("Two pointers with different name tags and identical points-to sets");
- debug_variable (ptr2);
- goto err;
- }
- }
+ if (ssa_name (j))
+ {
+ tree ptr2 = ssa_name (j);
+ struct ptr_info_def *pi2 = SSA_NAME_PTR_INFO (ptr2);
+
+ if (!TREE_VISITED (ptr2) || !POINTER_TYPE_P (TREE_TYPE (ptr2)))
+ continue;
+
+ if (pi2
+ && pi2->name_mem_tag
+ && pi2->pt_vars
+ && bitmap_first_set_bit (pi2->pt_vars) >= 0
+ && pi->name_mem_tag != pi2->name_mem_tag
+ && bitmap_equal_p (pi->pt_vars, pi2->pt_vars))
+ {
+ error ("Two pointers with different name tags and identical points-to sets");
+ debug_variable (ptr2);
+ goto err;
+ }
+ }
}
}
size_t i;
basic_block bb;
basic_block *definition_block = xcalloc (num_ssa_names, sizeof (basic_block));
+ ssa_op_iter iter;
+ tree op;
+ enum dom_state orig_dom_state = dom_computed[CDI_DOMINATORS];
+ bitmap names_defined_in_bb = BITMAP_XMALLOC ();
timevar_push (TV_TREE_SSA_VERIFY);
/* Keep track of SSA names present in the IL. */
for (i = 1; i < num_ssa_names; i++)
- TREE_VISITED (ssa_name (i)) = 0;
+ if (ssa_name (i))
+ TREE_VISITED (ssa_name (i)) = 0;
calculate_dominance_info (CDI_DOMINATORS);
for (bsi = bsi_start (bb); !bsi_end_p (bsi); bsi_next (&bsi))
{
tree stmt;
- stmt_ann_t ann;
- unsigned int j;
- v_may_def_optype v_may_defs;
- v_must_def_optype v_must_defs;
- def_optype defs;
stmt = bsi_stmt (bsi);
- ann = stmt_ann (stmt);
get_stmt_operands (stmt);
- v_may_defs = V_MAY_DEF_OPS (ann);
- if (ann->makes_aliased_stores && NUM_V_MAY_DEFS (v_may_defs) == 0)
+ if (stmt_ann (stmt)->makes_aliased_stores
+ && NUM_V_MAY_DEFS (STMT_V_MAY_DEF_OPS (stmt)) == 0)
{
error ("Statement makes aliased stores, but has no V_MAY_DEFS");
- debug_generic_stmt (stmt);
+ print_generic_stmt (stderr, stmt, TDF_VOPS);
goto err;
}
- for (j = 0; j < NUM_V_MAY_DEFS (v_may_defs); j++)
+ FOR_EACH_SSA_TREE_OPERAND (op, stmt, iter, SSA_OP_VIRTUAL_DEFS)
{
- tree op = V_MAY_DEF_RESULT (v_may_defs, j);
if (verify_def (bb, definition_block, op, stmt, true))
goto err;
}
- v_must_defs = STMT_V_MUST_DEF_OPS (stmt);
- for (j = 0; j < NUM_V_MUST_DEFS (v_must_defs); j++)
+ FOR_EACH_SSA_TREE_OPERAND (op, stmt, iter, SSA_OP_DEF)
{
- tree op = V_MUST_DEF_OP (v_must_defs, j);
- if (verify_def (bb, definition_block, op, stmt, true))
- goto err;
- }
-
- defs = DEF_OPS (ann);
- for (j = 0; j < NUM_DEFS (defs); j++)
- {
- tree op = DEF_OP (defs, j);
if (verify_def (bb, definition_block, op, stmt, false))
goto err;
}
/* Verify the arguments for every PHI node in the block. */
for (phi = phi_nodes (bb); phi; phi = PHI_CHAIN (phi))
- if (verify_phi_args (phi, bb, definition_block))
- goto err;
+ {
+ if (verify_phi_args (phi, bb, definition_block))
+ goto err;
+ bitmap_set_bit (names_defined_in_bb,
+ SSA_NAME_VERSION (PHI_RESULT (phi)));
+ }
/* Now verify all the uses and vuses in every statement of the block. */
for (bsi = bsi_start (bb); !bsi_end_p (bsi); bsi_next (&bsi))
{
tree stmt = bsi_stmt (bsi);
- stmt_ann_t ann = stmt_ann (stmt);
- unsigned int j;
- vuse_optype vuses;
- v_may_def_optype v_may_defs;
- use_optype uses;
-
- vuses = VUSE_OPS (ann);
- for (j = 0; j < NUM_VUSES (vuses); j++)
+
+ FOR_EACH_SSA_TREE_OPERAND (op, stmt, iter, SSA_OP_VIRTUAL_USES)
{
- tree op = VUSE_OP (vuses, j);
if (verify_use (bb, definition_block[SSA_NAME_VERSION (op)],
- op, stmt, false, true))
+ op, stmt, false, true,
+ names_defined_in_bb))
goto err;
}
- v_may_defs = V_MAY_DEF_OPS (ann);
- for (j = 0; j < NUM_V_MAY_DEFS (v_may_defs); j++)
+ FOR_EACH_SSA_TREE_OPERAND (op, stmt, iter, SSA_OP_USE)
{
- tree op = V_MAY_DEF_OP (v_may_defs, j);
if (verify_use (bb, definition_block[SSA_NAME_VERSION (op)],
- op, stmt, false, true))
+ op, stmt, false, false,
+ names_defined_in_bb))
goto err;
}
- uses = USE_OPS (ann);
- for (j = 0; j < NUM_USES (uses); j++)
+ FOR_EACH_SSA_TREE_OPERAND (op, stmt, iter, SSA_OP_ALL_DEFS)
+ {
+ bitmap_set_bit (names_defined_in_bb, SSA_NAME_VERSION (op));
+ }
+ }
+
+ /* Verify the uses in arguments of PHI nodes at the exits from the
+ block. */
+ for (e = bb->succ; e; e = e->succ_next)
+ {
+ for (phi = phi_nodes (e->dest); phi; phi = PHI_CHAIN (phi))
{
- tree op = USE_OP (uses, j);
+ bool virtual = !is_gimple_reg (PHI_RESULT (phi));
+ op = PHI_ARG_DEF_FROM_EDGE (phi, e);
+ if (TREE_CODE (op) != SSA_NAME)
+ continue;
+
if (verify_use (bb, definition_block[SSA_NAME_VERSION (op)],
- op, stmt, false, false))
+ op, phi, false, virtual,
+ names_defined_in_bb))
goto err;
}
}
+
+ bitmap_clear (names_defined_in_bb);
}
/* Finally, verify alias information. */
verify_alias_info ();
free (definition_block);
+ /* Restore the dominance information to its prior known state, so
+ that we do not perturb the compiler's subsequent behavior. */
+ if (orig_dom_state == DOM_NONE)
+ free_dominance_info (CDI_DOMINATORS);
+ else
+ dom_computed[CDI_DOMINATORS] = orig_dom_state;
+
+ BITMAP_XFREE (names_defined_in_bb);
timevar_pop (TV_TREE_SSA_VERIFY);
return;
/* Remove annotations from every tree in the function. */
FOR_EACH_BB (bb)
for (bsi = bsi_start (bb); !bsi_end_p (bsi); bsi_next (&bsi))
- bsi_stmt (bsi)->common.ann = NULL;
+ {
+ tree stmt = bsi_stmt (bsi);
+ release_defs (stmt);
+ ggc_free (stmt->common.ann);
+ stmt->common.ann = NULL;
+ }
/* Remove annotations from every referenced variable. */
if (referenced_vars)
{
for (i = 0; i < num_referenced_vars; i++)
- referenced_var (i)->common.ann = NULL;
+ {
+ tree var = referenced_var (i);
+ ggc_free (var->common.ann);
+ var->common.ann = NULL;
+ }
referenced_vars = NULL;
}
{
tree def_stmt;
-#if defined ENABLE_CHECKING
- if (TREE_CODE (var) != SSA_NAME)
- abort ();
-#endif
+ gcc_assert (TREE_CODE (var) == SSA_NAME);
def_stmt = SSA_NAME_DEF_STMT (var);
return;
addr_var = TREE_OPERAND (repl, 0);
- while (TREE_CODE (*x) == ARRAY_REF
- || TREE_CODE (*x) == COMPONENT_REF
- || TREE_CODE (*x) == BIT_FIELD_REF)
+ while (handled_component_p (*x)
+ || TREE_CODE (*x) == REALPART_EXPR
+ || TREE_CODE (*x) == IMAGPART_EXPR)
x = &TREE_OPERAND (*x, 0);
if (TREE_CODE (*x) != INDIRECT_REF
|| TREE_OPERAND (*x, 0) != var)
return;
- modify_stmt (stmt);
if (TREE_TYPE (*x) == TREE_TYPE (addr_var))
{
*x = addr_var;
return;
}
+
/* Frontends sometimes produce expressions like *&a instead of a[0].
Create a temporary variable to handle this case. */
ass_stmt = build2 (MODIFY_EXPR, void_type_node, NULL_TREE, repl);
static void
replace_immediate_uses (tree var, tree repl)
{
- use_optype uses;
- vuse_optype vuses;
- v_may_def_optype v_may_defs;
int i, j, n;
dataflow_t df;
tree stmt;
- stmt_ann_t ann;
bool mark_new_vars;
+ ssa_op_iter iter;
+ use_operand_p use_p;
df = get_immediate_uses (SSA_NAME_DEF_STMT (var));
n = num_immediate_uses (df);
for (i = 0; i < n; i++)
{
stmt = immediate_use (df, i);
- ann = stmt_ann (stmt);
if (TREE_CODE (stmt) == PHI_NODE)
{
propagate_into_addr (stmt, var, &TREE_OPERAND (stmt, 1), repl);
}
- uses = USE_OPS (ann);
- for (j = 0; j < (int) NUM_USES (uses); j++)
- if (USE_OP (uses, j) == var)
+ FOR_EACH_SSA_USE_OPERAND (use_p, stmt, iter, SSA_OP_USE)
+ if (USE_FROM_PTR (use_p) == var)
{
- propagate_value (USE_OP_PTR (uses, j), repl);
+ propagate_value (use_p, repl);
mark_new_vars = POINTER_TYPE_P (TREE_TYPE (repl));
}
}
else
{
- vuses = VUSE_OPS (ann);
- for (j = 0; j < (int) NUM_VUSES (vuses); j++)
- if (VUSE_OP (vuses, j) == var)
- propagate_value (VUSE_OP_PTR (vuses, j), repl);
-
- v_may_defs = V_MAY_DEF_OPS (ann);
- for (j = 0; j < (int) NUM_V_MAY_DEFS (v_may_defs); j++)
- if (V_MAY_DEF_OP (v_may_defs, j) == var)
- propagate_value (V_MAY_DEF_OP_PTR (v_may_defs, j), repl);
+ FOR_EACH_SSA_USE_OPERAND (use_p, stmt, iter, SSA_OP_VIRTUAL_USES)
+ if (USE_FROM_PTR (use_p) == var)
+ propagate_value (use_p, repl);
+ }
+
+ /* FIXME. If REPL is a constant, we need to fold STMT.
+ However, fold_stmt wants a pointer to the statement, because
+ it may happen that it needs to replace the whole statement
+ with a new expression. Since the current def-use machinery
+ does not return pointers to statements, we call fold_stmt
+ with the address of a local temporary, if that call changes
+ the temporary then we fall on our swords.
+
+ Note that all this will become unnecessary soon. This
+ pass is being replaced with a proper copy propagation pass
+ for 4.1 (dnovillo, 2004-09-17). */
+ if (TREE_CODE (repl) != SSA_NAME)
+ {
+ tree tmp = stmt;
+ fold_stmt (&tmp);
+ if (tmp != stmt)
+ abort ();
}
/* If REPL is a pointer, it may have different memory tags associated
/* At least one of the arguments should not be equal to the result, or
something strange is happening. */
- if (!val)
- abort ();
+ gcc_assert (val);
if (get_eq_name (eq_to, res) == val)
return;
0, /* properties_destroyed */
0, /* todo_flags_start */
TODO_dump_func | TODO_rename_vars
- | TODO_ggc_collect | TODO_verify_ssa /* todo_flags_finish */
+ | TODO_ggc_collect | TODO_verify_ssa, /* todo_flags_finish */
+ 0 /* letter */
};
\f
/* Emit warnings for uninitialized variables. This is done in two passes.
warn_uninit (t, "%H'%D' is used uninitialized in this function", locus);
*walk_subtrees = 0;
}
- else if (DECL_P (t) || TYPE_P (t))
+ else if (IS_TYPE_OR_DECL_P (t))
*walk_subtrees = 0;
return NULL_TREE;
0, /* properties_provided */
0, /* properties_destroyed */
0, /* todo_flags_start */
- 0 /* todo_flags_finish */
+ 0, /* todo_flags_finish */
+ 0 /* letter */
};
struct tree_opt_pass pass_late_warn_uninitialized =
0, /* properties_provided */
0, /* properties_destroyed */
0, /* todo_flags_start */
- 0 /* todo_flags_finish */
+ 0, /* todo_flags_finish */
+ 0 /* letter */
};