match.pd: (x & y) - (x | y) - 1 -> ~(x ^ y) simplification [PR94882]
authorJeff Law <law@redhat.com>
Wed, 1 Jul 2020 20:44:07 +0000 (14:44 -0600)
committerJeff Law <law@redhat.com>
Wed, 1 Jul 2020 20:49:30 +0000 (14:49 -0600)
gcc/
PR tree-optimization/94882
* match.pd (x & y) - (x | y) - 1 -> ~(x ^ y): New simplification.

gcc/testsuite/
PR tree-optimization/94882
* gcc.dg/tree-ssa/pr94882.c: New test.
* gcc.dg/tree-ssa/pr94882-1.c: New test.
* gcc.dg/tree-ssa/pr94882-2.c: New test.
* gcc.dg/tree-ssa/pr94882-3.c: New test.

gcc/match.pd
gcc/testsuite/gcc.dg/tree-ssa/pr94882-1.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/tree-ssa/pr94882-2.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/tree-ssa/pr94882-3.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/tree-ssa/pr94882.c [new file with mode: 0644]

index 43f3d7ab0fa5838c543c795ca283d90d8cecd62a..c6ae7a7db7aee88b8d42669133ddfe3f70f8761f 100644 (file)
@@ -1144,6 +1144,35 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
  (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)
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr94882-1.c b/gcc/testsuite/gcc.dg/tree-ssa/pr94882-1.c
new file mode 100644 (file)
index 0000000..976b8e5
--- /dev/null
@@ -0,0 +1,42 @@
+/* { 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;
+}
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr94882-2.c b/gcc/testsuite/gcc.dg/tree-ssa/pr94882-2.c
new file mode 100644 (file)
index 0000000..7f533b6
--- /dev/null
@@ -0,0 +1,78 @@
+/* { 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;
+}
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr94882-3.c b/gcc/testsuite/gcc.dg/tree-ssa/pr94882-3.c
new file mode 100644 (file)
index 0000000..979162f
--- /dev/null
@@ -0,0 +1,79 @@
+/* { 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);
+}
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr94882.c b/gcc/testsuite/gcc.dg/tree-ssa/pr94882.c
new file mode 100644 (file)
index 0000000..e7a5530
--- /dev/null
@@ -0,0 +1,36 @@
+/* { 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;
+}