commit af785bad5cb32ef2bc35503ebbe65414b67ef8b1 Author: Kyrylo Tkachov Date: Tue Jul 14 18:20:28 2015 +0100 [match.pd] optimize (X & C) == N when C is power of 2 diff --git a/gcc/match.pd b/gcc/match.pd index 9cf0278..02ad708 100644 --- a/gcc/match.pd +++ b/gcc/match.pd @@ -266,7 +266,9 @@ along with GCC; see the file COPYING3. If not see /* Optimize TRUNC_MOD_EXPR by a power of two into a BIT_AND_EXPR, i.e. "X % C" into "X & (C - 1)", if X and C are positive. Also optimize A % (C << N) where C is a power of 2, - to A & ((C << N) - 1). */ + to A & ((C << N) - 1). + Optimize (X % C) == N into (X & ((1 << (size - 1)) | (C - 1))) == N + when C is signed, a power of 2 and N is positive. */ (match (power_of_two_cand @1) INTEGER_CST@1) (match (power_of_two_cand @1) @@ -278,7 +280,17 @@ along with GCC; see the file COPYING3. If not see || tree_expr_nonnegative_p (@0)) && tree_nop_conversion_p (type, TREE_TYPE (@3)) && integer_pow2p (@2) && tree_int_cst_sgn (@2) > 0) - (bit_and @0 (convert (minus @1 { build_int_cst (TREE_TYPE (@1), 1); })))))) + (bit_and @0 (convert (minus @1 { build_int_cst (TREE_TYPE (@1), 1); }))))) + + (simplify + (eq (mod @0 (INTEGER_CST@1)) INTEGER_CST@2) + (if (integer_pow2p (@1) && tree_expr_nonnegative_p (@2) + && tree_to_uhwi (@2) < tree_to_uhwi (@1)) + (eq (bit_and @0 + (bit_ior (minus @1 { build_int_cst (TREE_TYPE (@1), 1); }) + { build_int_cst (type, 1 << (tree_to_uhwi (TYPE_SIZE (type)) - 1)); }) + ) + @2)))) /* X % Y is smaller than Y. */ (for cmp (lt ge) diff --git a/gcc/testsuite/gcc.dg/fold-mod-cmp-1.c b/gcc/testsuite/gcc.dg/fold-mod-cmp-1.c new file mode 100644 index 0000000..9dcf313 --- /dev/null +++ b/gcc/testsuite/gcc.dg/fold-mod-cmp-1.c @@ -0,0 +1,12 @@ +/* { dg-do compile } */ +/* { dg-options "-fdump-tree-original" } */ + +int +modcmp (int a) +{ + return (a % 32) == 6; +} + +/* The above should be simplified to (a & -2147483617) == 6. */ +/* { dg-final { scan-tree-dump "& -2147483617" "original" } } */ +/* { dg-final { scan-tree-dump "== 6" "original" } } */