Hi! According to my verification proglet, this transformation for signed types with undefined overflow doesn't introduce nor remove any UB cases, so should be valid even for signed integral types. Not using a for because of the :c on plus which can't be there on minus.
Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk? 2020-05-06 Jakub Jelinek <ja...@redhat.com> PR tree-optimization/94921 * match.pd (~(~X - Y) -> X + Y, ~(~X + Y) -> X - Y): New simplifications. * gcc.dg/tree-ssa/pr94921.c: New test. --- gcc/match.pd.jj 2020-05-05 11:36:17.510911674 +0200 +++ gcc/match.pd 2020-05-05 16:48:59.496883197 +0200 @@ -1010,6 +1010,14 @@ (define_operator_list COND_TERNARY @0)) #endif +/* ~(~X - Y) -> X + Y and ~(~X + Y) -> X - Y. */ +(simplify + (bit_not (minus (bit_not @0) @1)) + (plus @0 @1)) +(simplify + (bit_not (plus:c (bit_not @0) @1)) + (minus @0 @1)) + /* x + (x & 1) -> (x + 1) & ~1 */ (simplify (plus:c @0 (bit_and:s @0 integer_onep@1)) --- gcc/testsuite/gcc.dg/tree-ssa/pr94921.c.jj 2020-05-05 16:58:32.913192128 +0200 +++ gcc/testsuite/gcc.dg/tree-ssa/pr94921.c 2020-05-05 16:59:26.231384053 +0200 @@ -0,0 +1,18 @@ +/* PR tree-optimization/94921 */ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-optimized" } */ +/* { dg-final { scan-tree-dump " \[ab]_\[0-9]+\\\(D\\\) \\+ \[ab]_\[0-9]+\\\(D\\\);" "optimized" } } */ +/* { dg-final { scan-tree-dump " c_\[0-9]+\\\(D\\\) - d_\[0-9]+\\\(D\\\);" "optimized" } } */ +/* { dg-final { scan-tree-dump-not " ~\[abcd]\?_\[0-9]\+" "optimized" } } */ + +int +foo (int a, int b) +{ + return ~(~a - b); +} + +int +bar (int c, int d) +{ + return ~(~c + d); +} Jakub