re PR tree-optimization/87261 (Optimize bool expressions)
authorMCC CS <deswurstes@users.noreply.github.com>
Mon, 1 Oct 2018 11:25:45 +0000 (11:25 +0000)
committerRichard Biener <rguenth@gcc.gnu.org>
Mon, 1 Oct 2018 11:25:45 +0000 (11:25 +0000)
2018-10-01  MCC CS <deswurstes@users.noreply.github.com>

PR tree-optimization/87261
* match.pd: Remove trailing whitespace.
Add (x & y) | ~(x | y) -> ~(x ^ y),
(~x | y) ^ (x ^ y) -> x | ~y and (x ^ y) | ~(x | y) -> ~(x & y)

* gcc.dg/pr87261.c: New test.

From-SVN: r264744

gcc/ChangeLog
gcc/match.pd
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.dg/pr87261.c [new file with mode: 0644]

index 5214064bd1400ddf638e8c30a0cd97b0aff864bf..70bfeb6d92157e54046271dd044cda7e2e13bd64 100644 (file)
@@ -1,3 +1,10 @@
+2018-10-01  MCC CS <deswurstes@users.noreply.github.com>
+
+       PR tree-optimization/87261
+       * match.pd: Remove trailing whitespace.
+       Add (x & y) | ~(x | y) -> ~(x ^ y),
+       (~x | y) ^ (x ^ y) -> x | ~y and (x ^ y) | ~(x | y) -> ~(x & y)
+
 2018-10-01  Claudiu Zissulescu  <claziss@synopsys.com>
 
        * config/arc/arc.md (*add_n): Clean up pattern, update instruction
index ae26ec226aca2752ee13e3115bd7c2062de507ac..db0e4a8c4b918c306c8f466851dfbd370b91601b 100644 (file)
@@ -92,7 +92,7 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
   IFN_FMA IFN_FMS IFN_FNMA IFN_FNMS)
 (define_operator_list COND_TERNARY
   IFN_COND_FMA IFN_COND_FMS IFN_COND_FNMA IFN_COND_FNMS)
-    
+
 /* As opposed to convert?, this still creates a single pattern, so
    it is not a suitable replacement for convert? in all cases.  */
 (match (nop_convert @0)
@@ -106,7 +106,7 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
       && tree_nop_conversion_p (TREE_TYPE (type), TREE_TYPE (TREE_TYPE (@0))))))
 /* This one has to be last, or it shadows the others.  */
 (match (nop_convert @0)
- @0) 
+ @0)
 
 /* Transform likes of (char) ABS_EXPR <(int) x> into (char) ABSU_EXPR <x>
    ABSU_EXPR returns unsigned absolute value of the operand and the operand
@@ -285,7 +285,7 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
      And not for _Fract types where we can't build 1.  */
   (if (!integer_zerop (@0) && !ALL_FRACT_MODE_P (TYPE_MODE (type)))
    { build_one_cst (type); }))
- /* X / abs (X) is X < 0 ? -1 : 1.  */ 
+ /* X / abs (X) is X < 0 ? -1 : 1.  */
  (simplify
    (div:C @0 (abs @0))
    (if (INTEGRAL_TYPE_P (type)
@@ -929,6 +929,31 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
   (bitop:c @0 (bit_not (bitop:cs @0 @1)))
   (bitop @0 (bit_not @1))))
 
+/* (~x & y) | ~(x | y) -> ~x */
+(simplify
+ (bit_ior:c (bit_and:c (bit_not@2 @0) @1) (bit_not (bit_ior:c @0 @1)))
+ @2)
+
+/* (x | y) ^ (x | ~y) -> ~x */
+(simplify
+ (bit_xor:c (bit_ior:c @0 @1) (bit_ior:c @0 (bit_not @1)))
+ (bit_not @0))
+
+/* (x & y) | ~(x | y) -> ~(x ^ y) */
+(simplify
+ (bit_ior:c (bit_and:s @0 @1) (bit_not:s (bit_ior:s @0 @1)))
+ (bit_not (bit_xor @0 @1)))
+
+/* (~x | y) ^ (x ^ y) -> x | ~y */
+(simplify
+ (bit_xor:c (bit_ior:cs (bit_not @0) @1) (bit_xor:s @0 @1))
+ (bit_ior @0 (bit_not @1)))
+
+/* (x ^ y) | ~(x | y) -> ~(x & y) */
+(simplify
+ (bit_ior:c (bit_xor:s @0 @1) (bit_not:s (bit_ior:s @0 @1)))
+ (bit_not (bit_and @0 @1)))
+
 /* (x | y) & ~x -> y & ~x */
 /* (x & y) | ~x -> y | ~x */
 (for bitop (bit_and bit_ior)
@@ -1139,7 +1164,7 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
   (if (tree_nop_conversion_p (type, TREE_TYPE (@0))
        && tree_nop_conversion_p (type, TREE_TYPE (@1)))
    (mult (convert @0) (convert (negate @1)))))
+
 /* -(A + B) -> (-B) - A.  */
 (simplify
  (negate (plus:c @0 negate_expr_p@1))
@@ -3099,7 +3124,7 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
     (if (tree_int_cst_sgn (@1) < 0)
      (scmp @0 @2)
      (cmp @0 @2))))))
+
 /* Simplify comparison of something with itself.  For IEEE
    floating-point, we can only do some of these simplifications.  */
 (for cmp (eq ge le)
@@ -3170,11 +3195,11 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
         }
       tree newtype
         = (TYPE_PRECISION (TREE_TYPE (@0)) > TYPE_PRECISION (type1)
-          ? TREE_TYPE (@0) : type1); 
+          ? TREE_TYPE (@0) : type1);
     }
     (if (TYPE_PRECISION (TREE_TYPE (@2)) > TYPE_PRECISION (newtype))
      (cmp (convert:newtype @0) (convert:newtype @1))))))
+
  (simplify
   (cmp @0 REAL_CST@1)
   /* IEEE doesn't distinguish +0 and -0 in comparisons.  */
@@ -3422,7 +3447,7 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
            (FTYPE) N == CST -> 0
            (FTYPE) N != CST -> 1.  */
        (if (cmp == EQ_EXPR || cmp == NE_EXPR)
-        { constant_boolean_node (cmp == NE_EXPR, type); }) 
+        { constant_boolean_node (cmp == NE_EXPR, type); })
        /* Otherwise replace with sensible integer constant.  */
        (with
         {
@@ -3666,7 +3691,7 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
  (simplify
   (cmp (bit_and@2 @0 integer_pow2p@1) @1)
   (icmp @2 { build_zero_cst (TREE_TYPE (@0)); })))
+
 /* If we have (A & C) != 0 ? D : 0 where C and D are powers of 2,
    convert this into a shift followed by ANDing with D.  */
 (simplify
@@ -3886,7 +3911,7 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
         (if (cmp == LE_EXPR)
         (ge (convert:st @0) { build_zero_cst (st); })
         (lt (convert:st @0) { build_zero_cst (st); }))))))))))
+
 (for cmp (unordered ordered unlt unle ungt unge uneq ltgt)
  /* If the second operand is NaN, the result is constant.  */
  (simplify
@@ -4540,7 +4565,7 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
   (if (wi::to_wide (@1) == -1)
    (rdiv { build_real (type, dconst1); } @0))))
 
-/* Narrowing of arithmetic and logical operations. 
+/* Narrowing of arithmetic and logical operations.
 
    These are conceptually similar to the transformations performed for
    the C/C++ front-ends by shorten_binary_op and shorten_compare.  Long
@@ -4612,7 +4637,7 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
      (convert (bit_and (op (convert:utype @0) (convert:utype @1))
               (convert:utype @4))))))))
 
-/* Transform (@0 < @1 and @0 < @2) to use min, 
+/* Transform (@0 < @1 and @0 < @2) to use min,
    (@0 > @1 and @0 > @2) to use max */
 (for logic (bit_and bit_and bit_and bit_and bit_ior bit_ior bit_ior bit_ior)
      op    (lt      le      gt      ge      lt      le      gt      ge     )
index 7e73af73e754cd07e1b68d3623176e526d7fe603..5dbb34ebc5c46a42c8f3b60f22ff193996fcf1db 100644 (file)
@@ -1,3 +1,8 @@
+2018-10-01  MCC CS <deswurstes@users.noreply.github.com>
+
+       PR tree-optimization/87261
+       * gcc.dg/pr87261.c: New test.
+
 2018-10-01  Claudiu Zissulescu  <claziss@synopsys.com>
 
        * gcc.target/arc/tph_addx.c: New test.
diff --git a/gcc/testsuite/gcc.dg/pr87261.c b/gcc/testsuite/gcc.dg/pr87261.c
new file mode 100644 (file)
index 0000000..9b10d03
--- /dev/null
@@ -0,0 +1,35 @@
+/* { dg-do compile } */
+/* { dg-options "-O -fdump-tree-original" } */
+
+int f1 (int a, int b)
+{
+ return ~(a|b)|(~a&b);
+}
+
+int f2 (int a, int b)
+{
+ return (a|b)^(a|~b);
+}
+
+/* { dg-final { scan-tree-dump-times "return \\~a;" 2 "original" } } */
+
+int f3 (int a, int b)
+{
+ return ~(a|b)|(a&b);
+}
+
+/* { dg-final { scan-tree-dump "return \\~\\(a \\^ b\\);" "original" } } */
+
+int f4 (int a, int b)
+{
+ return a^b^(~a|b);
+}
+
+/* { dg-final { scan-tree-dump "return \\~b \\| a;" "original" } } */
+
+int f5 (int a, int b)
+{
+ return (a^b)|~(a|b);
+}
+
+/* { dg-final { scan-tree-dump "return \\~\\(a \\& b\\);" "original" } } */