On Sun, Sep 30, 2018 at 5:11 PM MCC CS <mc...@gmx.com> wrote: > > > Now that it has got enough reviews and there's > been no comments for a week, I believe > now it's time for us to install it on trunk. > The patch is the same as previous, but rebased > on current trunk. > > Could you please push it for me? If there's anything > I can do to help, just tell me.
I'll push it after a round of testing on my side. Thanks and sorry for the delay, Richard. > 2018-09-30 MCC CS <deswurs...@users.noreply.github.com> > > gcc/ > PR tree-optimization/87261 > * match.pd: Add boolean optimizations, > fix whitespace. > > 2018-09-30 MCC CS <deswurs...@users.noreply.github.com> > > gcc/testsuite/ > PR tree-optimization/87261 > * gcc.dg/pr87261.c: New test. > > Index: gcc/match.pd > =================================================================== > --- gcc/match.pd (revision 264725) > +++ gcc/match.pd (working copy) > @@ -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:cs @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:cs @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: gcc/testsuite/gcc.dg/pr87261.c > =================================================================== > --- gcc/testsuite/gcc.dg/pr87261.c (nonexistent) > +++ gcc/testsuite/gcc.dg/pr87261.c (working copy) > @@ -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" } } */