> On 6 Oct 2026, at 15:34, Richard Biener <[email protected]> wrote:
> 
> 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.
> 

Yes, the check covers the replacement as well as the match:

any_id_used = (contains_id (s->match, ids[i])
               || (s->result && contains_id (s->result, ids[i])));

The diagnostic only fires when the iterator appears in neither. If the iterator 
is used only in an inline C predicate or guard within the replacement, patch 
4/6 (which I’ve committed) ensures contains_id detects that via a CPP_NAME 
token scan, so the full expansion still proceeds correctly.

Thanks,
Kyrill

> 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)


Reply via email to