(bit_xor (bit_ior:c (bit_not @0) @1) (bit_ior:c @0 (bit_not @1)))
(bit_xor @0 @1))
+/* ((x & y) - (x | y)) - 1 -> ~(x ^ y) */
+(simplify
+ (plus (nop_convert1? (minus@2 (nop_convert2? (bit_and:c @0 @1))
+ (nop_convert2? (bit_ior @0 @1))))
+ integer_all_onesp)
+ (if (!TYPE_OVERFLOW_SANITIZED (type) && !TYPE_OVERFLOW_TRAPS (type)
+ && !TYPE_SATURATING (type) && !TYPE_OVERFLOW_SANITIZED (TREE_TYPE (@2))
+ && !TYPE_OVERFLOW_TRAPS (TREE_TYPE (@2))
+ && !TYPE_SATURATING (TREE_TYPE (@2)))
+ (bit_not (convert (bit_xor @0 @1)))))
+(simplify
+ (minus (nop_convert1? (plus@2 (nop_convert2? (bit_and:c @0 @1))
+ integer_all_onesp))
+ (nop_convert3? (bit_ior @0 @1)))
+ (if (!TYPE_OVERFLOW_SANITIZED (type) && !TYPE_OVERFLOW_TRAPS (type)
+ && !TYPE_SATURATING (type) && !TYPE_OVERFLOW_SANITIZED (TREE_TYPE (@2))
+ && !TYPE_OVERFLOW_TRAPS (TREE_TYPE (@2))
+ && !TYPE_SATURATING (TREE_TYPE (@2)))
+ (bit_not (convert (bit_xor @0 @1)))))
+(simplify
+ (minus (nop_convert1? (bit_and @0 @1))
+ (nop_convert2? (plus@2 (nop_convert3? (bit_ior:c @0 @1))
+ integer_onep)))
+ (if (!TYPE_OVERFLOW_SANITIZED (type) && !TYPE_OVERFLOW_TRAPS (type)
+ && !TYPE_SATURATING (type) && !TYPE_OVERFLOW_SANITIZED (TREE_TYPE (@2))
+ && !TYPE_OVERFLOW_TRAPS (TREE_TYPE (@2))
+ && !TYPE_SATURATING (TREE_TYPE (@2)))
+ (bit_not (convert (bit_xor @0 @1)))))
+
/* ~x & ~y -> ~(x | y)
~x | ~y -> ~(x & y) */
(for op (bit_and bit_ior)
--- /dev/null
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-optimized" } */
+/* { dg-final { scan-tree-dump-not "x_\[0-9]+\\\(D\\\) & y_\[0-9]+\\\(D\\\);" "optimized" } } */
+/* { dg-final { scan-tree-dump-not "x_\[0-9]+\\\(D\\\) \\| y_\[0-9]+\\\(D\\\);" "optimized" } } */
+/* { dg-final { scan-tree-dump-times "x_\[0-9]+\\\(D\\\) \\^ y_\[0-9]+\\\(D\\\);" 4 "optimized" } } */
+/* { dg-final { scan-tree-dump-times "~_\[0-9]\+" 4 "optimized" } } */
+
+int
+a (int x, int y)
+{
+ int t = x & y;
+ int tt = x | y;
+ t = t - tt;
+ return t + -1;
+}
+
+int
+b (int x, int y)
+{
+ int t = x & y;
+ int tt = x | y;
+ t = t - 1;
+ return t - tt;
+}
+
+int
+c (int x, int y)
+{
+ int t = x & y;
+ int tt = x | y;
+ tt = tt + 1;
+ return t - tt;
+}
+
+int
+d (int x, int y)
+{
+ int t = x & y;
+ int tt = x | y;
+ tt = tt + 1;
+ return t - tt;
+}
--- /dev/null
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-optimized" } */
+/* { dg-final { scan-tree-dump-not "x_\[0-9]+\\\(D\\\) & y_\[0-9]+\\\(D\\\);" "optimized" } } */
+/* { dg-final { scan-tree-dump-not "x_\[0-9]+\\\(D\\\) \\| y_\[0-9]+\\\(D\\\);" "optimized" } } */
+/* { dg-final { scan-tree-dump-times "x_\[0-9]+\\\(D\\\) \\^ y_\[0-9]+\\\(D\\\);" 8 "optimized" } } */
+/* { dg-final { scan-tree-dump-times "~_\[0-9]\+" 8 "optimized" } } */
+
+int
+a (int x, int y)
+{
+ unsigned t = x & y;
+ unsigned tt = x | y;
+ t = t - tt;
+ return t + -1;
+}
+
+int
+a1 (int x, int y)
+{
+ int t = x & y;
+ int tt = x | y;
+ unsigned t1 = t - tt;
+ return t1 + -1;
+}
+
+int
+b (int x, int y)
+{
+ unsigned t = x & y;
+ unsigned tt = x | y;
+ t = t - 1;
+ return t - tt;
+}
+
+int
+b1 (int x, int y)
+{
+ int t = x & y;
+ int tt = x | y;
+ unsigned t1 = t - 1;
+ return t1 - tt;
+}
+
+int
+c (int x, int y)
+{
+ unsigned t = x & y;
+ unsigned tt = x | y;
+ tt = tt + 1;
+ return t - tt;
+}
+
+int
+c1 (int x, int y)
+{
+ int t = x & y;
+ int tt = x | y;
+ unsigned tt1 = tt + 1;
+ return t - tt1;
+}
+
+int
+d (int x, int y)
+{
+ unsigned t = x & y;
+ unsigned tt = x | y;
+ tt = tt + 1;
+ return t - tt;
+}
+
+int
+d1 (int x, int y)
+{
+ int t = x & y;
+ int tt = x | y;
+ unsigned tt1 = tt + 1;
+ return t - tt1;
+}
--- /dev/null
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-optimized" } */
+/* { dg-final { scan-tree-dump-not "x_\[0-9]+\\\(D\\\) & y_\[0-9]+\\\(D\\\);" "optimized" } } */
+/* { dg-final { scan-tree-dump-not "x_\[0-9]+\\\(D\\\) \\| y_\[0-9]+\\\(D\\\);" "optimized" } } */
+/* { dg-final { scan-tree-dump-times "x_\[0-9]+\\\(D\\\) \\^ y_\[0-9]+\\\(D\\\);" 4 "optimized" } } */
+/* { dg-final { scan-tree-dump-times "_\[0-9] \\^ _\[0-9]" 4 "optimized" } } */
+/* { dg-final { scan-tree-dump-times "~_\[0-9]\+" 8 "optimized" } } */
+
+signed char
+a (short x, short y)
+{
+ unsigned char t = (unsigned char) (x & y);
+ unsigned char tt = (unsigned char) (x | y);
+ t = t - tt;
+ return (signed char) (t + -1);
+}
+
+unsigned char
+a1 (signed char x, signed char y)
+{
+ short t = (short) (x & y);
+ short tt = (short) (x | y);
+ unsigned char t1 = (unsigned char) (t - tt);
+ return t1 + -1;
+}
+
+signed char
+b (short x, short y)
+{
+ unsigned char t = (unsigned char) (x & y);
+ signed char tt = (signed char) (x | y);
+ t = t - 1;
+ return ((signed char) t - tt);
+}
+
+short
+b1 (short x, short y)
+{
+ int t = (int) (x & y);
+ int tt = (int) (x | y);
+ short t1 = (short) (t - 1);
+ return (short) (t1 - tt);
+}
+
+signed char
+c (unsigned x, unsigned y)
+{
+ unsigned char t = (unsigned char) (x & y);
+ signed char tt = (signed char) (x | y);
+ tt = tt + 1;
+ return (signed char) (t - tt);
+}
+
+unsigned char
+c1 (signed char x, signed char y)
+{
+ unsigned char t = (unsigned char) (x & y);
+ short tt = (short) (x | y);
+ unsigned char tt1 = (unsigned char) (tt + 1);
+ return t - tt1;
+}
+
+signed char
+d (unsigned char x, unsigned char y)
+{
+ int t = (int) (x & y);
+ int tt = (int) (x | y);
+ tt = tt + 1;
+ return (signed char) (t - tt);
+}
+
+unsigned char
+d1 (int x, int y)
+{
+ signed char t = (signed char) (x & y);
+ signed char tt = (signed char) (x | y);
+ unsigned char tt1 = (unsigned char) (tt + 1);
+ return (unsigned char) (t - tt1);
+}
--- /dev/null
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-optimized" } */
+/* { dg-final { scan-tree-dump-not "x_\[0-9]+\\\(D\\\) & y_\[0-9]+\\\(D\\\);" "optimized" } } */
+/* { dg-final { scan-tree-dump-not "x_\[0-9]+\\\(D\\\) \\| y_\[0-9]+\\\(D\\\);" "optimized" } } */
+/* { dg-final { scan-tree-dump-times "x_\[0-9]+\\\(D\\\) \\^ y_\[0-9]+\\\(D\\\);" 5 "optimized" } } */
+/* { dg-final { scan-tree-dump-times "~_\[0-9]\+" 5 "optimized" } } */
+
+int
+a (int x, int y)
+{
+ return (x & y) - (x | y) - 1;
+}
+
+int
+b (int x, int y)
+{
+ return (x & y) - 1 - (x | y);
+}
+
+int
+c (int x, int y)
+{
+ return (x & y) - ((x | y) + 1);
+}
+
+int
+d (int x, int y)
+{
+ return (x & y) - (1 + (x | y));
+}
+
+int
+e (int x, int y)
+{
+ return (unsigned) ((x & y) - (x | y)) + -1u;
+}