From: Richard Biener Date: Mon, 3 Nov 2025 13:04:55 +0000 (+0100) Subject: SSA immediate use iterator checking X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=e82a29a9a7e6d5a2f5e8c873ae19703048a6fcba;p=thirdparty%2Fgcc.git SSA immediate use iterator checking 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. * 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-core.h (tree_ssa_name::active_iterated_stmt, tree_ssa_name::fast_iteration_depth): New members when ENABLE_GIMPLE_CHECKING. * tree-ssanames.cc (make_ssa_name_fn): Initialize immediate use verifier bookkeeping members. --- diff --git a/gcc/ssa-iterators.h b/gcc/ssa-iterators.h index 8fcc9b8a55f..24cf6bfd63b 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; }