Hi!

While generic tree sharing is usually harmless, because we unshare
everything before gimplification, on the following testcase a match.pd
pattern that uses @1 twice introduces tree sharing during the C
gimplification langhook, so after everything has been unshared.

The following patch fixes it by unsharing uses of captures except for the
last use.  Bootstrapped/regtested on x86_64-linux and i686-linux, acked
by Richard in the PR, committed to trunk.

2017-04-04  Jakub Jelinek  <ja...@redhat.com>
            Richard Biener  <rguent...@suse.de>

        PR c++/80297
        * genmatch.c (capture::gen_transform): For GENERIC unshare_expr
        captures used multiple times, except for the last use.
        * generic-match-head.c: Include gimplify.h.

        * g++.dg/torture/pr80297.C: New test.

--- gcc/genmatch.c.jj   2017-03-19 11:57:19.000000000 +0100
+++ gcc/genmatch.c      2017-04-04 13:23:15.053251358 +0200
@@ -2525,7 +2525,18 @@ capture::gen_transform (FILE *f, int ind
        }
     }
 
-  fprintf_indent (f, indent, "%s = captures[%u];\n", dest, where);
+  /* If in GENERIC some capture is used multiple times, unshare it except
+     when emitting the last use.  */
+  if (!gimple
+      && cinfo->info.exists ()
+      && cinfo->info[cinfo->info[where].same_as].result_use_count > 1)
+    {
+      fprintf_indent (f, indent, "%s = unshare_expr (captures[%u]);\n",
+                     dest, where);
+      cinfo->info[cinfo->info[where].same_as].result_use_count--;
+    }
+  else
+    fprintf_indent (f, indent, "%s = captures[%u];\n", dest, where);
 
   /* ???  Stupid tcc_comparison GENERIC trees in COND_EXPRs.  Deal
      with substituting a capture of that.  */
--- gcc/generic-match-head.c.jj 2017-01-01 12:45:38.000000000 +0100
+++ gcc/generic-match-head.c    2017-04-04 13:18:38.437884559 +0200
@@ -33,6 +33,7 @@ along with GCC; see the file COPYING3.
 #include "builtins.h"
 #include "dumpfile.h"
 #include "case-cfn-macros.h"
+#include "gimplify.h"
 
 
 /* Routine to determine if the types T1 and T2 are effectively
--- gcc/testsuite/g++.dg/torture/pr80297.C.jj   2017-04-04 13:47:45.254048537 
+0200
+++ gcc/testsuite/g++.dg/torture/pr80297.C      2017-04-04 13:47:29.000000000 
+0200
@@ -0,0 +1,12 @@
+// PR c++/80297
+// { dg-do compile }
+
+extern const unsigned long int b;
+extern const long long int c;
+
+int
+foo ()
+{
+  int a = 809 >> -(b & !c) + b - (long long)(b & !c);
+  return a;
+}

        Jakub

Reply via email to