(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))
--- /dev/null
+/* 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;
+}
--- /dev/null
+/* 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;
+}
--- /dev/null
+/* 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;
+}