On Thu, 7 Dec 2017, Jakub Jelinek wrote:

> Hi!
> 
> When committing the previous PR81281 patch, I've removed all the @@0 cases
> on plus:c, used @0 instead, to make sure we don't regress.
> 
> This patch readds those where possible.  For the cases where there is
> just P and A, it was mostly a matter of @@0 and convert? instead of convert
> plus using type from @1 instead of @0, though if @0 is INTEGER_CST, what we
> usually end up with is a (plus (convert (plus @1 @0) @2) where @2 negated
> is equal to @0, so the patch adds a simplification for that too.
> 
> For the case with P, A and B, the patch limits it to the case where either
> both A and B are narrower or both are wider.
> 
> Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk?

Comments below.

> 2017-12-07  Jakub Jelinek  <ja...@redhat.com>
> 
>       PR sanitizer/81281
>       * match.pd ((T)(P + A) - (T)P -> (T) A): Use @@0 instead of @0 and
>       convert? on @0 instead of convert.  Check type of @1, not @0.
>       Add a simplify for (T)(P + A) + Q where -Q is equal to P.
>       ((T)P - (T)(P + A) -> -(T) A): Use @@0 instead of @0 and
>       convert? on @0 instead of convert.  Check type of @1, not @0.
>       ((T)(P + A) - (T)(P + B) -> (T)A - (T)B): Use @@0 instead of @0,
>       only optimize if either both @1 and @2 types are narrower
>       precision, or both are wider or equal precision, and in the former
>       case only if both have undefined overflow.
> 
>       * gcc.dg/pr81281-3.c: New test.
> 
> --- gcc/match.pd.jj   2017-12-07 14:00:51.083048186 +0100
> +++ gcc/match.pd      2017-12-07 15:17:49.132784931 +0100
> @@ -1784,8 +1784,8 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
>  
>    /* (T)(P + A) - (T)P -> (T) A */
>    (simplify
> -   (minus (convert (plus:c @0 @1))
> -    (convert @0))
> +   (minus (convert (plus:c @@0 @1))
> +    (convert? @0))
>     (if (element_precision (type) <= element_precision (TREE_TYPE (@1))
>       /* For integer types, if A has a smaller type
>          than T the result depends on the possible
> @@ -1794,10 +1794,29 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
>          However, if an overflow in P + A would cause
>          undefined behavior, we can assume that there
>          is no overflow.  */
> -     || (INTEGRAL_TYPE_P (TREE_TYPE (@0))
> -         && TYPE_OVERFLOW_UNDEFINED (TREE_TYPE (@0))))
> +     || (INTEGRAL_TYPE_P (TREE_TYPE (@1))
> +         && TYPE_OVERFLOW_UNDEFINED (TREE_TYPE (@1))))

Given @1 and @@0 are in the same plus this change isn't technically
necessary but it makes it clearer which type we look at (thus ok).

>      (convert @1)))
>    (simplify
> +   (plus (convert (plus @1 INTEGER_CST@0)) INTEGER_CST@2)
> +   (with { bool overflow;
> +        wide_int w = wi::neg (wi::to_wide (@2), &overflow); }
> +    (if (wi::to_widest (@0) == widest_int::from (w, TYPE_SIGN (TREE_TYPE 
> (@2)))
> +      && (!overflow
> +          || (INTEGRAL_TYPE_P (TREE_TYPE (@2))
> +              && TYPE_UNSIGNED (TREE_TYPE (@2))))
> +      && (element_precision (type) <= element_precision (TREE_TYPE (@1))
> +          /* For integer types, if A has a smaller type
> +             than T the result depends on the possible
> +             overflow in P + A.
> +             E.g. T=size_t, A=(unsigned)429497295, P>0.
> +             However, if an overflow in P + A would cause
> +             undefined behavior, we can assume that there
> +             is no overflow.  */
> +          || (INTEGRAL_TYPE_P (TREE_TYPE (@1))
> +              && TYPE_OVERFLOW_UNDEFINED (TREE_TYPE (@1)))))

I think we don't need to worry about definedness of overflow.  All
that matters is whether twos complement arithmetic will simplify
the expression to (convert @1).  Specifically the possible overflow
of the negation of @2 for the case element_precision (type) <= 
element_precision (TREE_TYPE (@1)) shouldn't matter, likewise
for the widening case (we'd never get the equality).

Don't we want to compare @0 and -@2 in the type of @2?  Like
for (unsigned int)(unsigned-long-x + 0x100000005) + -5U which
we should be able to simplify?  For the widening case that would
work as well as far as I can see?

If you can split out this new pattern the rest is ok with honoring
the comment below.

> +     (convert @1))))
> +  (simplify
>     (minus (convert (pointer_plus @@0 @1))
>      (convert @0))
>     (if (element_precision (type) <= element_precision (TREE_TYPE (@1))
> @@ -1818,8 +1837,8 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
>  
>    /* (T)P - (T)(P + A) -> -(T) A */
>    (simplify
> -   (minus (convert @0)
> -    (convert (plus:c @0 @1)))
> +   (minus (convert? @0)
> +    (convert (plus:c @@0 @1)))
>     (if (INTEGRAL_TYPE_P (type)
>       && TYPE_OVERFLOW_UNDEFINED (type)
>       && element_precision (type) <= element_precision (TREE_TYPE (@1)))
> @@ -1833,8 +1852,8 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
>           However, if an overflow in P + A would cause
>           undefined behavior, we can assume that there
>           is no overflow.  */
> -      || (INTEGRAL_TYPE_P (TREE_TYPE (@0))
> -          && TYPE_OVERFLOW_UNDEFINED (TREE_TYPE (@0))))
> +      || (INTEGRAL_TYPE_P (TREE_TYPE (@1))
> +          && TYPE_OVERFLOW_UNDEFINED (TREE_TYPE (@1))))
>       (negate (convert @1)))))
>    (simplify
>     (minus (convert @0)
> @@ -1862,23 +1881,28 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
>  
>    /* (T)(P + A) - (T)(P + B) -> (T)A - (T)B */
>    (simplify
> -   (minus (convert (plus:c @0 @1))
> +   (minus (convert (plus:c @@0 @1))
>      (convert (plus:c @0 @2)))
>     (if (INTEGRAL_TYPE_P (type)
>       && TYPE_OVERFLOW_UNDEFINED (type)
> -     && element_precision (type) <= element_precision (TREE_TYPE (@1)))
> +     && element_precision (type) <= element_precision (TREE_TYPE (@1))
> +     && element_precision (type) <= element_precision (TREE_TYPE (@2)))
>      (with { tree utype = unsigned_type_for (type); }
>       (convert (minus (convert:utype @1) (convert:utype @2))))
> -    (if (element_precision (type) <= element_precision (TREE_TYPE (@1))
> -      /* For integer types, if A has a smaller type
> -         than T the result depends on the possible
> -         overflow in P + A.
> -         E.g. T=size_t, A=(unsigned)429497295, P>0.
> -         However, if an overflow in P + A would cause
> -         undefined behavior, we can assume that there
> -         is no overflow.  */
> -      || (INTEGRAL_TYPE_P (TREE_TYPE (@0))
> -          && TYPE_OVERFLOW_UNDEFINED (TREE_TYPE (@0))))
> +    (if (((element_precision (type) <= element_precision (TREE_TYPE (@1)))
> +       == (element_precision (type) <= element_precision (TREE_TYPE (@1))))
> +      && (element_precision (type) <= element_precision (TREE_TYPE (@1))

Huh.  This looks like a copy&paste error (@1 vs. @2?).

> +          /* For integer types, if A has a smaller type
> +             than T the result depends on the possible
> +             overflow in P + A.
> +             E.g. T=size_t, A=(unsigned)429497295, P>0.
> +             However, if an overflow in P + A would cause
> +             undefined behavior, we can assume that there
> +             is no overflow.  */
> +          || (INTEGRAL_TYPE_P (TREE_TYPE (@1))
> +              && INTEGRAL_TYPE_P (TREE_TYPE (@2))
> +              && TYPE_OVERFLOW_UNDEFINED (TREE_TYPE (@1))
> +              && TYPE_OVERFLOW_UNDEFINED (TREE_TYPE (@2)))))
>       (minus (convert @1) (convert @2)))))
>    (simplify
>     (minus (convert (pointer_plus @@0 @1))
> --- gcc/testsuite/gcc.dg/pr81281-3.c.jj       2017-12-07 15:19:06.334840988 
> +0100
> +++ gcc/testsuite/gcc.dg/pr81281-3.c  2017-12-07 14:38:25.000000000 +0100
> @@ -0,0 +1,102 @@
> +/* PR sanitizer/81281 */
> +/* { dg-do compile } */
> +/* { dg-options "-O2 -fdump-tree-optimized" } */
> +/* { dg-final { scan-tree-dump-not "\[+=-] \?123\[ ;]" "optimized" } } */
> +
> +#ifdef __SIZEOF_INT128__
> +__int128
> +f1 (int a, long long b)
> +{
> +  __int128 f = 123 + a;
> +  __int128 g = 123 + b;
> +  return f - g;
> +}
> +#endif
> +
> +signed char
> +f2 (int a, long long b)
> +{
> +  signed char f = 123 + a;
> +  signed char g = 123 + b;
> +  return f - g;
> +}
> +
> +signed char
> +f3 (unsigned int a, unsigned long long b)
> +{
> +  signed char f = 123 + a;
> +  signed char g = 123 + b;
> +  return f - g;
> +}
> +
> +unsigned char
> +f4 (unsigned int a, unsigned long long b)
> +{
> +  unsigned char f = 123 + a;
> +  unsigned char g = 123 + b;
> +  return f - g;
> +}
> +
> +long long
> +f5 (int a)
> +{
> +  long long f = 123 + a;
> +  long long g = 123;
> +  return f - g;
> +}
> +
> +signed char
> +f6 (long long a)
> +{
> +  signed char f = 123 + a;
> +  signed char g = 123;
> +  return f - g;
> +}
> +
> +signed char
> +f7 (unsigned int a)
> +{
> +  signed char f = 123 + a;
> +  signed char g = 123;
> +  return f - g;
> +}
> +
> +unsigned char
> +f8 (unsigned long int a)
> +{
> +  unsigned char f = 123 + a;
> +  unsigned char g = 123;
> +  return f - g;
> +}
> +
> +long long
> +f9 (int a)
> +{
> +  long long f = 123;
> +  long long g = 123 + a;
> +  return f - g;
> +}
> +
> +signed char
> +f10 (long long a)
> +{
> +  signed char f = 123;
> +  signed char g = 123 + a;
> +  return f - g;
> +}
> +
> +signed char
> +f11 (unsigned int a)
> +{
> +  signed char f = 123;
> +  signed char g = 123 + a;
> +  return f - g;
> +}
> +
> +unsigned char
> +f12 (unsigned long int a)
> +{
> +  unsigned char f = 123;
> +  unsigned char g = 123 + a;
> +  return f - g;
> +}
> 
>       Jakub
> 
> 

-- 
Richard Biener <rguent...@suse.de>
SUSE LINUX GmbH, GF: Felix Imendoerffer, Jane Smithard, Graham Norton, HRB 
21284 (AG Nuernberg)

Reply via email to