https://gcc.gnu.org/bugzilla/show_bug.cgi?id=122502
--- Comment #7 from Richard Biener <rguenth at gcc dot gnu.org> ---
I think this is simply "unfortunate". Iterating over SSA uses from inside
fold() is questionable - those might not even be initialized and are definitely
not kept up to date during recursive folding (so with ranger being called via
fold, it's iterating over uses is questionable).
But of course the issue is that our FOR_EACH_IMM_USE_STMT is "destructive"
to the immediate use list (it inserts a dummy marker), and we do not expect
another immediate use traversal to happen on the same SSA name within it.
Nor would any immediate use traversal expect the number of uses to change,
but in principle a
FOR_EACH_IMM_USE_STMT (...)
if (fold_stmt ())
update_stmt ();
might remove 'stmt' from the immediate use list (unsure if this would break or
not).
For checking purposes we might want to steal a flag on SSA names to indicate
whether a FOR_EACH_IMM_USE_STMT traversal is ongoing and assert on conflicting
iterations - possibly also from _FAST as to catch recursive _STMT iterations?
Only _FAST inside _FAST is OK I think.
That said, the "easiest" solution might be to do sth like
auto_vec<gimple *> uses = get_imm_use_stmts ();
for (.. : uses)
fold_stmt ();
it might look tempting to rewrite FOR_EACH_IMM_USE_STMT to always collect
a temporary vector of stmt uses first, similar as to how loop iterators
work. But that might be quite costly.
The checking code above could also detect when the immediate use list of
an SSA name that is iterated over is changed which might or might not be
"safe" (it might at least be unexpected).
That said - does ranger really need to look at immediate uses from folding
context? This on-demand filling bites back here and makes things a lot more
fragile as to at which point we have to have an absolutely consistent IL.
Maybe have a ranger->stop_fill (), ranger->start_fill () flag passes could
set around code that does IL transforms but fold()s to avoid running into
these kind of issues?