Message ID | alpine.DEB.2.02.1605221922250.4797@laptop-mg.saclay.inria.fr |
---|---|
State | New |
Headers | show |
On Sun, May 22, 2016 at 7:42 PM, Marc Glisse <marc.glisse@inria.fr> wrote: > Hello, > > this patch replaces some tree_nop_conversion_p tests with less restrictive > conditions. In some cases I checked the transformation automatically (of > course I could have messed up the checker, or the translation). I didn't > always put the laxest possible check. For instance the transformation for > (~x & ~y) is valid with sign extension, but the gain is less obvious in that > case. ~(~X >> Y) also seems valid in some odd cases involving boolean types, > not worth the complication. The bad case for a * (1 << b) is when 1<<b turns > into INT_MIN (and then we sign-extend), which I think is valid even with the > strictest overflow rules :-( > > I only did a few transforms because it isn't clear to me that this is worth > it. It makes the validity of the transformation less obvious to the reader > and probably seldom fires in regular code. True conversions also have a cost > that can change if the transformation actually gains anything (may require > extra :s). It could also interfere with a narrowing/promotion pass. > > Bootstrap+regtest on powerpc64le-unknown-linux-gnu. Ok. Thanks, Richard. > 2016-05-23 Marc Glisse <marc.glisse@inria.fr> > > gcc/ > * match.pd (a * (1 << b), ~x & ~y, ~X ^ ~Y, (X ^ Y) ^ Y, ~ (-A), > ~ (A - 1), ~(~X >> Y), ~(~X >>r Y)): Relax constraints. > > gcc/testsuite/ > * gcc.dg/fold-notshift-2.c: Adjust. > > -- > Marc Glisse > Index: gcc/match.pd > =================================================================== > --- gcc/match.pd (revision 236488) > +++ gcc/match.pd (working copy) > @@ -447,21 +447,22 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT) > (for ops (conj negate) > (for cabss (CABS) > (simplify > (cabss (ops @0)) > (cabss @0)))) > > /* Fold (a * (1 << b)) into (a << b) */ > (simplify > (mult:c @0 (convert? (lshift integer_onep@1 @2))) > (if (! FLOAT_TYPE_P (type) > - && tree_nop_conversion_p (type, TREE_TYPE (@1))) > + && (element_precision (type) <= element_precision (TREE_TYPE (@1)) > + || TYPE_UNSIGNED (TREE_TYPE (@1)))) > (lshift @0 @2))) > > /* Fold (C1/X)*C2 into (C1*C2)/X. */ > (simplify > (mult (rdiv@3 REAL_CST@0 @1) REAL_CST@2) > (if (flag_associative_math > && single_use (@3)) > (with > { tree tem = const_binop (MULT_EXPR, type, @0, @2); } > (if (tem) > @@ -648,22 +649,22 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT) > (simplify > (bit_and:c (bit_ior:c @0 @1) (bit_xor:c @1 (bit_not @0))) > (bit_and @0 @1)) > > /* ~x & ~y -> ~(x | y) > ~x | ~y -> ~(x & y) */ > (for op (bit_and bit_ior) > rop (bit_ior bit_and) > (simplify > (op (convert1? (bit_not @0)) (convert2? (bit_not @1))) > - (if (tree_nop_conversion_p (type, TREE_TYPE (@0)) > - && tree_nop_conversion_p (type, TREE_TYPE (@1))) > + (if (element_precision (type) <= element_precision (TREE_TYPE (@0)) > + && element_precision (type) <= element_precision (TREE_TYPE (@1))) > (bit_not (rop (convert @0) (convert @1)))))) > > /* If we are XORing or adding two BIT_AND_EXPR's, both of which are and'ing > with a constant, and the two constants have no bits in common, > we should treat this as a BIT_IOR_EXPR since this may produce more > simplifications. */ > (for op (bit_xor plus) > (simplify > (op (convert1? (bit_and@4 @0 INTEGER_CST@1)) > (convert2? (bit_and@5 @2 INTEGER_CST@3))) > @@ -674,22 +675,22 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT) > > /* (X | Y) ^ X -> Y & ~ X*/ > (simplify > (bit_xor:c (convert? (bit_ior:c @0 @1)) (convert? @0)) > (if (tree_nop_conversion_p (type, TREE_TYPE (@0))) > (convert (bit_and @1 (bit_not @0))))) > > /* Convert ~X ^ ~Y to X ^ Y. */ > (simplify > (bit_xor (convert1? (bit_not @0)) (convert2? (bit_not @1))) > - (if (tree_nop_conversion_p (type, TREE_TYPE (@0)) > - && tree_nop_conversion_p (type, TREE_TYPE (@1))) > + (if (element_precision (type) <= element_precision (TREE_TYPE (@0)) > + && element_precision (type) <= element_precision (TREE_TYPE (@1))) > (bit_xor (convert @0) (convert @1)))) > > /* Convert ~X ^ C to X ^ ~C. */ > (simplify > (bit_xor (convert? (bit_not @0)) INTEGER_CST@1) > (if (tree_nop_conversion_p (type, TREE_TYPE (@0))) > (bit_xor (convert @0) (bit_not @1)))) > > /* Fold (X & Y) ^ Y and (X ^ Y) & Y as ~X & Y. */ > (for opo (bit_and bit_xor) > @@ -715,22 +716,21 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT) > /* Some simple reassociation for bit operations, also handled in reassoc. > */ > /* (X & Y) & Y -> X & Y > (X | Y) | Y -> X | Y */ > (for op (bit_and bit_ior) > (simplify > (op:c (convert?@2 (op:c @0 @1)) (convert? @1)) > @2)) > /* (X ^ Y) ^ Y -> X */ > (simplify > (bit_xor:c (convert? (bit_xor:c @0 @1)) (convert? @1)) > - (if (tree_nop_conversion_p (type, TREE_TYPE (@0))) > - (convert @0))) > + (convert @0)) > /* (X & Y) & (X & Z) -> (X & Y) & Z > (X | Y) | (X | Z) -> (X | Y) | Z */ > (for op (bit_and bit_ior) > (simplify > (op:c (convert1?@3 (op:c@4 @0 @1)) (convert2?@5 (op:c@6 @0 @2))) > (if (tree_nop_conversion_p (type, TREE_TYPE (@1)) > && tree_nop_conversion_p (type, TREE_TYPE (@2))) > (if (single_use (@5) && single_use (@6)) > (op @3 (convert @2)) > (if (single_use (@3) && single_use (@4)) > @@ -908,31 +908,34 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT) > (le @0 @1))) > > /* ~~x -> x */ > (simplify > (bit_not (bit_not @0)) > @0) > > /* Convert ~ (-A) to A - 1. */ > (simplify > (bit_not (convert? (negate @0))) > - (if (tree_nop_conversion_p (type, TREE_TYPE (@0))) > + (if (element_precision (type) <= element_precision (TREE_TYPE (@0)) > + || !TYPE_UNSIGNED (TREE_TYPE (@0))) > (convert (minus @0 { build_each_one_cst (TREE_TYPE (@0)); })))) > > /* Convert ~ (A - 1) or ~ (A + -1) to -A. */ > (simplify > (bit_not (convert? (minus @0 integer_each_onep))) > - (if (tree_nop_conversion_p (type, TREE_TYPE (@0))) > + (if (element_precision (type) <= element_precision (TREE_TYPE (@0)) > + || !TYPE_UNSIGNED (TREE_TYPE (@0))) > (convert (negate @0)))) > (simplify > (bit_not (convert? (plus @0 integer_all_onesp))) > - (if (tree_nop_conversion_p (type, TREE_TYPE (@0))) > + (if (element_precision (type) <= element_precision (TREE_TYPE (@0)) > + || !TYPE_UNSIGNED (TREE_TYPE (@0))) > (convert (negate @0)))) > > /* Part of convert ~(X ^ Y) to ~X ^ Y or X ^ ~Y if ~X or ~Y simplify. */ > (simplify > (bit_not (convert? (bit_xor @0 INTEGER_CST@1))) > (if (tree_nop_conversion_p (type, TREE_TYPE (@0))) > (convert (bit_xor @0 (bit_not @1))))) > (simplify > (bit_not (convert? (bit_xor:c (bit_not @0) @1))) > (if (tree_nop_conversion_p (type, TREE_TYPE (@0))) > @@ -1498,34 +1501,37 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT) > (simplify > (shift (convert?:s (bit_op:s @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_op (shift (convert @0) @1) { mask; })))))) > > /* ~(~X >> Y) -> X >> Y (for arithmetic shift). */ > (simplify > (bit_not (convert1?:s (rshift:s (convert2?@0 (bit_not @1)) @2))) > (if (!TYPE_UNSIGNED (TREE_TYPE (@0)) > - && element_precision (TREE_TYPE (@0)) > - <= element_precision (TREE_TYPE (@1)) > - && element_precision (type) <= element_precision (TREE_TYPE (@0))) > + && (element_precision (TREE_TYPE (@0)) > + <= element_precision (TREE_TYPE (@1)) > + || !TYPE_UNSIGNED (TREE_TYPE (@1)))) > (with > { tree shift_type = TREE_TYPE (@0); } > (convert (rshift (convert:shift_type @1) @2))))) > > /* ~(~X >>r Y) -> X >>r Y > ~(~X <<r Y) -> X <<r Y */ > (for rotate (lrotate rrotate) > (simplify > (bit_not (convert1?:s (rotate:s (convert2?@0 (bit_not @1)) @2))) > - (if (element_precision (TREE_TYPE (@0)) <= element_precision (TREE_TYPE > (@1)) > - && element_precision (type) <= element_precision (TREE_TYPE (@0))) > + (if ((element_precision (TREE_TYPE (@0)) > + <= element_precision (TREE_TYPE (@1)) > + || !TYPE_UNSIGNED (TREE_TYPE (@1))) > + && (element_precision (type) <= element_precision (TREE_TYPE (@0)) > + || !TYPE_UNSIGNED (TREE_TYPE (@0)))) > (with > { tree rotate_type = TREE_TYPE (@0); } > (convert (rotate (convert:rotate_type @1) @2)))))) > > /* Simplifications of conversions. */ > > /* Basic strip-useless-type-conversions / strip_nops. */ > (for cvt (convert view_convert float fix_trunc) > (simplify > (cvt @0) > Index: gcc/testsuite/gcc.dg/fold-notshift-2.c > =================================================================== > --- gcc/testsuite/gcc.dg/fold-notshift-2.c (revision 236488) > +++ gcc/testsuite/gcc.dg/fold-notshift-2.c (working copy) > @@ -8,26 +8,26 @@ lsr (unsigned int a, unsigned int b) > { > return ~((~a) >> b); > } > > int > sl (int a, int b) > { > return ~((~a) << b); > } > > -typedef __INT32_TYPE__ int32_t; > +typedef unsigned __INT32_TYPE__ uint32_t; > typedef __INT64_TYPE__ int64_t; > > int64_t > -asr_widen1 (int32_t a, int b) > +asr_widen1 (uint32_t a, int b) > { > return ~((int64_t)(~a) >> b); > } > > int64_t > -asr_widen2 (int32_t a, int b) > +asr_widen2 (uint32_t a, int b) > { > return ~(int64_t)(~a >> b); > } > > /* { dg-final { scan-tree-dump-times "~" 8 "cddce1" } } */ >
Index: gcc/match.pd =================================================================== --- gcc/match.pd (revision 236488) +++ gcc/match.pd (working copy) @@ -447,21 +447,22 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT) (for ops (conj negate) (for cabss (CABS) (simplify (cabss (ops @0)) (cabss @0)))) /* Fold (a * (1 << b)) into (a << b) */ (simplify (mult:c @0 (convert? (lshift integer_onep@1 @2))) (if (! FLOAT_TYPE_P (type) - && tree_nop_conversion_p (type, TREE_TYPE (@1))) + && (element_precision (type) <= element_precision (TREE_TYPE (@1)) + || TYPE_UNSIGNED (TREE_TYPE (@1)))) (lshift @0 @2))) /* Fold (C1/X)*C2 into (C1*C2)/X. */ (simplify (mult (rdiv@3 REAL_CST@0 @1) REAL_CST@2) (if (flag_associative_math && single_use (@3)) (with { tree tem = const_binop (MULT_EXPR, type, @0, @2); } (if (tem) @@ -648,22 +649,22 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT) (simplify (bit_and:c (bit_ior:c @0 @1) (bit_xor:c @1 (bit_not @0))) (bit_and @0 @1)) /* ~x & ~y -> ~(x | y) ~x | ~y -> ~(x & y) */ (for op (bit_and bit_ior) rop (bit_ior bit_and) (simplify (op (convert1? (bit_not @0)) (convert2? (bit_not @1))) - (if (tree_nop_conversion_p (type, TREE_TYPE (@0)) - && tree_nop_conversion_p (type, TREE_TYPE (@1))) + (if (element_precision (type) <= element_precision (TREE_TYPE (@0)) + && element_precision (type) <= element_precision (TREE_TYPE (@1))) (bit_not (rop (convert @0) (convert @1)))))) /* If we are XORing or adding two BIT_AND_EXPR's, both of which are and'ing with a constant, and the two constants have no bits in common, we should treat this as a BIT_IOR_EXPR since this may produce more simplifications. */ (for op (bit_xor plus) (simplify (op (convert1? (bit_and@4 @0 INTEGER_CST@1)) (convert2? (bit_and@5 @2 INTEGER_CST@3))) @@ -674,22 +675,22 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT) /* (X | Y) ^ X -> Y & ~ X*/ (simplify (bit_xor:c (convert? (bit_ior:c @0 @1)) (convert? @0)) (if (tree_nop_conversion_p (type, TREE_TYPE (@0))) (convert (bit_and @1 (bit_not @0))))) /* Convert ~X ^ ~Y to X ^ Y. */ (simplify (bit_xor (convert1? (bit_not @0)) (convert2? (bit_not @1))) - (if (tree_nop_conversion_p (type, TREE_TYPE (@0)) - && tree_nop_conversion_p (type, TREE_TYPE (@1))) + (if (element_precision (type) <= element_precision (TREE_TYPE (@0)) + && element_precision (type) <= element_precision (TREE_TYPE (@1))) (bit_xor (convert @0) (convert @1)))) /* Convert ~X ^ C to X ^ ~C. */ (simplify (bit_xor (convert? (bit_not @0)) INTEGER_CST@1) (if (tree_nop_conversion_p (type, TREE_TYPE (@0))) (bit_xor (convert @0) (bit_not @1)))) /* Fold (X & Y) ^ Y and (X ^ Y) & Y as ~X & Y. */ (for opo (bit_and bit_xor) @@ -715,22 +716,21 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT) /* Some simple reassociation for bit operations, also handled in reassoc. */ /* (X & Y) & Y -> X & Y (X | Y) | Y -> X | Y */ (for op (bit_and bit_ior) (simplify (op:c (convert?@2 (op:c @0 @1)) (convert? @1)) @2)) /* (X ^ Y) ^ Y -> X */ (simplify (bit_xor:c (convert? (bit_xor:c @0 @1)) (convert? @1)) - (if (tree_nop_conversion_p (type, TREE_TYPE (@0))) - (convert @0))) + (convert @0)) /* (X & Y) & (X & Z) -> (X & Y) & Z (X | Y) | (X | Z) -> (X | Y) | Z */ (for op (bit_and bit_ior) (simplify (op:c (convert1?@3 (op:c@4 @0 @1)) (convert2?@5 (op:c@6 @0 @2))) (if (tree_nop_conversion_p (type, TREE_TYPE (@1)) && tree_nop_conversion_p (type, TREE_TYPE (@2))) (if (single_use (@5) && single_use (@6)) (op @3 (convert @2)) (if (single_use (@3) && single_use (@4)) @@ -908,31 +908,34 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT) (le @0 @1))) /* ~~x -> x */ (simplify (bit_not (bit_not @0)) @0) /* Convert ~ (-A) to A - 1. */ (simplify (bit_not (convert? (negate @0))) - (if (tree_nop_conversion_p (type, TREE_TYPE (@0))) + (if (element_precision (type) <= element_precision (TREE_TYPE (@0)) + || !TYPE_UNSIGNED (TREE_TYPE (@0))) (convert (minus @0 { build_each_one_cst (TREE_TYPE (@0)); })))) /* Convert ~ (A - 1) or ~ (A + -1) to -A. */ (simplify (bit_not (convert? (minus @0 integer_each_onep))) - (if (tree_nop_conversion_p (type, TREE_TYPE (@0))) + (if (element_precision (type) <= element_precision (TREE_TYPE (@0)) + || !TYPE_UNSIGNED (TREE_TYPE (@0))) (convert (negate @0)))) (simplify (bit_not (convert? (plus @0 integer_all_onesp))) - (if (tree_nop_conversion_p (type, TREE_TYPE (@0))) + (if (element_precision (type) <= element_precision (TREE_TYPE (@0)) + || !TYPE_UNSIGNED (TREE_TYPE (@0))) (convert (negate @0)))) /* Part of convert ~(X ^ Y) to ~X ^ Y or X ^ ~Y if ~X or ~Y simplify. */ (simplify (bit_not (convert? (bit_xor @0 INTEGER_CST@1))) (if (tree_nop_conversion_p (type, TREE_TYPE (@0))) (convert (bit_xor @0 (bit_not @1))))) (simplify (bit_not (convert? (bit_xor:c (bit_not @0) @1))) (if (tree_nop_conversion_p (type, TREE_TYPE (@0))) @@ -1498,34 +1501,37 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT) (simplify (shift (convert?:s (bit_op:s @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_op (shift (convert @0) @1) { mask; })))))) /* ~(~X >> Y) -> X >> Y (for arithmetic shift). */ (simplify (bit_not (convert1?:s (rshift:s (convert2?@0 (bit_not @1)) @2))) (if (!TYPE_UNSIGNED (TREE_TYPE (@0)) - && element_precision (TREE_TYPE (@0)) - <= element_precision (TREE_TYPE (@1)) - && element_precision (type) <= element_precision (TREE_TYPE (@0))) + && (element_precision (TREE_TYPE (@0)) + <= element_precision (TREE_TYPE (@1)) + || !TYPE_UNSIGNED (TREE_TYPE (@1)))) (with { tree shift_type = TREE_TYPE (@0); } (convert (rshift (convert:shift_type @1) @2))))) /* ~(~X >>r Y) -> X >>r Y ~(~X <<r Y) -> X <<r Y */ (for rotate (lrotate rrotate) (simplify (bit_not (convert1?:s (rotate:s (convert2?@0 (bit_not @1)) @2))) - (if (element_precision (TREE_TYPE (@0)) <= element_precision (TREE_TYPE (@1)) - && element_precision (type) <= element_precision (TREE_TYPE (@0))) + (if ((element_precision (TREE_TYPE (@0)) + <= element_precision (TREE_TYPE (@1)) + || !TYPE_UNSIGNED (TREE_TYPE (@1))) + && (element_precision (type) <= element_precision (TREE_TYPE (@0)) + || !TYPE_UNSIGNED (TREE_TYPE (@0)))) (with { tree rotate_type = TREE_TYPE (@0); } (convert (rotate (convert:rotate_type @1) @2)))))) /* Simplifications of conversions. */ /* Basic strip-useless-type-conversions / strip_nops. */ (for cvt (convert view_convert float fix_trunc) (simplify (cvt @0) Index: gcc/testsuite/gcc.dg/fold-notshift-2.c =================================================================== --- gcc/testsuite/gcc.dg/fold-notshift-2.c (revision 236488) +++ gcc/testsuite/gcc.dg/fold-notshift-2.c (working copy) @@ -8,26 +8,26 @@ lsr (unsigned int a, unsigned int b) { return ~((~a) >> b); } int sl (int a, int b) { return ~((~a) << b); } -typedef __INT32_TYPE__ int32_t; +typedef unsigned __INT32_TYPE__ uint32_t; typedef __INT64_TYPE__ int64_t; int64_t -asr_widen1 (int32_t a, int b) +asr_widen1 (uint32_t a, int b) { return ~((int64_t)(~a) >> b); } int64_t -asr_widen2 (int32_t a, int b) +asr_widen2 (uint32_t a, int b) { return ~(int64_t)(~a >> b); } /* { dg-final { scan-tree-dump-times "~" 8 "cddce1" } } */