/* 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). */
--- /dev/null
+/* 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;
+}
--- /dev/null
+/* { 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" } } */