On Tue, 6 Oct 2026, Kyrylo Tkachov wrote:
>
>
> > On 6 Oct 2026, at 13:59, Richard Biener <[email protected]> wrote:
> >
> > On Tue, 6 Oct 2026, [email protected] wrote:
> >
> >> From: Kyrylo Tkachov <[email protected]>
> >>
> >> lower_for replicates each pattern once per operator of each for-level,
> >> substituting the operator into the match and result. When a pattern
> >> does not reference any of the for-level iterators in either its match
> >> or result, every substituted copy is structurally identical, producing
> >> dead leaves in the decision tree.
> >>
> >> Since f6eb8291e1c (PR119196, 2025-07-09), match.pd:6638 has a
> >> (for lop ...) pattern nested inside a (for op ...) whose 34-operator
> >> list it does not use. lower_for therefore emits 34 identical copies of
> >> each of the three lop alternatives per GIMPLE and GENERIC IL.
> >>
> >> Before proceeding through the operator substitution loop, check whether
> >> any id in the current for-level appears in the pattern's match or
> >> result. If none do, a single copy with j=0 operator values suffices
> >> and the remaining max_n_opers-1 iterations are skipped.
> >>
> >> Bootstrapped and tested on aarch64-none-linux-gnu.
> >> Ok for trunk?
> >
> > Might there be any valid uses of such case? It looks like the pattern
> > in question should be simply moved out of the enclosing (for ...).
> >
> > That said, this should emit an unconditional diagnostic from genmatch.
> >
> > Can you re-post with such a change (and move the pattern)?
> >
>
> Yeah, that works.
> Does this version look ok?
Looking I wonder what happens to a non-sensical case like
(for opA (plus minus)
(for opB (minus minus)
(simplify (opB @0 @1)
(if (opA == minus)
(opA @0 @1)))))
so whether this should be an error instead? ISTR we did have
sth like
(for icmp (tcc_comparison)
(for cmp (tcc_comparison)
(simplify (bit_not (cmp @0 @1))
(with
{
enum tree_code icmpc = invert_tree_comparison (...);
}
(if (icmpc == icmp)
(icmp @0 @1))))
or so, but we can now handle this better thanks to Andrew. But in
general not all such cases might be fixed, so do we need to verify
the iterator isn't used in the replacement as well? For the above
case a diagnostic would be still OK since we now have the extended
(with ...) syntax that can avoid the outer iteration.
Richard.
> Thanks,
> Kyrill
>
>
> > Thanks,
> > Richard.
> >
> >> Thanks,
> >> Kyrill
> >>
> >> gcc/ChangeLog:
> >>
> >> * genmatch.cc (lower_for): Skip replicated substitutions when no
> >> for-level iterator appears in the pattern.
> >>
> >> Signed-off-by: Kyrylo Tkachov <[email protected]>
> >> ---
> >> gcc/genmatch.cc | 8 +++++++-
> >> 1 file changed, 7 insertions(+), 1 deletion(-)
> >>
> >> diff --git a/gcc/genmatch.cc b/gcc/genmatch.cc
> >> index 9bb7cbbb427..1d53283e094 100644
> >> --- a/gcc/genmatch.cc
> >> +++ b/gcc/genmatch.cc
> >> @@ -2433,7 +2433,13 @@ lower_for (simplify *sin, vec<simplify *>&
> >> simplifiers)
> >> for (unsigned si = worklist_start; si < worklist_end; ++si)
> >> {
> >> simplify *s = worklist[si];
> >> - for (unsigned j = 0; j < max_n_opers; ++j)
> >> + /* If none of the for-level ids appear in this pattern's match or
> >> + result, all operator substitutions are no-ops. Emit one copy. */
> >> + bool any_id_used = false;
> >> + for (unsigned i = 0; i < n_ids && !any_id_used; ++i)
> >> + any_id_used = (contains_id (s->match, ids[i])
> >> + || (s->result && contains_id (s->result, ids[i])));
> >> + for (unsigned j = 0; j < (any_id_used ? max_n_opers : 1u); ++j)
> >> {
> >> operand *match_op = s->match;
> >> operand *result_op = s->result;
> >>
> >
> > --
> > Richard Biener <[email protected]>
> > SUSE Software Solutions Germany GmbH,
> > Frankenstrasse 146, 90461 Nuernberg, Germany;
> > GF: Stefan Gaiser, Jochen Jaser, Abhinav Puri; (HRB 36809, AG Nuernberg)
>
>
>
--
Richard Biener <[email protected]>
SUSE Software Solutions Germany GmbH,
Frankenstrasse 146, 90461 Nuernberg, Germany;
GF: Stefan Gaiser, Jochen Jaser, Abhinav Puri; (HRB 36809, AG Nuernberg)