This moves a few more patterns that show up during bootstrap. Bootstrapped and tested on x86_64-unknown-linux-gnu, applied to trunk.
Richard. 2015-07-07 Richard Biener <rguent...@suse.de> * fold-const.c (fold_binary_loc): Move (X & C2) << C1 -> (X << C1) & (C2 << C1) simplification ... * match.pd: ... here. Add (X * C1) % C2 -> 0 simplification pattern derived from extract_muldiv_1. * gcc.dg/vect/vect-over-widen-3-big-array.c: Adjust. Index: gcc/match.pd =================================================================== --- gcc/match.pd (revision 225504) +++ gcc/match.pd (working copy) @@ -230,7 +230,14 @@ (define_operator_list CBRT BUILT_IN_CBRT /* (X % Y) % Y is just X % Y. */ (simplify (mod (mod@2 @0 @1) @1) - @2)) + @2) + /* From extract_muldiv_1: (X * C1) % C2 is zero if C1 is a multiple of C2. */ + (simplify + (mod (mult @0 INTEGER_CST@1) INTEGER_CST@2) + (if (ANY_INTEGRAL_TYPE_P (type) + && TYPE_OVERFLOW_UNDEFINED (type) + && wi::multiple_of_p (@1, @2, TYPE_SIGN (type))) + { build_zero_cst (type); }))) /* X % -C is the same as X % C. */ (simplify @@ -992,6 +999,16 @@ (define_operator_list CBRT BUILT_IN_CBRT (if (shift_type == TREE_TYPE (@3)) (bit_and @4 { newmaskt; })))))))))))) +/* Fold (X & C2) << C1 into (X << C1) & (C2 << C1) + (X & C2) >> C1 into (X >> C1) & (C2 >> C1). */ +(for shift (lshift rshift) + (simplify + (shift (convert? (bit_and @0 INTEGER_CST@2)) INTEGER_CST@1) + (if (tree_nop_conversion_p (type, TREE_TYPE (@0))) + (with { tree mask = int_const_binop (shift, fold_convert (type, @2), @1); } + (bit_and (shift (convert @0) @1) { mask; }))))) + + /* Simplifications of conversions. */ /* Basic strip-useless-type-conversions / strip_nops. */ Index: gcc/fold-const.c =================================================================== --- gcc/fold-const.c (revision 225504) +++ gcc/fold-const.c (working copy) @@ -11194,27 +11140,6 @@ fold_binary_loc (location_t loc, prec) == 0) return TREE_OPERAND (arg0, 0); - /* Fold (X & C2) << C1 into (X << C1) & (C2 << C1) - (X & C2) >> C1 into (X >> C1) & (C2 >> C1) - if the latter can be further optimized. */ - if ((code == LSHIFT_EXPR || code == RSHIFT_EXPR) - && TREE_CODE (arg0) == BIT_AND_EXPR - && TREE_CODE (arg1) == INTEGER_CST - && TREE_CODE (TREE_OPERAND (arg0, 1)) == INTEGER_CST) - { - tree mask = fold_build2_loc (loc, code, type, - fold_convert_loc (loc, type, - TREE_OPERAND (arg0, 1)), - arg1); - tree shift = fold_build2_loc (loc, code, type, - fold_convert_loc (loc, type, - TREE_OPERAND (arg0, 0)), - arg1); - tem = fold_binary_loc (loc, BIT_AND_EXPR, type, shift, mask); - if (tem) - return tem; - } - return NULL_TREE; case MIN_EXPR: Index: gcc/testsuite/gcc.dg/vect/vect-over-widen-3-big-array.c =================================================================== --- gcc/testsuite/gcc.dg/vect/vect-over-widen-3-big-array.c (revision 225504) +++ gcc/testsuite/gcc.dg/vect/vect-over-widen-3-big-array.c (working copy) @@ -58,6 +58,6 @@ int main (void) return 0; } -/* { dg-final { scan-tree-dump-times "vect_recog_over_widening_pattern: detected" 1 "vect" } } */ +/* { dg-final { scan-tree-dump-times "vect_recog_over_widening_pattern: detected" 2 "vect" } } */ /* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" } } */