The following implements additional checking around
SSA immediate use iteration. Specifically this prevents
- any nesting of FOR_EACH_IMM_USE_STMT inside another iteration
via FOR_EACH_IMM_USE_STMT or FOR_EACH_IMM_USE_FAST when iterating
on the same SSA name
- modification (for now unlinking of immediate uses) of a SSA
immediate use list when a fast iteration of the immediate uses
of the SSA name is active
- modification (for now unlinking of immediate uses) of the immediate
use list outside of the block of uses for the currently active stmt
of an ongoing FOR_EACH_IMM_USE_STMT of the SSA name
To implement this additional bookkeeping members are put into the
SSA name structure when ENABLE_GIMPLE_CHECKING is active. I have
kept the existing consistency checking of the fast iterator.
The patch depends on the previous one removing the fake sentinel
immediate use entry. Depends only in sofar that it doesn't apply
on trunk directly at the moment.
Boostrapped and tested on x86_64-unknown-linux-gnu, ontop of
the other patches.
Any further comments? I've seen no comment on the very first
change yet which was removal of the sentinel element (to fix
the ranger interaction)?
Thanks,
Richard.
* ssa-iterators.h (imm_use_iterator::name): Add.
(delink_imm_use): When in a FOR_EACH_IMM_USE_STMT iteration
enforce we only remove uses from the current stmt.
(end_imm_use_stmt_traverse): Reset current stmt.
(first_imm_use_stmt): Assert no FOR_EACH_IMM_USE_STMT on
var is in progress. Set the current stmt.
(next_imm_use_stmt): Set the current stmt.
(auto_end_imm_use_fast_traverse): New, lower iteration
depth upon destruction.
(first_readonly_imm_use): Bump the iteration depth.
* tree-ssanames.cc (make_ssa_name_fn): Initialize
immediate use verifier bookkeeping members.
---
gcc/ssa-iterators.h | 58 +++++++++++++++++++++++++++++++++++++++++++-
gcc/tree-core.h | 4 +++
gcc/tree-ssanames.cc | 4 +++
3 files changed, 65 insertions(+), 1 deletion(-)
diff --git a/gcc/ssa-iterators.h b/gcc/ssa-iterators.h
index ccafdd80c0c..330bd224b8a 100644
--- a/gcc/ssa-iterators.h
+++ b/gcc/ssa-iterators.h
@@ -59,16 +59,40 @@ struct imm_use_iterator
/* This is the next ssa_name to visit. IMM_USE may get removed before
the next one is traversed to, so it must be cached early. */
ssa_use_operand_t *next_imm_name;
+ /* This is the SSA name iterated over. */
+ tree name;
};
/* Use this iterator when simply looking at stmts. Adding, deleting or
modifying stmts will cause this iterator to malfunction. */
+#if ! defined ENABLE_GIMPLE_CHECKING
#define FOR_EACH_IMM_USE_FAST(DEST, ITER, SSAVAR) \
for ((DEST) = first_readonly_imm_use (&(ITER), (SSAVAR)); \
!end_readonly_imm_use_p (&(ITER)); \
(void) ((DEST) = next_readonly_imm_use (&(ITER))))
+#else
+
+/* arrange to automatically call, upon descruction, with a given pointer
+ to imm_use_iterator. */
+struct auto_end_imm_use_fast_traverse
+{
+ imm_use_iterator *imm;
+ auto_end_imm_use_fast_traverse (imm_use_iterator *imm)
+ : imm (imm) {}
+ ~auto_end_imm_use_fast_traverse ()
+ { imm->name->ssa_name.fast_iteration_depth--; }
+};
+
+#define FOR_EACH_IMM_USE_FAST(DEST, ITER, SSAVAR) \
+ for (struct auto_end_imm_use_fast_traverse \
+ auto_end_imm_use_fast_traverse \
+ ((((DEST) = first_readonly_imm_use (&(ITER), (SSAVAR))), \
+ &(ITER))); \
+ !end_readonly_imm_use_p (&(ITER)); \
+ (void) ((DEST) = next_readonly_imm_use (&(ITER))))
+#endif
/* Forward declare for use in the class below. */
inline void end_imm_use_stmt_traverse (imm_use_iterator *);
@@ -251,6 +275,20 @@ delink_imm_use (ssa_use_operand_t *linknode)
if (linknode->prev == NULL)
return;
+#if defined ENABLE_GIMPLE_CHECKING
+ if (linknode->loc.stmt
+ /* update_stmt on constant/removed uses. */
+ && USE_FROM_PTR (linknode)
+ && TREE_CODE (USE_FROM_PTR (linknode)) == SSA_NAME)
+ {
+ tree var = USE_FROM_PTR (linknode);
+ gcc_assert (var->ssa_name.fast_iteration_depth == 0
+ && (var->ssa_name.active_iterated_stmt == NULL
+ || (var->ssa_name.active_iterated_stmt
+ == linknode->loc.stmt)));
+ }
+#endif
+
linknode->prev->next = linknode->next;
linknode->next->prev = linknode->prev;
linknode->prev = NULL;
@@ -349,9 +387,13 @@ end_readonly_imm_use_p (const imm_use_iterator *imm)
inline use_operand_p
first_readonly_imm_use (imm_use_iterator *imm, tree var)
{
+#if defined ENABLE_GIMPLE_CHECKING
+ var->ssa_name.fast_iteration_depth++;
+#endif
imm->end_p = &(SSA_NAME_IMM_USE_NODE (var));
imm->imm_use = imm->end_p->next;
imm->next_stmt_use = imm->imm_use->next;
+ imm->name = var;
if (end_readonly_imm_use_p (imm))
return NULL_USE_OPERAND_P;
return imm->imm_use;
@@ -846,8 +888,11 @@ end_imm_use_stmt_p (const imm_use_iterator *imm)
placeholder node from the list. */
inline void
-end_imm_use_stmt_traverse (imm_use_iterator *)
+end_imm_use_stmt_traverse (imm_use_iterator * ARG_UNUSED (imm))
{
+#if defined ENABLE_GIMPLE_CHECKING
+ imm->name->ssa_name.active_iterated_stmt = NULL;
+#endif
}
/* Immediate use traversal of uses within a stmt require that all the
@@ -923,6 +968,10 @@ link_use_stmts_after (use_operand_p head, imm_use_iterator
*)
inline gimple *
first_imm_use_stmt (imm_use_iterator *imm, tree var)
{
+#if defined ENABLE_GIMPLE_CHECKING
+ gcc_assert (var->ssa_name.active_iterated_stmt == NULL
+ && var->ssa_name.fast_iteration_depth == 0);
+#endif
imm->end_p = &(SSA_NAME_IMM_USE_NODE (var));
imm->imm_use = imm->end_p->next;
imm->next_imm_name = NULL_USE_OPERAND_P;
@@ -930,12 +979,16 @@ first_imm_use_stmt (imm_use_iterator *imm, tree var)
/* next_stmt_use is used to point to the immediate use node after
the set of uses for the current stmt. */
imm->next_stmt_use = NULL_USE_OPERAND_P;
+ imm->name = var;
if (end_imm_use_stmt_p (imm))
return NULL;
imm->next_stmt_use = link_use_stmts_after (imm->imm_use, imm)->next;
+#if defined ENABLE_GIMPLE_CHECKING
+ var->ssa_name.active_iterated_stmt = USE_STMT (imm->imm_use);
+#endif
return USE_STMT (imm->imm_use);
}
@@ -948,6 +1001,9 @@ next_imm_use_stmt (imm_use_iterator *imm)
if (end_imm_use_stmt_p (imm))
return NULL;
+#if defined ENABLE_GIMPLE_CHECKING
+ imm->name->ssa_name.active_iterated_stmt = USE_STMT (imm->imm_use);
+#endif
imm->next_stmt_use = link_use_stmts_after (imm->imm_use, imm)->next;
return USE_STMT (imm->imm_use);
}
diff --git a/gcc/tree-core.h b/gcc/tree-core.h
index 145e758600e..a6e40c7497f 100644
--- a/gcc/tree-core.h
+++ b/gcc/tree-core.h
@@ -1717,6 +1717,10 @@ struct GTY(()) tree_ssa_name {
"!POINTER_TYPE_P (TREE_TYPE ((tree)&%1)) : 2"))) info;
/* Immediate uses list for this SSA_NAME. */
struct ssa_use_operand_t imm_uses;
+#if defined ENABLE_GIMPLE_CHECKING
+ gimple *active_iterated_stmt;
+ unsigned fast_iteration_depth;
+#endif
};
struct GTY(()) phi_arg_d {
diff --git a/gcc/tree-ssanames.cc b/gcc/tree-ssanames.cc
index dcf8da56272..3d915738c98 100644
--- a/gcc/tree-ssanames.cc
+++ b/gcc/tree-ssanames.cc
@@ -406,6 +406,10 @@ make_ssa_name_fn (struct function *fn, tree var, gimple
*stmt,
SSA_NAME_IN_FREE_LIST (t) = 0;
SSA_NAME_IS_DEFAULT_DEF (t) = 0;
init_ssa_name_imm_use (t);
+#if defined ENABLE_GIMPLE_CHECKING
+ t->ssa_name.active_iterated_stmt = NULL;
+ t->ssa_name.fast_iteration_depth = 0;
+#endif
return t;
}
--
2.51.0