https://gcc.gnu.org/g:fbbe414895c6450ff3e282ed45c2b8306bc1f67e
commit r17-4985-gfbbe414895c6450ff3e282ed45c2b8306bc1f67e Author: Kyrylo Tkachov <[email protected]> Date: Tue Oct 6 15:45:44 2026 +0200 genmatch: Avoid replicating patterns over unused for-iterators 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. This is always a match.pd authoring mistake: such a pattern should be moved outside the enclosing for-loop. 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, emit a diagnostic and emit only a single copy with j=0 operator values. Fix the instance that motivated this: the (for lop ...) pattern inside (for op ...) at match.pd:6580 does not use op. Move it outside. gcc/ChangeLog: * genmatch.cc (lower_for): Emit a diagnostic and skip replicated substitutions when no for-level iterator appears in the pattern. * match.pd: Move the (for lop ...) vec_cond pattern outside the enclosing (for op ...). Signed-off-by: Kyrylo Tkachov <[email protected]> Diff: --- gcc/genmatch.cc | 12 +++++++++++- gcc/match.pd | 18 +++++++++--------- 2 files changed, 20 insertions(+), 10 deletions(-) diff --git a/gcc/genmatch.cc b/gcc/genmatch.cc index a67426b6313c..6f3f3c670baa 100644 --- a/gcc/genmatch.cc +++ b/gcc/genmatch.cc @@ -2446,7 +2446,17 @@ 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]))); + if (!any_id_used) + warning_at (s->match->location, + "pattern does not use any operator from the enclosing" + " for; move it outside"); + for (unsigned j = 0; j < (any_id_used ? max_n_opers : 1u); ++j) { operand *match_op = s->match; operand *result_op = s->result; diff --git a/gcc/match.pd b/gcc/match.pd index 833ee23b8fcc..0a4f7b718b46 100644 --- a/gcc/match.pd +++ b/gcc/match.pd @@ -6642,15 +6642,6 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT) && !expand_vec_cond_expr_p (TREE_TYPE (@1), TREE_TYPE (@0))))) (vec_cond @0 (op!:type @1 @3) (op!:type @2 @4)))) -/* (@0 ? @2 : @3) lop (@1 ? @2 : @3) --> (@0 lop @1) ? @2 : @3. */ -(for lop (bit_and bit_ior bit_xor) - (simplify - (lop - (vec_cond @0 integer_minus_onep@2 integer_zerop@3) - (vec_cond @1 @2 @3)) - (if (target_supports_op_p (TREE_TYPE (@0), lop, optab_vector)) - (vec_cond (lop @0 @1) @2 @3)))) - /* (c ? a : b) op d --> c ? (a op d) : (b op d) */ (simplify (op (vec_cond:s @0 @1 @2) @3) @@ -6671,6 +6662,15 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT) && !expand_vec_cond_expr_p (TREE_TYPE (@1), TREE_TYPE (@0))))) (vec_cond @0 (op!:type @3 @1) (op!:type @3 @2))))) +/* (@0 ? @2 : @3) lop (@1 ? @2 : @3) --> (@0 lop @1) ? @2 : @3. */ +(for lop (bit_and bit_ior bit_xor) + (simplify + (lop + (vec_cond @0 integer_minus_onep@2 integer_zerop@3) + (vec_cond @1 @2 @3)) + (if (target_supports_op_p (TREE_TYPE (@0), lop, optab_vector)) + (vec_cond (lop @0 @1) @2 @3)))) + /* If we have a "if a bit is not set, set it" case, just set the bit all the time (PR 64567). Note that this does not work if we're checking for more than one
