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)

Reply via email to