On December 12, 2020 9:10:41 AM GMT+01:00, Jakub Jelinek <ja...@redhat.com> wrote: >Hi! > >This patch adds the ~(X - Y) -> ~X + Y simplification requested >in the PR (plus also ~(X + C) -> ~X + (-C) for constants C that can >be safely negated. > >The first two simplify blocks is what has been requested in the PR >and that makes the first testcase pass. >Unfortunately, that change also breaks the second testcase, because >while the same expressions appearing in the same stmt and split >across multiple stmts has been folded (not really) before, with >this optimization fold-const.c optimizes ~X + Y further into >(Y - X) - 1 in fold_binary_loc associate: code, but we have nothing >like that in GIMPLE and so end up with different expressions. > >The last simplify is an attempt to deal with just this case, >had to rule out there the Y == -1U case, because then we >reached infinite recursion as ~X + -1U was canonicalized by >the pattern into (-1U - X) + -1U but there is a canonicalization >-1 - A -> ~A that turns it back. Furthermore, had to make it >#if GIMPLE only, because it otherwise resulted in infinite recursion >when interacting with the associate: optimization. >The end result is that we pass all 3 testcases and thus canonizalize >the 3 possible forms of writing the same thing. > >Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk?
Ok. Thanks, Richard. >2020-12-12 Jakub Jelinek <ja...@redhat.com> > > PR tree-optimization/96685 > * match.pd (~(X - Y) -> ~X + Y): New optimization. > (~X + Y -> (Y - X) - 1): Likewise. > > * gcc.dg/tree-ssa/pr96685-1.c: New test. > * gcc.dg/tree-ssa/pr96685-2.c: New test. > * gcc.dg/tree-ssa/pr96685-3.c: New test. > >--- gcc/match.pd.jj 2020-12-11 16:41:45.797787831 +0100 >+++ gcc/match.pd 2020-12-11 23:12:45.769291586 +0100 >@@ -1074,6 +1074,34 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT) > (bit_not (plus:c (bit_not @0) @1)) > (minus @0 @1)) > >+/* ~(X - Y) -> ~X + Y. */ >+(simplify >+ (bit_not (minus:s @0 @1)) >+ (plus (bit_not @0) @1)) >+(simplify >+ (bit_not (plus:s @0 INTEGER_CST@1)) >+ (if ((INTEGRAL_TYPE_P (type) >+ && TYPE_UNSIGNED (type)) >+ || (!TYPE_OVERFLOW_SANITIZED (type) >+ && may_negate_without_overflow_p (@1))) >+ (plus (bit_not @0) { const_unop (NEGATE_EXPR, type, @1); }))) >+ >+#if GIMPLE >+/* ~X + Y -> (Y - X) - 1. */ >+(simplify >+ (plus:c (bit_not @0) @1) >+ (if (ANY_INTEGRAL_TYPE_P (type) >+ && TYPE_OVERFLOW_WRAPS (type) >+ /* -1 - X is folded to ~X, so we'd recurse endlessly. */ >+ && !integer_all_onesp (@1)) >+ (plus (minus @1 @0) { build_minus_one_cst (type); }) >+ (if (INTEGRAL_TYPE_P (type) >+ && TREE_CODE (@1) == INTEGER_CST >+ && wi::to_wide (@1) != wi::min_value (TYPE_PRECISION (type), >+ SIGNED)) >+ (minus (plus @1 { build_minus_one_cst (type); }) @0)))) >+#endif >+ > /* x + (x & 1) -> (x + 1) & ~1 */ > (simplify > (plus:c @0 (bit_and:s @0 integer_onep@1)) >--- gcc/testsuite/gcc.dg/tree-ssa/pr96685-1.c.jj 2020-12-11 >16:42:03.975584838 +0100 >+++ gcc/testsuite/gcc.dg/tree-ssa/pr96685-1.c 2020-12-11 >16:42:03.975584838 +0100 >@@ -0,0 +1,52 @@ >+/* PR tree-optimization/96685 */ >+/* { dg-do compile } */ >+/* { dg-options "-O2 -fdump-tree-optimized" } */ >+/* { dg-final { scan-tree-dump-times "return 1;" 6 "optimized" } } */ >+ >+unsigned >+f1 (unsigned x, unsigned y) >+{ >+ unsigned a = ~(x - y); >+ unsigned b = ~x + y; >+ return a == b; >+} >+ >+unsigned >+f2 (unsigned x) >+{ >+ unsigned a = ~(x + -124U); >+ unsigned b = ~x + 124U; >+ return a == b; >+} >+ >+unsigned >+f3 (unsigned x) >+{ >+ unsigned a = ~(x + 124U); >+ unsigned b = ~x + -124U; >+ return a == b; >+} >+ >+int >+f4 (int x, int y) >+{ >+ int a = ~(x - y); >+ int b = ~x + y; >+ return a == b; >+} >+ >+int >+f5 (int x) >+{ >+ int a = ~(x + -124); >+ int b = ~x + 124; >+ return a == b; >+} >+ >+int >+f6 (int x) >+{ >+ int a = ~(x + 124); >+ int b = ~x + -124; >+ return a == b; >+} >--- gcc/testsuite/gcc.dg/tree-ssa/pr96685-2.c.jj 2020-12-11 >16:42:03.975584838 +0100 >+++ gcc/testsuite/gcc.dg/tree-ssa/pr96685-2.c 2020-12-11 >16:42:03.975584838 +0100 >@@ -0,0 +1,40 @@ >+/* PR tree-optimization/96685 */ >+/* { dg-do compile } */ >+/* { dg-options "-O2 -fdump-tree-optimized" } */ >+/* { dg-final { scan-tree-dump-times "return 1;" 4 "optimized" } } */ >+ >+int >+f1 (unsigned x, unsigned y) >+{ >+ unsigned int r1 = (x - y); >+ r1 = ~r1; >+ unsigned int r2 = ~(x - y); >+ return r1 == r2; >+} >+ >+int >+f2 (unsigned x, unsigned y) >+{ >+ unsigned int r1 = (x - 23); >+ r1 = ~r1; >+ unsigned int r2 = ~(x - 23); >+ return r1 == r2; >+} >+ >+int >+f3 (int x, int y) >+{ >+ int r1 = (x - y); >+ r1 = ~r1; >+ int r2 = ~(x - y); >+ return r1 == r2; >+} >+ >+int >+f4 (int x, int y) >+{ >+ int r1 = (x - 23); >+ r1 = ~r1; >+ int r2 = ~(x - 23); >+ return r1 == r2; >+} >--- gcc/testsuite/gcc.dg/tree-ssa/pr96685-3.c.jj 2020-12-11 >17:35:09.536123227 +0100 >+++ gcc/testsuite/gcc.dg/tree-ssa/pr96685-3.c 2020-12-11 >17:34:31.911543423 +0100 >@@ -0,0 +1,43 @@ >+/* PR tree-optimization/96685 */ >+/* { dg-do compile } */ >+/* { dg-options "-O2 -fdump-tree-optimized" } */ >+/* { dg-final { scan-tree-dump-times "return 1;" 4 "optimized" } } */ >+ >+int >+f1 (unsigned x, unsigned y) >+{ >+ unsigned int r1 = (x - y); >+ r1 = ~r1; >+ unsigned int r2 = (y - x); >+ r2 = r2 - 1; >+ return r1 == r2; >+} >+ >+int >+f2 (unsigned x, unsigned y) >+{ >+ unsigned int r1 = (x - 23); >+ r1 = ~r1; >+ unsigned int r2 = (23 - x); >+ r2 = r2 - 1; >+ return r1 == r2; >+} >+ >+int >+f3 (int x, int y) >+{ >+ int r1 = (x - 23); >+ r1 = ~r1; >+ int r2 = (23 - x); >+ --r2; >+ return r1 == r2; >+} >+ >+int >+f4 (int x, int y) >+{ >+ int r1 = (x - 23); >+ r1 = ~r1; >+ int r2 = (22 - x); >+ return r1 == r2; >+} > > Jakub