&& wi::to_wide (@1) != wi::min_value (TYPE_PRECISION (type),
SIGNED))
(minus (plus @1 { build_minus_one_cst (type); }) @0))))
+
+/* ~(X >> Y) -> ~X >> Y if ~X can be simplified. */
+(simplify
+ (bit_not (rshift:s @0 @1))
+ (if (!TYPE_UNSIGNED (TREE_TYPE (@0)))
+ (rshift (bit_not! @0) @1)
+ /* For logical right shifts, this is possible only if @0 doesn't
+ have MSB set and the logical right shift is changed into
+ arithmetic shift. */
+ (if (!wi::neg_p (tree_nonzero_bits (@0)))
+ (with { tree stype = signed_type_for (TREE_TYPE (@0)); }
+ (convert (rshift (bit_not! (convert:stype @0)) @1))))))
#endif
/* x + (x & 1) -> (x + 1) & ~1 */
--- /dev/null
+/* PR tree-optimization/96688 */
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-optimized" } */
+/* { dg-final { scan-tree-dump-times " = -124 >> " 2 "optimized" } } */
+/* { dg-final { scan-tree-dump-times " >> " 3 "optimized" } } */
+/* { dg-final { scan-tree-dump-times " = ~" 1 "optimized" } } */
+
+int
+foo (int x)
+{
+ return ~(123 >> x);
+}
+
+unsigned
+bar (int x)
+{
+ return ~(123U >> x);
+}
+
+unsigned
+baz (int x)
+{
+ return ~(~123U >> x);
+}
}
/* Check if the tests have been folded into a bit test. */
-/* { dg-final { scan-tree-dump "(8784908|0x0*860c0c)" "optimized" { target i?86-*-* x86_64-*-* } } } */
+/* { dg-final { scan-tree-dump "(8784908|-8784909|0x0*860c0c)" "optimized" { target i?86-*-* x86_64-*-* } } } */
/* { dg-final { scan-tree-dump "(<<|>>)" "optimized" { target i?86-*-* x86_64-*-* } } } */
}
/* Check if the tests have been folded into a bit test. */
-/* { dg-final { scan-tree-dump "(8784908|0x0*860c0c)" "optimized" } } */
+/* { dg-final { scan-tree-dump "(8784908|-8784909|0x0*860c0c)" "optimized" } } */
/* { dg-final { scan-tree-dump "(<<|>>)" "optimized" } } */