aboutsummaryrefslogtreecommitdiff
path: root/gcc/tree-ssa-operands.c
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/tree-ssa-operands.c')
-rw-r--r--gcc/tree-ssa-operands.c461
1 files changed, 380 insertions, 81 deletions
diff --git a/gcc/tree-ssa-operands.c b/gcc/tree-ssa-operands.c
index ac5f6075f74..df968699833 100644
--- a/gcc/tree-ssa-operands.c
+++ b/gcc/tree-ssa-operands.c
@@ -124,7 +124,6 @@ tree check_build_stmt;
#endif
def_operand_p NULL_DEF_OPERAND_P = { NULL };
-use_operand_p NULL_USE_OPERAND_P = { NULL };
static void note_addressable (tree, stmt_ann_t);
static void get_expr_operands (tree, tree *, int);
@@ -160,7 +159,7 @@ allocate_use_optype (unsigned num)
{
use_optype use_ops;
unsigned size;
- size = sizeof (struct use_optype_d) + sizeof (tree *) * (num - 1);
+ size = sizeof (struct use_optype_d) + sizeof (use_operand_type_t) * (num - 1);
use_ops = ggc_alloc (size);
use_ops->num_uses = num;
return use_ops;
@@ -189,7 +188,8 @@ allocate_vuse_optype (unsigned num)
{
vuse_optype vuse_ops;
unsigned size;
- size = sizeof (struct vuse_optype_d) + sizeof (tree) * (num - 1);
+ size = sizeof (struct vuse_optype_d)
+ + sizeof (vuse_operand_type_t) * (num - 1);
vuse_ops = ggc_alloc (size);
vuse_ops->num_vuses = num;
return vuse_ops;
@@ -217,6 +217,10 @@ free_uses (use_optype *uses)
{
if (*uses)
{
+ unsigned int x;
+ use_optype use = *uses;
+ for (x = 0; x < use->num_uses; x++)
+ delink_imm_use (&(use->uses[x]));
ggc_free (*uses);
*uses = NULL;
}
@@ -243,6 +247,10 @@ free_vuses (vuse_optype *vuses)
{
if (*vuses)
{
+ unsigned int x;
+ vuse_optype vuse = *vuses;
+ for (x = 0; x < vuse->num_vuses; x++)
+ delink_imm_use (&(vuse->vuses[x].imm_use));
ggc_free (*vuses);
*vuses = NULL;
}
@@ -256,6 +264,10 @@ free_v_may_defs (v_may_def_optype *v_may_defs)
{
if (*v_may_defs)
{
+ unsigned int x;
+ v_may_def_optype v_may_def = *v_may_defs;
+ for (x = 0; x < v_may_def->num_v_may_defs; x++)
+ delink_imm_use (&(v_may_def->v_may_defs[x].imm_use));
ggc_free (*v_may_defs);
*v_may_defs = NULL;
}
@@ -305,6 +317,43 @@ fini_ssa_operands (void)
build_v_must_defs = NULL;
}
+/* Initialize V_USES index INDEX to VAL for STMT. If OLD is present, preserve
+ the position of the may-def in the immediate_use list. */
+
+static inline void
+initialize_vuse_operand (vuse_optype vuses, unsigned int index, tree val,
+ tree stmt, ssa_imm_use_t *old)
+{
+ vuse_operand_type_t *ptr;
+ ptr = &(vuses->vuses[index]);
+ ptr->use = val;
+ ptr->imm_use.use = &(ptr->use);
+ if (old)
+ relink_imm_use_stmt (&(ptr->imm_use), old, stmt);
+ else
+ link_imm_use_stmt (&(ptr->imm_use), ptr->use, stmt);
+}
+
+
+/* Initialize V_MAY_DEF_OPS index X to be DEF = MAY_DEF <USE> for STMT. If
+ OLD is present, preserve the position of the may-def in the immediate_use
+ list. */
+
+static inline void
+initialize_v_may_def_operand (v_may_def_optype v_may_def_ops, unsigned int x,
+ tree def, tree use, tree stmt, ssa_imm_use_t *old)
+{
+ v_may_def_operand_type_t *ptr;
+ ptr = &(v_may_def_ops->v_may_defs[x]);
+ ptr->def = def;
+ ptr->use = use;
+ ptr->imm_use.use = &(ptr->use);
+ if (old)
+ relink_imm_use_stmt (&(ptr->imm_use), old, stmt);
+ else
+ link_imm_use_stmt (&(ptr->imm_use), ptr->use, stmt);
+}
+
/* All the finalize_ssa_* routines do the work required to turn the build_
VARRAY into an operand_vector of the appropriate type. The original vector,
@@ -315,7 +364,7 @@ fini_ssa_operands (void)
/* Return a new def operand vector for STMT, comparing to OLD_OPS_P. */
static def_optype
-finalize_ssa_defs (def_optype *old_ops_p, tree stmt ATTRIBUTE_UNUSED)
+finalize_ssa_defs (def_optype *old_ops_p, tree stmt)
{
unsigned num, x;
def_optype def_ops, old_ops;
@@ -326,13 +375,13 @@ finalize_ssa_defs (def_optype *old_ops_p, tree stmt ATTRIBUTE_UNUSED)
return NULL;
/* There should only be a single real definition per assignment. */
- gcc_assert (TREE_CODE (stmt) != MODIFY_EXPR || num <= 1);
+ gcc_assert ((stmt && TREE_CODE (stmt) != MODIFY_EXPR) || num <= 1);
old_ops = *old_ops_p;
/* Compare old vector and new array. */
build_diff = true;
- if (old_ops && old_ops->num_defs == num)
+ if (stmt && old_ops && old_ops->num_defs == num)
{
build_diff = false;
for (x = 0; x < num; x++)
@@ -361,12 +410,41 @@ finalize_ssa_defs (def_optype *old_ops_p, tree stmt ATTRIBUTE_UNUSED)
}
+/* Make sure PTR is inn the correct immediate use list. Since uses are simply
+ pointers into the stmt TREE, there is no way of telling if anyone has
+ changed what this pointer points to via TREE_OPERANDS (exp, 0) = <...>.
+ THe contents are different, but the the pointer is still the same. This
+ routine will check to make sure PTR is in the correct list, and if it isn't
+ put it in the correct list. */
+
+static inline void
+correct_use_link (ssa_imm_use_t *ptr)
+{
+ ssa_imm_use_t *prev;
+ tree root;
+
+ prev = ptr->prev;
+ if (prev)
+ {
+ /* find the root, which has a non-NULL stmt, and a NULL use. */
+ while (prev->stmt == NULL || prev->use != NULL)
+ prev = prev->prev;
+ root = prev->stmt;
+ if (root == *(ptr->use))
+ return;
+ }
+ /* Its in the wrong list if we reach here. */
+ delink_imm_use (ptr);
+ link_imm_use (ptr, *(ptr->use));
+}
+
+
/* Return a new use operand vector for STMT, comparing to OLD_OPS_P. */
static use_optype
-finalize_ssa_uses (use_optype *old_ops_p, tree stmt ATTRIBUTE_UNUSED)
+finalize_ssa_uses (use_optype *old_ops_p, tree stmt)
{
- unsigned num, x;
+ unsigned num, x, num_old, i;
use_optype use_ops, old_ops;
bool build_diff;
@@ -386,30 +464,53 @@ finalize_ssa_uses (use_optype *old_ops_p, tree stmt ATTRIBUTE_UNUSED)
}
#endif
old_ops = *old_ops_p;
+ num_old = ((stmt && old_ops) ? old_ops->num_uses : 0);
/* Check if the old vector and the new array are the same. */
build_diff = true;
- if (old_ops && old_ops->num_uses == num)
+ if (stmt && old_ops && num_old == num)
{
build_diff = false;
for (x = 0; x < num; x++)
- if (old_ops->uses[x].use != VARRAY_TREE_PTR (build_uses, x))
- {
- build_diff = true;
- break;
- }
+ {
+ tree *var_p = VARRAY_TREE_PTR (build_uses, x);
+ tree *node = old_ops->uses[x].use;
+ /* Check the pointer values to see if they are the same. */
+ if (node != var_p)
+ {
+ build_diff = true;
+ break;
+ }
+ }
}
if (!build_diff)
{
use_ops = old_ops;
*old_ops_p = NULL;
+ for (i = 0; i < num_old; i++)
+ correct_use_link (&(use_ops->uses[i]));
}
else
{
use_ops = allocate_use_optype (num);
for (x = 0; x < num ; x++)
- use_ops->uses[x].use = VARRAY_TREE_PTR (build_uses, x);
+ {
+ tree *var = VARRAY_TREE_PTR (build_uses, x);
+ use_ops->uses[x].use = var;
+ for (i = 0; i < num_old; i++)
+ {
+ ssa_imm_use_t *ptr = &(old_ops->uses[i]);
+ if (ptr->use == var)
+ {
+ relink_imm_use_stmt (&(use_ops->uses[x]), ptr, stmt);
+ correct_use_link (&(use_ops->uses[x]));
+ break;
+ }
+ }
+ if (i == num_old)
+ link_imm_use_stmt (&(use_ops->uses[x]), *var, stmt);
+ }
}
VARRAY_POP_ALL (build_uses);
@@ -420,7 +521,7 @@ finalize_ssa_uses (use_optype *old_ops_p, tree stmt ATTRIBUTE_UNUSED)
/* Return a new v_may_def operand vector for STMT, comparing to OLD_OPS_P. */
static v_may_def_optype
-finalize_ssa_v_may_defs (v_may_def_optype *old_ops_p)
+finalize_ssa_v_may_defs (v_may_def_optype *old_ops_p, tree stmt)
{
unsigned num, x, i, old_num;
v_may_def_optype v_may_def_ops, old_ops;
@@ -435,7 +536,7 @@ finalize_ssa_v_may_defs (v_may_def_optype *old_ops_p)
/* Check if the old vector and the new array are the same. */
build_diff = true;
- if (old_ops && old_ops->num_v_may_defs == num)
+ if (stmt && old_ops && old_ops->num_v_may_defs == num)
{
old_num = num;
build_diff = false;
@@ -458,6 +559,8 @@ finalize_ssa_v_may_defs (v_may_def_optype *old_ops_p)
{
v_may_def_ops = old_ops;
*old_ops_p = NULL;
+ for (x = 0; x < num; x++)
+ correct_use_link (&(v_may_def_ops->v_may_defs[x].imm_use));
}
else
{
@@ -473,14 +576,18 @@ finalize_ssa_v_may_defs (v_may_def_optype *old_ops_p)
result = SSA_NAME_VAR (result);
if (result == var)
{
- v_may_def_ops->v_may_defs[x] = old_ops->v_may_defs[i];
+ initialize_v_may_def_operand (v_may_def_ops, x,
+ old_ops->v_may_defs[i].def,
+ old_ops->v_may_defs[i].use,
+ stmt,
+ &(old_ops->v_may_defs[i].imm_use));
break;
}
}
if (i == old_num)
{
- v_may_def_ops->v_may_defs[x].def = var;
- v_may_def_ops->v_may_defs[x].use = var;
+ initialize_v_may_def_operand (v_may_def_ops, x, var, var, stmt,
+ NULL);
}
}
}
@@ -494,7 +601,7 @@ finalize_ssa_v_may_defs (v_may_def_optype *old_ops_p)
/* Return a new vuse operand vector, comparing to OLD_OPS_P. */
static vuse_optype
-finalize_ssa_vuses (vuse_optype *old_ops_p)
+finalize_ssa_vuses (vuse_optype *old_ops_p, tree stmt)
{
unsigned num, x, i, num_v_may_defs, old_num;
vuse_optype vuse_ops, old_ops;
@@ -568,14 +675,14 @@ finalize_ssa_vuses (vuse_optype *old_ops_p)
/* Determine whether vuses is the same as the old vector. */
build_diff = true;
- if (old_ops && old_ops->num_vuses == num)
+ if (stmt && old_ops && old_ops->num_vuses == num)
{
old_num = num;
build_diff = false;
for (x = 0; x < num ; x++)
{
tree v;
- v = old_ops->vuses[x];
+ v = old_ops->vuses[x].use;
if (TREE_CODE (v) == SSA_NAME)
v = SSA_NAME_VAR (v);
if (v != VARRAY_TREE (build_vuses, x))
@@ -592,6 +699,8 @@ finalize_ssa_vuses (vuse_optype *old_ops_p)
{
vuse_ops = old_ops;
*old_ops_p = NULL;
+ for (x = 0; x < num; x++)
+ correct_use_link (&(vuse_ops->vuses[x].imm_use));
}
else
{
@@ -602,17 +711,18 @@ finalize_ssa_vuses (vuse_optype *old_ops_p)
/* Look for VAR in the old vector, and use that SSA_NAME. */
for (i = 0; i < old_num; i++)
{
- result = old_ops->vuses[i];
+ result = old_ops->vuses[i].use;
if (TREE_CODE (result) == SSA_NAME)
result = SSA_NAME_VAR (result);
if (result == var)
{
- vuse_ops->vuses[x] = old_ops->vuses[i];
+ initialize_vuse_operand (vuse_ops, x, old_ops->vuses[i].use,
+ stmt, &(old_ops->vuses[i].imm_use));
break;
}
}
if (i == old_num)
- vuse_ops->vuses[x] = var;
+ initialize_vuse_operand (vuse_ops, x, var, stmt, NULL);
}
}
@@ -627,8 +737,7 @@ finalize_ssa_vuses (vuse_optype *old_ops_p)
/* Return a new v_must_def operand vector for STMT, comparing to OLD_OPS_P. */
static v_must_def_optype
-finalize_ssa_v_must_defs (v_must_def_optype *old_ops_p,
- tree stmt ATTRIBUTE_UNUSED)
+finalize_ssa_v_must_defs (v_must_def_optype *old_ops_p, tree stmt)
{
unsigned num, x, i, old_num = 0;
v_must_def_optype v_must_def_ops, old_ops;
@@ -639,13 +748,13 @@ finalize_ssa_v_must_defs (v_must_def_optype *old_ops_p,
return NULL;
/* There should only be a single V_MUST_DEF per assignment. */
- gcc_assert (TREE_CODE (stmt) != MODIFY_EXPR || num <= 1);
+ gcc_assert ((stmt && TREE_CODE (stmt) != MODIFY_EXPR) || num <= 1);
old_ops = *old_ops_p;
/* Check if the old vector and the new array are the same. */
build_diff = true;
- if (old_ops && old_ops->num_v_must_defs == num)
+ if (stmt && old_ops && old_ops->num_v_must_defs == num)
{
old_num = num;
build_diff = false;
@@ -707,8 +816,9 @@ finalize_ssa_stmt_operands (tree stmt, stmt_operands_p old_ops,
new_ops->use_ops = finalize_ssa_uses (&(old_ops->use_ops), stmt);
new_ops->v_must_def_ops
= finalize_ssa_v_must_defs (&(old_ops->v_must_def_ops), stmt);
- new_ops->v_may_def_ops = finalize_ssa_v_may_defs (&(old_ops->v_may_def_ops));
- new_ops->vuse_ops = finalize_ssa_vuses (&(old_ops->vuse_ops));
+ new_ops->v_may_def_ops
+ = finalize_ssa_v_may_defs (&(old_ops->v_may_def_ops), stmt);
+ new_ops->vuse_ops = finalize_ssa_vuses (&(old_ops->vuse_ops), stmt);
}
@@ -790,46 +900,15 @@ append_v_must_def (tree var)
VARRAY_PUSH_TREE (build_v_must_defs, var);
}
-/* Create an operands cache for STMT, returning it in NEW_OPS. OLD_OPS are the
- original operands, and if ANN is non-null, appropriate stmt flags are set
- in the stmt's annotation. Note that some fields in old_ops may
- change to NULL, although none of the memory they originally pointed to
- will be destroyed. It is appropriate to call free_stmt_operands() on
- the value returned in old_ops.
-
- The rationale for this: Certain optimizations wish to examine the difference
- between new_ops and old_ops after processing. If a set of operands don't
- change, new_ops will simply assume the pointer in old_ops, and the old_ops
- pointer will be set to NULL, indicating no memory needs to be cleared.
- Usage might appear something like:
- old_ops_copy = old_ops = stmt_ann(stmt)->operands;
- build_ssa_operands (stmt, NULL, &old_ops, &new_ops);
- <* compare old_ops_copy and new_ops *>
- free_ssa_operands (old_ops); */
+/* Parse STMT looking for operands. OLD_OPS is the original stmt operand
+ cache for STMT, if it exested before. When fniished, the various build_*
+ operand vectors will have potential operands. in them. */
-void
-build_ssa_operands (tree stmt, stmt_ann_t ann, stmt_operands_p old_ops,
- stmt_operands_p new_ops)
+static void
+parse_ssa_operands (tree stmt)
{
enum tree_code code;
- tree_ann_t saved_ann = stmt->common.ann;
-
- /* Replace stmt's annotation with the one passed in for the duration
- of the operand building process. This allows "fake" stmts to be built
- and not be included in other data structures which can be built here. */
- stmt->common.ann = (tree_ann_t) ann;
-
- /* Initially assume that the statement has no volatile operands, nor
- makes aliased loads or stores. */
- if (ann)
- {
- ann->has_volatile_ops = false;
- ann->makes_aliased_stores = false;
- ann->makes_aliased_loads = false;
- }
-
- start_ssa_stmt_operands ();
code = TREE_CODE (stmt);
switch (code)
@@ -894,8 +973,58 @@ build_ssa_operands (tree stmt, stmt_ann_t ann, stmt_operands_p old_ops,
get_expr_operands (stmt, &stmt, opf_none);
break;
}
+}
+
+/* Create an operands cache for STMT, returning it in NEW_OPS. OLD_OPS are the
+ original operands, and if ANN is non-null, appropriate stmt flags are set
+ in the stmt's annotation. If ANN is NULL, this is not considered a "real"
+ stmt, and none of the operands will be entered into their respective
+ immediate uses tables. This is to allow stmts to be processed when they
+ are not actually in the CFG.
+
+ Note that some fields in old_ops may change to NULL, although none of the
+ memory they originally pointed to will be destroyed. It is appropriate
+ to call free_stmt_operands() on the value returned in old_ops.
+
+ The rationale for this: Certain optimizations wish to examine the difference
+ between new_ops and old_ops after processing. If a set of operands don't
+ change, new_ops will simply assume the pointer in old_ops, and the old_ops
+ pointer will be set to NULL, indicating no memory needs to be cleared.
+ Usage might appear something like:
+
+ old_ops_copy = old_ops = stmt_ann(stmt)->operands;
+ build_ssa_operands (stmt, NULL, &old_ops, &new_ops);
+ <* compare old_ops_copy and new_ops *>
+ free_ssa_operands (old_ops); */
- finalize_ssa_stmt_operands (stmt, old_ops, new_ops);
+void
+build_ssa_operands (tree stmt, stmt_ann_t ann, stmt_operands_p old_ops,
+ stmt_operands_p new_ops)
+{
+ tree_ann_t saved_ann = stmt->common.ann;
+
+ /* Replace stmt's annotation with the one passed in for the duration
+ of the operand building process. This allows "fake" stmts to be built
+ and not be included in other data structures which can be built here. */
+ stmt->common.ann = (tree_ann_t) ann;
+
+ /* Initially assume that the statement has no volatile operands, nor
+ makes aliased loads or stores. */
+ if (ann)
+ {
+ ann->has_volatile_ops = false;
+ ann->makes_aliased_stores = false;
+ ann->makes_aliased_loads = false;
+ }
+
+ start_ssa_stmt_operands ();
+
+ parse_ssa_operands (stmt);
+
+ if (ann)
+ finalize_ssa_stmt_operands (stmt, old_ops, new_ops);
+ else
+ finalize_ssa_stmt_operands (NULL, old_ops, new_ops);
stmt->common.ann = saved_ann;
}
@@ -920,14 +1049,18 @@ free_ssa_operands (stmt_operands_p ops)
/* Get the operands of statement STMT. Note that repeated calls to
get_stmt_operands for the same statement will do nothing until the
- statement is marked modified by a call to modify_stmt(). */
+ statement is marked modified by a call to mark_stmt_modified(). */
void
-get_stmt_operands (tree stmt)
+update_stmt_operands (tree stmt)
{
stmt_ann_t ann;
stmt_operands_t old_operands;
+ /* If get_stmt_operands is called before SSA is initialized, dont
+ do anything. */
+ if (build_defs == NULL)
+ return;
/* The optimizers cannot handle statements that are nothing but a
_DECL. This indicates a bug in the gimplifier. */
gcc_assert (!SSA_VAR_P (stmt));
@@ -938,9 +1071,7 @@ get_stmt_operands (tree stmt)
ann = get_stmt_ann (stmt);
- /* If the statement has not been modified, the operands are still valid. */
- if (!ann->modified)
- return;
+ gcc_assert (ann->modified);
timevar_push (TV_TREE_OPS);
@@ -952,7 +1083,7 @@ get_stmt_operands (tree stmt)
/* Clear the modified bit for STMT. Subsequent calls to
get_stmt_operands for this statement will do nothing until the
- statement is marked modified by a call to modify_stmt(). */
+ statement is marked modified by a call to mark_stmt_modified(). */
ann->modified = 0;
timevar_pop (TV_TREE_OPS);
@@ -1704,7 +1835,7 @@ copy_virtual_operands (tree dst, tree src)
{
*vuses_new = allocate_vuse_optype (NUM_VUSES (vuses));
for (i = 0; i < NUM_VUSES (vuses); i++)
- SET_VUSE_OP (*vuses_new, i, VUSE_OP (vuses, i));
+ initialize_vuse_operand (*vuses_new, i, VUSE_OP (vuses, i), dst, NULL);
}
if (v_may_defs)
@@ -1712,15 +1843,17 @@ copy_virtual_operands (tree dst, tree src)
*v_may_defs_new = allocate_v_may_def_optype (NUM_V_MAY_DEFS (v_may_defs));
for (i = 0; i < NUM_V_MAY_DEFS (v_may_defs); i++)
{
- SET_V_MAY_DEF_OP (*v_may_defs_new, i, V_MAY_DEF_OP (v_may_defs, i));
- SET_V_MAY_DEF_RESULT (*v_may_defs_new, i,
- V_MAY_DEF_RESULT (v_may_defs, i));
+ initialize_v_may_def_operand (*v_may_defs_new, i,
+ V_MAY_DEF_RESULT (v_may_defs, i),
+ V_MAY_DEF_OP (v_may_defs, i), dst,
+ NULL);
}
}
if (v_must_defs)
{
- *v_must_defs_new = allocate_v_must_def_optype (NUM_V_MUST_DEFS (v_must_defs));
+ *v_must_defs_new
+ = allocate_v_must_def_optype (NUM_V_MUST_DEFS (v_must_defs));
for (i = 0; i < NUM_V_MUST_DEFS (v_must_defs); i++)
SET_V_MUST_DEF_OP (*v_must_defs_new, i, V_MUST_DEF_OP (v_must_defs, i));
}
@@ -1768,7 +1901,173 @@ create_ssa_artficial_load_stmt (stmt_operands_p old_ops, tree new_stmt)
}
/* Now set the vuses for this new stmt. */
- ann->operands.vuse_ops = finalize_ssa_vuses (&(tmp.vuse_ops));
+ ann->operands.vuse_ops = finalize_ssa_vuses (&(tmp.vuse_ops), NULL);
+}
+
+
+
+/* Issue immediate use error for VAR to debug file F. */
+static void
+verify_abort (FILE *f, ssa_imm_use_t *var)
+{
+ tree stmt;
+ stmt = var->stmt;
+ if (stmt)
+ {
+ if (stmt_modified_p(stmt))
+ {
+ fprintf (f, " STMT MODIFIED. - <0x%x> ", (unsigned int)stmt);
+ print_generic_stmt (f, stmt, TDF_SLIM);
+ }
+ }
+ fprintf (f, " IMM ERROR : (use_p : tree: 0x%X:0x%x)", (unsigned int)var,
+ (unsigned int)var->use);
+ print_generic_expr (f, USE_FROM_PTR (var), TDF_SLIM);
+ fprintf(f, "\n");
+}
+
+
+/* Scan the immediate_use list for VAR making sure its linked properly.
+ return RTUE iof there is a problem. */
+
+bool
+verify_imm_links (FILE *f, tree var)
+{
+ ssa_imm_use_t *ptr, *prev;
+ ssa_imm_use_t *list;
+ int count;
+
+ gcc_assert (TREE_CODE (var) == SSA_NAME);
+
+ list = &(SSA_NAME_IMM_USE_NODE (var));
+ gcc_assert (list->use == NULL);
+
+ if (list->prev == NULL)
+ {
+ gcc_assert (list->next == NULL);
+ return false;
+ }
+
+ prev = list;
+ count = 0;
+ for (ptr = list->next; ptr != list; )
+ {
+ if (prev != ptr->prev)
+ {
+ verify_abort (f, ptr);
+ return true;
+ }
+
+ if (ptr->use == NULL)
+ {
+ verify_abort (f, ptr); /* 2 roots, or SAFE guard node. */
+ return true;
+ }
+ else
+ if (*(ptr->use) != var)
+ {
+ verify_abort (f, ptr);
+ return true;
+ }
+
+ prev = ptr;
+ ptr = ptr->next;
+ /* Avoid infinite loops. */
+ if (count++ > 30000)
+ {
+ verify_abort (f, ptr);
+ return true;
+ }
+ }
+
+ /* Verify list in the other direction. */
+ prev = list;
+ for (ptr = list->prev; ptr != list; )
+ {
+ if (prev != ptr->next)
+ {
+ verify_abort (f, ptr);
+ return true;
+ }
+ prev = ptr;
+ ptr = ptr->prev;
+ if (count-- < 0)
+ {
+ verify_abort (f, ptr);
+ return true;
+ }
+ }
+
+ if (count != 0)
+ {
+ verify_abort (f, ptr);
+ return true;
+ }
+
+ return false;
+}
+
+
+/* Dump all the immediate uses to FILE. */
+
+void
+dump_immediate_uses_for (FILE *file, tree var)
+{
+ imm_use_iterator iter;
+ use_operand_p use_p;
+
+ gcc_assert (var && TREE_CODE (var) == SSA_NAME);
+
+ print_generic_expr (file, var, TDF_SLIM);
+ fprintf (file, " : -->");
+ if (has_zero_uses (var))
+ fprintf (file, " no uses.\n");
+ else
+ if (has_single_use (var))
+ fprintf (file, " single use.\n");
+ else
+ fprintf (file, "%d uses.\n", num_imm_uses (var));
+
+ FOR_EACH_IMM_USE_FAST (use_p, iter, var)
+ {
+ print_generic_stmt (file, USE_STMT (use_p), TDF_SLIM);
+ }
+ fprintf(file, "\n");
+}
+
+/* Dump all the immediate uses to FILE. */
+
+void
+dump_immediate_uses (FILE *file)
+{
+ tree var;
+ unsigned int x;
+
+ fprintf (file, "Immediate_uses: \n\n");
+ for (x = 1; x < num_ssa_names; x++)
+ {
+ var = ssa_name(x);
+ if (!var)
+ continue;
+ dump_immediate_uses_for (file, var);
+ }
+}
+
+
+/* Dump def-use edges on stderr. */
+
+void
+debug_immediate_uses (void)
+{
+ dump_immediate_uses (stderr);
+}
+
+/* Dump def-use edges on stderr. */
+
+void
+debug_immediate_uses_for (tree var)
+{
+ dump_immediate_uses_for (stderr, var);
}
#include "gt-tree-ssa-operands.h"