]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
match: Fix the `popcnt(a&b) + popcnt(a|b)` pattern for types [PR111913]
authorAndrew Pinski <pinskia@gmail.com>
Mon, 23 Oct 2023 19:46:34 +0000 (12:46 -0700)
committerAndrew Pinski <pinskia@gmail.com>
Tue, 24 Oct 2023 11:16:12 +0000 (04:16 -0700)
So this pattern needs a little help on the gimple side of things to know what
the type popcount should be. For most builtins, the type is the same as the input
but popcount and others are not. And when using it with another outer expression,
genmatch needs some slight help to know that the return type was type rather than
the argument type.

Bootstrapped and tested on x86_64-linux-gnu with no regressions.

PR tree-optimization/111913

gcc/ChangeLog:

* match.pd (`popcount(X&Y) + popcount(X|Y)`): Add the resulting
type for popcount.

gcc/testsuite/ChangeLog:

* gcc.c-torture/compile/fold-popcount-1.c: New test.
* gcc.dg/fold-popcount-8a.c: New test.

gcc/match.pd
gcc/testsuite/gcc.c-torture/compile/fold-popcount-1.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/fold-popcount-8a.c [new file with mode: 0644]

index ce8d159d260f1a3d4785b3e52c6d4c143fa0fec5..f725a685863dce2b1f7ba295d32fa9ba092bf961 100644 (file)
@@ -8600,7 +8600,7 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
 /* popcount(X&Y) + popcount(X|Y) is popcount(x) + popcount(Y).  */
 (simplify
   (plus:c (POPCOUNT:s (bit_and:s @0 @1)) (POPCOUNT:s (bit_ior:cs @0 @1)))
-  (plus (POPCOUNT @0) (POPCOUNT @1)))
+  (plus (POPCOUNT:type @0) (POPCOUNT:type @1)))
 
 /* popcount(X) + popcount(Y) - popcount(X&Y) is popcount(X|Y).  */
 /* popcount(X) + popcount(Y) - popcount(X|Y) is popcount(X&Y).  */
diff --git a/gcc/testsuite/gcc.c-torture/compile/fold-popcount-1.c b/gcc/testsuite/gcc.c-torture/compile/fold-popcount-1.c
new file mode 100644 (file)
index 0000000..d3d3a29
--- /dev/null
@@ -0,0 +1,13 @@
+/* PR tree-optimization/111913 */
+
+int f(unsigned int x, unsigned int y)
+{
+  return __builtin_popcount (x&y) + __builtin_popcount (y|x--);
+}
+
+int f2(unsigned int x, unsigned int y)
+{
+  int t = __builtin_popcount (x&y);
+  int t1 = __builtin_popcount (x|y);
+  return t + t1;
+}
diff --git a/gcc/testsuite/gcc.dg/fold-popcount-8a.c b/gcc/testsuite/gcc.dg/fold-popcount-8a.c
new file mode 100644 (file)
index 0000000..3001522
--- /dev/null
@@ -0,0 +1,33 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-optimized" } */
+
+int foo1(unsigned int x, unsigned int y)
+{
+  int t = __builtin_popcount (x&y);
+  int t1 = __builtin_popcount (x|y);
+  return t + t1;
+}
+
+int foo2(unsigned int x, unsigned int y)
+{
+  int t1 = __builtin_popcount (x|y);
+  int t = __builtin_popcount (x&y);
+  return t + t1;
+}
+
+int foo3(unsigned int y, unsigned int x)
+{
+  int t = __builtin_popcount (x&y);
+  int t1 = __builtin_popcount (x|y);
+  return t + t1;
+}
+
+int foo4(unsigned int y, unsigned int x)
+{
+  int t1 = __builtin_popcount (x|y);
+  int t = __builtin_popcount (x&y);
+  return t + t1;
+}
+
+/* { dg-final { scan-tree-dump-not " & " "optimized" } } */
+/* { dg-final { scan-tree-dump-not " \\| " "optimized" } } */