@@ -7836,3 +7836,15 @@ and,
(match (bitwise_induction_p @0 @2 @3)
(bit_not
(nop_convert1? (bit_xor@0 (convert2? (lshift integer_onep@1 @2)) @3))))
+
+/* n - (((n > C1) ? n : C1) & -C2) -> n & C1 for unsigned case.
+ n - (((n > C1) ? n : C1) & -C2) -> (n <= C1) ? n : (n & C1) for signed case. */
+(simplify
+ (minus @0 (bit_and (max @0 INTEGER_CST@1) INTEGER_CST@2))
+ (with { auto i = wi::neg (wi::to_wide (@2)); }
+ /* Check if -C2 is a power of 2 and C1 = -C2 - 1. */
+ (if (wi::popcount (i) == 1
+ && (wi::to_wide (@1)) == (i - 1))
+ (if (TYPE_UNSIGNED (TREE_TYPE (@0)))
+ (bit_and @0 @1)
+ (cond (le @0 @1) @0 (bit_and @0 @1))))))
new file mode 100644
@@ -0,0 +1,37 @@
+/* PR tree-optimization/98304 */
+
+#include "../../gcc.dg/pr98304-1.c"
+
+/* Runtime tests. */
+int main() {
+
+ /* Signed tests. */
+ if (foo(-42) != -42
+ || foo(0) != 0
+ || foo(63) != 63
+ || foo(64) != 0
+ || foo(65) != 1
+ || foo(99) != 35) {
+ __builtin_abort();
+ }
+
+ /* Unsigned tests. */
+ if (bar(42) != 42
+ || bar(0) != 0
+ || bar(63) != 63
+ || bar(64) != 0
+ || bar(65) != 1
+ || bar(99) != 35) {
+ __builtin_abort();
+ }
+
+ /* Should not simplify. */
+ if (corge(13) != 13
+ || thud(13) != 13
+ || qux(13) != 13
+ || quux(13) != 13) {
+ __builtin_abort();
+ }
+
+ return 0;
+}
new file mode 100644
@@ -0,0 +1,57 @@
+/* PR tree-optimization/98304 */
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-optimized" } */
+
+/* Signed test function. */
+__attribute__((noipa)) int foo(int n) {
+ return n - (((n > 63) ? n : 63) & -64);
+}
+
+/* Unsigned test function. */
+__attribute__((noipa)) unsigned int bar(unsigned int n) {
+ return n - (((n > 63) ? n : 63) & -64);
+}
+
+/* Different power of 2. */
+__attribute__((noipa)) int goo(int n) {
+ return n - (((n > 31) ? n : 31) & -32);
+}
+
+/* Commutative property (should be identical to foo) */
+__attribute__((noipa)) int baz(int n) {
+ return n - (((64 > n) ? 63 : n) & -64);
+}
+
+/* < instead of >. */
+__attribute__((noipa)) int fred(int n) {
+ return n - (((63 < n) ? n : 63) & -64);
+}
+
+/* Constant is not a power of 2 so should not simplify. */
+__attribute__((noipa)) int qux(int n) {
+ return n - (((n > 62) ? n : 62) & -63);
+}
+
+/* Constant is not a power of 2 so should not simplify. */
+__attribute__((noipa)) unsigned int quux(unsigned int n) {
+ return n - (((n > 62) ? n : 62) & -63);
+}
+
+/* Constant is a variable so should not simplify. */
+__attribute__((noipa)) int waldo(int n, int x) {
+ return n - (((n > 63) ? n : 63) & x);
+}
+
+/* Difference between constants is not -1. */
+__attribute__((noipa)) int corge(int n) {
+ return n - (((n > 1) ? n : 1) & -64);
+}
+
+/* Difference between constants is not -1. */
+__attribute__((noipa)) unsigned int thud(unsigned int n)
+{
+ return n - (((n > 1) ? n : 1) & -64);
+}
+
+/* { dg-final { scan-tree-dump-times " - " 5 "optimized" } } */
+/* { dg-final { scan-tree-dump-times " <= " 4 "optimized" } } */