https://gcc.gnu.org/g:5f55b86f2737a046bb3d06cae52d1c96646b84fe

commit r17-4933-g5f55b86f2737a046bb3d06cae52d1c96646b84fe
Author: Kyrylo Tkachov <[email protected]>
Date:   Mon Oct 5 22:46:52 2026 +0200

    genmatch: Share transform copies for non-delayable for-iterators
    
    When can_delay_subst is false, lower_for substitutes the for-iterator
    into both the match and the result for each operator in the list.  If
    the result does not reference the iterator, replace_id still produces a
    fresh deep copy, so every iteration holds a distinct result pointer even
    though the result trees are structurally identical.  The code generator
    then emits the transform inline once per operator, bloating the output.
    
    The existing sharing mechanism (compare_op, sinfo) already shares a
    transform across operators when can_delay_subst is true, detecting
    identical results by pointer equality.  The same mechanism works for the
    non-delayable case when the result pointer is not replaced.
    
    Guard the replace_id call on the result with contains_id: skip the copy
    when the iterator does not appear in the result.  All iterations then
    keep result_op pointing to the original s->result, compare_op returns
    true for them, and the code generator outlines the transform once.
    
    The main beneficiary is match.pd:3732 (combine_comparisons).  Since
    c7ebd58535a and bbc2517fe41 (2026-08-11), its outer (for bitop ...) list
    mixes tcc_binary and tcc_comparison codes, blocking delayed substitution.
    The result does not reference bitop, so without this fix every one of
    the 1764 worklist entries gets its own result copy and its own
    gimple_simplify_N function.  This patch reduces the generated GIMPLE
    matcher by about 1.2% and the GENERIC matcher by about 1.2%.
    
    Also fix contains_id for c_expr: the previous code checked capture_ids,
    which only tracks @N-style captures, so it always returned false for
    for-iterator names.  Replace it with a scan of the CPP_NAME tokens in
    the inline C code, matching the lookup gen_transform performs at
    code-generation time.
    
    Bootstrapped and tested on aarch64-none-linux-gnu.
    Ok for trunk?
    Thanks,
    Kyrill
    
    gcc/ChangeLog:
    
            * genmatch.cc (contains_id): For c_expr, check CPP_NAME tokens
            rather than capture_ids to detect for-iterator references.
            (lower_for): Skip result copy in replace_id when the for-iterator
            does not appear in the result, to preserve pointer identity and
            enable transform sharing.
    
    Signed-off-by: Kyrylo Tkachov <[email protected]>

Diff:
---
 gcc/genmatch.cc | 19 ++++++++++++++++---
 1 file changed, 16 insertions(+), 3 deletions(-)

diff --git a/gcc/genmatch.cc b/gcc/genmatch.cc
index 1a89b7c13c2f..da80a2c4778d 100644
--- a/gcc/genmatch.cc
+++ b/gcc/genmatch.cc
@@ -2273,7 +2273,20 @@ contains_id (operand *o, user_id *id)
            || (ife->falseexpr && contains_id (ife->falseexpr, id)));
 
   if (c_expr *ce = dyn_cast<c_expr *> (o))
-    return ce->capture_ids && ce->capture_ids->get (id->id);
+    {
+      /* Check whether any CPP_NAME token in the inline C code spells id->id.
+        gen_transform looks up CPP_NAME tokens in the id substitution table,
+        so the same check here determines whether the table needs an entry.  */
+      for (unsigned i = 0; i < ce->code.length (); ++i)
+       {
+         const cpp_token *t = &ce->code[i];
+         if (t->type == CPP_NAME
+             && strcmp ((const char *) NODE_NAME (t->val.node.node),
+                        id->id) == 0)
+           return true;
+       }
+      return false;
+    }
 
   return false;
 }
@@ -2454,8 +2467,8 @@ lower_for (simplify *sin, vec<simplify *>& simplifiers)
                  if (sin->kind == simplify::SIMPLIFY
                      || !can_delay_subst)
                    match_op = replace_id (match_op, id, oper);
-                 if (result_op
-                     && !can_delay_subst)
+                 if (result_op && !can_delay_subst
+                     && contains_id (result_op, id))
                    result_op = replace_id (result_op, id, oper);
                }
              if (skip)

Reply via email to