This fixes wrong-code when GENERIC code generation is faced with
collapsed captures from conditional converts.  In this case it
gets confused when looking for omitted operands.

Fixed with the following.  It does affect quite a number of
cases on trunk - I will have a look at the branch next to see
if I need to backport this.

Bootstrapped on x86_64-unknown-linux-gnu, testing in progress.

Richard.

2015-07-24  Richard Biener  <rguent...@suse.de>

        * genmatch.c (struct capture_info): Add same_as field.
        (capture_info::capture_info): Initialize same_as.
        (capture_info::walk_match): Compute same_as.
        (capture_info::walk_result): Compute stuff for the leader.
        (capture_info::walk_c_expr): Likewise.
        (dt_simplify::gen_1): Only look at leaders when deciding
        to force no side-effects or emit side-effects of omitted operands.

Index: gcc/genmatch.c
===================================================================
--- gcc/genmatch.c      (revision 226140)
+++ gcc/genmatch.c      (working copy)
@@ -1582,6 +1595,7 @@ struct capture_info
       bool cond_expr_cond_p;
       unsigned long toplevel_msk;
       int result_use_count;
+      unsigned same_as;
     };
 
   auto_vec<cinfo> info;
@@ -1601,6 +1615,9 @@ capture_info::capture_info (simplify *s,
 
   force_no_side_effects = 0;
   info.safe_grow_cleared (s->capture_max + 1);
+  for (int i = 0; i <= s->capture_max; ++i)
+    info[i].same_as = i;
+
   e = as_a <expr *> (s->match);
   for (unsigned i = 0; i < e->ops.length (); ++i)
     walk_match (e->ops[i], i,
@@ -1634,9 +1651,16 @@ capture_info::walk_match (operand *o, un
        walk_match (c->what, toplevel_arg, conditional_p, false);
       /* We need to look past multiple captures to find a captured
         expression as with conditional converts two captures
-        can be collapsed onto the same expression.  */
+        can be collapsed onto the same expression.  Also collect
+        what captures capture the same thing.  */
       while (c->what && is_a <capture *> (c->what))
-       c = as_a <capture *> (c->what);
+       {
+         c = as_a <capture *> (c->what);
+         if (info[c->where].same_as != c->where
+             && info[c->where].same_as != info[where].same_as)
+           fatal_at (c->location, "cannot handle this collapsed capture");
+         info[c->where].same_as = info[where].same_as;
+       }
       /* Mark expr (non-leaf) captures and forced single-use exprs.  */
       expr *e;
       if (c->what
@@ -1682,19 +1706,20 @@ capture_info::walk_result (operand *o, b
 {
   if (capture *c = dyn_cast <capture *> (o))
     {
-      info[c->where].result_use_count++;
+      unsigned where = info[c->where].same_as;
+      info[where].result_use_count++;
       /* If we substitute an expression capture we don't know
          which captures this will end up using (well, we don't
         compute that).  Force the uses to be side-effect free
         which means forcing the toplevels that reach the
         expression side-effect free.  */
-      if (info[c->where].expr_p)
-       force_no_side_effects |= info[c->where].toplevel_msk;
+      if (info[where].expr_p)
+       force_no_side_effects |= info[where].toplevel_msk;
       /* Mark CSE capture uses as forced to have no side-effects. */
       if (c->what
          && is_a <expr *> (c->what))
        {
-         info[c->where].cse_p = true;
+         info[where].cse_p = true;
          walk_result (c->what, true, result);
        }
     }
@@ -1783,7 +1808,8 @@ capture_info::walk_c_expr (c_expr *e)
            id = (const char *)n->val.str.text;
          else
            id = (const char *)CPP_HASHNODE (n->val.node.node)->ident.str;
-         info[*e->capture_ids->get(id)].force_no_side_effects_p = true;
+         unsigned where = *e->capture_ids->get(id);
+         info[info[where].same_as].force_no_side_effects_p = true;
        }
     }
 }
@@ -2767,6 +2793,8 @@ dt_simplify::gen_1 (FILE *f, int indent,
          if (!is_predicate)
            for (int i = 0; i < s->capture_max + 1; ++i)
              {
+               if (cinfo.info[i].same_as != (unsigned)i)
+                 continue;
                if (!cinfo.info[i].force_no_side_effects_p
                    && cinfo.info[i].result_use_count > 1)
                  {
@@ -2842,6 +2870,8 @@ dt_simplify::gen_1 (FILE *f, int indent,
             on TREE_SIDE_EFFECTS emit omit_one_operand.  */
          for (int i = 0; i < s->capture_max + 1; ++i)
            {
+             if (cinfo.info[i].same_as != (unsigned)i)
+               continue;
              if (!cinfo.info[i].force_no_side_effects_p
                  && !cinfo.info[i].expr_p
                  && cinfo.info[i].result_use_count == 0)

Reply via email to