We had a pattern for `X % Y < Y` when X and Y where non-negative but
this can be generalized for all values. And also we can handle `>=` too.
Bootstrapped and tested on x86_64-pc-linux-gnu
PR tree-optimization/125737
gcc:
* match.pd: Optimize X % Y < Y -> Y >= 0 and X % Y >= Y -> Y < 0
gcc/testsuite:
* gcc.dg/pr125737.c: Move test to pr125737-1.c.
* gcc.dg/pr125737-1.c: Add test for (a % b) >= b when a and b are nonnegative.
* gcc.dg/pr125737-2.c: New test for (a % b) {<,>=} b.
Signed-off-by: Kael Franco <kaelfandrew@gmail.com>
wi::max_value (TYPE_PRECISION (TREE_TYPE (@0)), SIGNED)))
(resop @2 { build_zero_cst (TREE_TYPE (@2)); }))))
-/* X % Y is smaller than Y. */
-(for cmp (lt ge)
+/* X % Y < Y -> Y >= 0
+ X % Y >= Y -> Y < 0 */
+(for ltge (lt ge)
+ gelt (ge lt)
(simplify
- (cmp:c (trunc_mod tree_expr_nonnegative_p@0 tree_expr_nonnegative_p@1) @1)
- { constant_boolean_node (cmp == LT_EXPR, type); }))
+ (ltge:c (trunc_mod @0 @1) @1)
+ (gelt @1 { build_zero_cst (TREE_TYPE (@1)); })))
/* x | ~0 -> ~0 */
(simplify
return c < bb;
}
-/* { dg-final { scan-tree-dump-times "return 1;" 1 "optimized" } } */
+int
+g (unsigned short a, unsigned short b) {
+ int aa = a;
+ int bb = b;
+ int c = aa % bb;
+ return (c >= bb) == 0;
+}
+
+/* { dg-final { scan-tree-dump-times "return 1;" 2 "optimized" } } */
--- /dev/null
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-optimized" } */
+
+_Bool
+a_mod_b_lt_b (int a, int b) {
+ return ((a % b) < b) == (b >= 0);
+}
+
+_Bool
+a_mod_b_ge_b (int a, int b) {
+ return ((a % b) >= b) == (b < 0);
+}
+
+/* { dg-final { scan-tree-dump-times "return 1;" 2 "optimized" } } */