diff --git a/gcc/match.pd b/gcc/match.pd
index 33ee1a920bf4a036cc5fdb3c96b38b52765bdefb..f02021b80a0ebb34e3608239c71fc9fe74705cbf 100644
--- a/gcc/match.pd
+++ b/gcc/match.pd
@@ -1109,6 +1109,11 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
       && !TYPE_SATURATING (type))
   (bit_ior @0 @1)))
 
+/* (x | y) - y -> (x & ~y) */
+(simplify
+ (minus (bit_ior @0 @1) @1)
+ (bit_and @0 (bit_not @1)))
+
 /* (x | y) - (x ^ y) -> x & y */
 (simplify
  (minus (bit_ior @0 @1) (bit_xor @0 @1))
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr94880.c b/gcc/testsuite/gcc.dg/tree-ssa/pr94880.c
new file mode 100644
index 0000000000000000000000000000000000000000..f72166181479d43762423e7e153ee1832760cad0
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/pr94880.c
@@ -0,0 +1,29 @@
+/* PR tree-optimization/94786 */
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-optimized" } */
+/* { dg-final { scan-tree-dump-times "= ~\[xy\]_" 4 "optimized" } } */
+/* { dg-final { scan-tree-dump-times " & \[xy\]_" 4 "optimized" } } */
+
+unsigned
+foo_u(unsigned x, unsigned y)
+{
+  return (x | y) - y;
+}
+
+int
+foo_i(int x, int y)
+{
+  return (x | y) - y;
+}
+
+unsigned long long
+foo_ull(unsigned long long x, unsigned long long y)
+{
+  return (x | y) - y;
+}
+
+long long
+foo_ll(long long x, long long y)
+{
+  return (x | y) - y;
+}
