On Tue, 6 Oct 2026, [email protected] wrote:
> From: Kyrylo Tkachov <[email protected]>
>
> The DT_TRUE merge barrier in find_node prevents a later pattern from
> merging into an earlier equal sibling when a DT_TRUE node lies between
> them. The barrier was introduced for PR 64084 (r218141) to preserve
> source order in cases where multiple patterns can match the same input.
>
> Today's match.pd is protected at a finer grain by the gen_kids flush:
> DT_TRUE and DT_MATCH kids each force a flush of collected alternatives
> before emitting their own subtrees. The flush guarantees that patterns
> before a DT_TRUE are tried before patterns after it, so the barrier in
> find_node is redundant for most cases.
>
> The remaining cases where the barrier is necessary are those where an
> intermediate sibling (between the earlier and later equal nodes) has a
> DT_MATCH descendant. A DT_MATCH descendant means the sibling's
> subtree can match any input value, including inputs matched by the later
> node's subtree. If the later node merged into the earlier one, it would
> be tried before the DT_MATCH sibling, violating source order for those
> inputs.
>
> When no intermediate sibling has a DT_MATCH descendant, every sibling
> matches a disjoint set of inputs (since the top-level operand overlap
> check already ensures no sibling's top-level operation overlaps with
> p's, and DT_MATCH is the only construct that can widen the match beyond
> a specific operation). In this case the merge is safe.
>
> Replace the unconditional DT_TRUE barrier refusal with a scan of the
> intermediate siblings: refuse only when at least one non-DT_TRUE sibling
> between the candidate and the insertion point has a DT_MATCH descendant.
> This reduces the generated GIMPLE matcher by about 0.4% and the GENERIC
> matcher by about 0.2%.
>
> Bootstrapped and tested on aarch64-none-linux-gnu.
> Ok for trunk?
>
> Thanks,
> Kyrill
>
> gcc/ChangeLog:
>
> * genmatch.cc (subtree_has_match_p): New function.
> (decision_tree::find_node): Replace unconditional DT_TRUE barrier
> with a scan for DT_MATCH descendants in intermediate siblings.
>
> Signed-off-by: Kyrylo Tkachov <[email protected]>
> ---
> gcc/genmatch.cc | 36 ++++++++++++++++++++++++++++++++----
> 1 file changed, 32 insertions(+), 4 deletions(-)
>
> diff --git a/gcc/genmatch.cc b/gcc/genmatch.cc
> index 905ff420d6a..028283b9825 100644
> --- a/gcc/genmatch.cc
> +++ b/gcc/genmatch.cc
> @@ -2859,6 +2859,19 @@ nodes_overlap_p (dt_node *n1, dt_node *n2)
> return operand_cases_overlap_p (op1, op2);
> }
>
> +/* Return true if N or any node in its subtree has type DT_MATCH. */
> +
> +static bool
> +subtree_has_match_p (dt_node *n)
> +{
> + if (n->type == dt_node::DT_MATCH)
> + return true;
> + for (auto kid : n->kids)
> + if (subtree_has_match_p (kid))
> + return true;
> + return false;
> +}
> +
> /* Search OPS for a decision tree node like P and return it if found. */
>
> dt_node *
> @@ -2886,10 +2899,25 @@ decision_tree::find_node (vec<dt_node *>& ops,
> dt_node *p)
> {
> /* Unless we are processing the same pattern or the blocking
> pattern is before the one we are going to merge with. */
> - if ((true_node
> - && true_node->for_id != current_id
> - && true_node->for_id > as_a <dt_operand *> (ops[i])->for_id)
> - || overlap_node)
> + bool refused = overlap_node != NULL;
> + if (!refused
> + && true_node
> + && true_node->for_id != current_id
> + && true_node->for_id > as_a <dt_operand *> (ops[i])->for_id)
> + {
> + /* Refuse only when an intermediate sibling has a DT_MATCH
> + descendant. Such a sibling can match any input, and its
> + ordering relative to p must be preserved. When no
> + intermediate sibling has a DT_MATCH descendant, every
> + sibling matches a disjoint set of inputs, so the ordering
> + of p's subtree with respect to those siblings does not
> + affect which pattern fires. */
> + for (int k = i + 1; k < (int) ops.length (); ++k)
> + if (ops[k]->type != dt_node::DT_TRUE
> + && subtree_has_match_p (ops[k]))
> + { refused = true; break; }
please fix formatting:
{
refused = true;
break;
}
OK with that change.
Thanks,
Richard.
> + }
> + if (refused)
> {
> if (verbose >= 1)
> {
>
--
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)