On Wed, Oct 7, 2015 at 11:54 AM, Hurugalawadi, Naveen <naveen.hurugalaw...@caviumnetworks.com> wrote: > Hi, > > Please find attached the patch that moves some more patterns from > fold-const using simplify and match. > > Please review the patch and let me know if any modifications are required.
+/* Fold X + (X / CST) * -CST to X % CST. */ +(simplify + (plus @0 (mult:s (trunc_div:s @0 INTEGER_CST@1) (negate @1))) that's a bit too literal -- (negate @1) won't match for -@1 + (if (INTEGRAL_TYPE_P (type) || VECTOR_INTEGER_TYPE_P (type)) + (trunc_mod @0 @1))) +/* Fold (A & ~B) - (A & B) into (A ^ B) - B. */ +(simplify + (minus (bit_and:s @0 (bit_not:s @1)) (bit_and:s @0 @1)) + (if (! FLOAT_TYPE_P (type)) + (minus (bit_xor @0 @1) @1))) Likewise the fold code handles both constant and non-constant B. To mimic this you need a second pattern for the constant case or add a predicate matching @1 with ~@1. +/* (-A) * (-B) -> A * B */ +(simplify + (mult:c (negate @0) (negate @1)) + (mult @0 @1)) the fold-const.c code handles sign-conversions around the negates so you should add (convert?)s around them and verify useless_type_conversions. +/* Fold (a * (1 << b)) into (a << b) */ +(simplify + (mult:c @0 (lshift integer_onep@1 @2)) + (if (! FLOAT_TYPE_P (type)) + (lshift @0 @2))) Likewise (sign-conversion on the lshift). Though I'm not sure this won't trap ubsan for signed left-shift of negative values. +/* Fold (C1/X)*C2 into (C1*C2)/X. */ +(simplify + (mult (rdiv REAL_CST@0 @1) REAL_CST@2) + (if (FLOAT_TYPE_P (type) + && flag_associative_math) + (rdiv (mult @0 @2) @1))) the fold-const.c code avoids the transform if @0 * @2 doesn't simplify (nans/infs and flag combos). Not sure if we care though. +/* Simplify (X & ~Y) | (~X & Y) is X ^ Y. */ +(simplify + (bit_ior (bit_and:s @0 (bit_not:s @1)) (bit_and:s (bit_not:s @0) @1)) + (bit_xor @0 @1)) fold again handles also constants for X and Y. I suggest to re-use the matching predicate you need to add for the above ~ pattern. fold also handles sign-converted bit-ands. +/* Simplify ~X & X as zero. */ +(simplify + (bit_and:c @0 (bit_not:s @0)) + { build_zero_cst (type); }) I was sure we already have this... looks I was wrong. Again fold handles sign-conversions on @0 resp. the bit_not. +/* Simplify (X == 0) & X as zero. */ +(simplify + (bit_and:c @0 (eq @0 integer_zerop@1)) + @1) I think we have this one see logical_inverted_value and uses: (simplify (bit_and:c @0 (logical_inverted_value @0)) { build_zero_cst (type); }) +/* Fold X & (X ^ Y) as X & ~Y. */ +(simplify + (bit_and @0 (bit_xor:s @0 @1)) + (bit_and @0 (bit_not @1))) + +/* Fold X & (Y ^ X) as ~Y & X. */ +(simplify + (bit_and @0 (bit_xor:s @1 @0)) + (bit_and (bit_not @1) @0)) add :c on the bit_and and the bit_xor and then merge the patterns. Thanks, Richard. > Tested the patch on X86 without any regressions. > > Thanks, > Naveen > > ChangeLog > > 2015-10-07 Naveen H.S <naveen.hurugalaw...@caviumnetworks.com> > > * fold-const.c (fold_binary_loc) : Move X + (X / CST) * -CST -> > X % CST to match.pd. > Move Fold (A & ~B) - (A & B) into (A ^ B) - B to match.pd. > Move (-A) * (-B) -> A * B to match.pd. > Move (a * (1 << b)) is (a << b) to match.pd. > Move convert (C1/X)*C2 into (C1*C2)/X to match.pd. > Move (X & ~Y) | (~X & Y) is X ^ Y to match.pd. > Move ~X & X, (X == 0) & X, and !X & X are zero to match.pd. > Move X & ~X , X & (X == 0), and X & !X are zero to match.pd. > Move Fold X & (X ^ Y) as X & ~Y to match.pd. > Move Fold X & (Y ^ X) as ~Y & X to match.pd. > > * match.pd (plus @0 (mult:s (trunc_div:s @0 INTEGER_CST@1) > (negate @1))): New simplifier. > (minus (bit_and:s @0 (bit_not:s @1)) (bit_and:s @0 @1)) : > New simplifier. > (mult:c @0 (lshift integer_onep@1 @2)): New simplifier. > (mult:c (plus @0 @0) INTEGER_CST@1): New simplifier. > (mult (rdiv REAL_CST@0 @1) REAL_CST@2): New simplifier. > (bit_ior (bit_and:s @0 (bit_not:s @1)) (bit_and:s (bit_not:s @0) @1)) > : New simplifier. > (bit_and:c @0 (bit_not:s @0)): New simplifier. > (bit_and:c @0 (eq @0 integer_zerop@1)): New simplifier. > (bit_and @0 (bit_xor:s @0 @1)): New simplifier. > (bit_and @0 (bit_xor:s @1 @0)): New simplifier. > (mult:c (negate @0) (negate @1)): New simplifier.