Move some bit and binary optimizations in simplify and match
Richard Biener
richard.guenther@gmail.com
Thu Oct 8 13:39:00 GMT 2015
On Wed, Oct 7, 2015 at 11:54 AM, Hurugalawadi, Naveen
<Naveen.Hurugalawadi@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.Hurugalawadi@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.
More information about the Gcc-patches
mailing list