From: Kyrylo Tkachov <[email protected]>
genmatch can leave the iterators of a named match unexpanded. Code generation
emits COND_EXPR conditions in opcode switches. Overlapping delayed iterator
sets can then emit duplicate case labels.
Substitute a group before decision-tree insertion when one of its iterators
occurs in a COND_EXPR condition. The existing eager path keeps the
substitutions aligned and lets the decision tree merge common concrete
operations. Other named matches keep delayed substitution.
A reduced GIMPLE and GENERIC matcher with overlapping iterator sets fails to
compile before this change. Both forms compile after the change.
This is needed to accept the patterns in patch 3/3.
Bootstrapped and tested on aarch64-none-linux-gnu.
Ok for trunk?
Thanks,
Kyrill
gcc/ChangeLog:
* genmatch.cc (cond_expr_condition_contains_id): New function.
(lower_for): Expand iterators used in COND_EXPR conditions.
(lower): Update comment.
Signed-off-by: Kyrylo Tkachov <[email protected]>
---
gcc/genmatch.cc | 44 ++++++++++++++++++++++++++++++++++++++++----
1 file changed, 40 insertions(+), 4 deletions(-)
diff --git a/gcc/genmatch.cc b/gcc/genmatch.cc
index 1bc5875d7dd..c4bb1c12400 100644
--- a/gcc/genmatch.cc
+++ b/gcc/genmatch.cc
@@ -2159,6 +2159,26 @@ contains_id (operand *o, user_id *id)
return false;
}
+/* Return true if O contains a COND_EXPR condition that refers to ID. */
+
+static bool
+cond_expr_condition_contains_id (operand *o, user_id *id)
+{
+ if (capture *c = dyn_cast <capture *> (o))
+ return c->what && cond_expr_condition_contains_id (c->what, id);
+
+ if (expr *e = dyn_cast <expr *> (o))
+ {
+ if (*e->operation == COND_EXPR && contains_id (e->ops[0], id))
+ return true;
+ for (unsigned i = 0; i < e->ops.length (); ++i)
+ if (cond_expr_condition_contains_id (e->ops[i], id))
+ return true;
+ }
+
+ return false;
+}
+
/* In AST operand O replace operator ID with operator WITH. */
@@ -2304,9 +2324,24 @@ lower_for (simplify *sin, vec<simplify *>& simplifiers)
else
can_delay_subst = false;
}
- if (sin->kind == simplify::MATCH
- && can_delay_subst)
- continue;
+ /* Code generation emits COND_EXPR conditions in opcode switches.
+ Substitute iterators in these conditions before inserting the patterns
+ into the decision tree. Overlapping iterator sets could otherwise
+ emit duplicate case labels. */
+ if (sin->kind == simplify::MATCH && can_delay_subst)
+ {
+ for (unsigned si = worklist_start;
+ si < worklist.length () && can_delay_subst; ++si)
+ for (unsigned i = 0; i < n_ids; ++i)
+ if (cond_expr_condition_contains_id (worklist[si]->match,
+ ids[i]))
+ {
+ can_delay_subst = false;
+ break;
+ }
+ if (can_delay_subst)
+ continue;
+ }
unsigned worklist_end = worklist.length ();
for (unsigned si = worklist_start; si < worklist_end; ++si)
@@ -2374,7 +2409,8 @@ lower (vec<simplify *>& simplifiers, bool gimple)
/* Lower for needs to happen before lowering cond
to support (for cnd (cond vec_cond)). This is
safe as substitution delay does not happen for
- cond or vec_cond. */
+ cond or vec_cond, or for iterators used in a
+ COND_EXPR condition. */
out_simplifiers.truncate (0);
for (auto s: simplifiers)
lower_for (s, out_simplifiers);
--
2.50.1 (Apple Git-155)