Hello,after this patch I think I'll close the PR. This was regtested on ppc64le-redhat-linux.
Apparently I wrote this patch in a file that already had a trivial hunk: -1-A -> ~A is rejected for complex while -A-1 isn't, there is no reason for this difference (maybe there was before integer_all_onesp / integer_minus_onep was introduced), I hope you don't mind.
I am wondering if we want some helper (like :c for commutative operations) to avoid duplicating patterns for x<y and y>x. We could also, when a comparison x<=y doesn't simplify, see if !!(x<=y) simplifies better, but that's becoming a bit complicated.
2015-05-15 Marc Glisse <marc.gli...@inria.fr> PR tree-optimization/64454 gcc/ * match.pd ((X % Y) % Y, (X % Y) < Y): New patterns. (-1 - A -> ~A): Remove unnecessary condition. gcc/testsuite/ * gcc.dg/modmod.c: New testcase. -- Marc Glisse
Index: gcc/match.pd =================================================================== --- gcc/match.pd (revision 223199) +++ gcc/match.pd (working copy) @@ -204,33 +204,49 @@ along with GCC; see the file COPYING3. (if (!integer_zerop (@1)) @0)) /* X % 1 is always zero. */ (simplify (mod @0 integer_onep) { build_zero_cst (type); }) /* X % -1 is zero. */ (simplify (mod @0 integer_minus_onep@1) (if (!TYPE_UNSIGNED (type)) - { build_zero_cst (type); }))) + { build_zero_cst (type); })) + /* (X % Y) % Y is just X % Y. */ + (simplify + (mod (mod@2 @0 @1) @1) + @2)) /* X % -C is the same as X % C. */ (simplify (trunc_mod @0 INTEGER_CST@1) (if (TYPE_SIGN (type) == SIGNED && !TREE_OVERFLOW (@1) && wi::neg_p (@1) && !TYPE_OVERFLOW_TRAPS (type) /* Avoid this transformation if C is INT_MIN, i.e. C == -C. */ && !sign_bit_p (@1, @1)) (trunc_mod @0 (negate @1)))) +/* X % Y is smaller than Y. */ +(for cmp (lt ge) + (simplify + (cmp (trunc_mod @0 @1) @1) + (if (TYPE_UNSIGNED (TREE_TYPE (@0))) + { constant_boolean_node (cmp == LT_EXPR, type); }))) +(for cmp (gt le) + (simplify + (cmp @1 (trunc_mod @0 @1)) + (if (TYPE_UNSIGNED (TREE_TYPE (@0))) + { constant_boolean_node (cmp == GT_EXPR, type); }))) + /* x | ~0 -> ~0 */ (simplify (bit_ior @0 integer_all_onesp@1) @1) /* x & 0 -> 0 */ (simplify (bit_and @0 integer_zerop@1) @1) @@ -526,22 +542,21 @@ along with GCC; see the file COPYING3. /* -A - 1 -> ~A */ (simplify (minus (convert? (negate @0)) integer_each_onep) (if (!TYPE_OVERFLOW_TRAPS (type) && tree_nop_conversion_p (type, TREE_TYPE (@0))) (bit_not (convert @0)))) /* -1 - A -> ~A */ (simplify (minus integer_all_onesp @0) - (if (TREE_CODE (type) != COMPLEX_TYPE) - (bit_not @0))) + (bit_not @0)) /* (T)(P + A) - (T)P -> (T) A */ (for add (plus pointer_plus) (simplify (minus (convert (add @0 @1)) (convert @0)) (if (element_precision (type) <= element_precision (TREE_TYPE (@1)) /* For integer types, if A has a smaller type than T the result depends on the possible overflow in P + A. Index: gcc/testsuite/gcc.dg/modmod.c =================================================================== --- gcc/testsuite/gcc.dg/modmod.c (revision 0) +++ gcc/testsuite/gcc.dg/modmod.c (working copy) @@ -0,0 +1,13 @@ +/* { dg-options "-O -fdump-tree-optimized-raw" } */ + +int f(int a, int b){ + a %= b; + return a % b; +} +int g(unsigned a, unsigned b){ + a %= b; + return a < b; +} + +/* { dg-final { scan-tree-dump-times "trunc_mod_expr" 1 "optimized" } } */ +/* { dg-final { cleanup-tree-dump "optimized" } } */