On Thu, 7 May 2020, Jakub Jelinek wrote:
> Hi!
>
> Implemented thusly. The TYPE_OVERFLOW_WRAPS is there just because the
> pattern above it has it too, if you want, I can throw it away from both.
>
> Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk?
>
> 2020-05-06 Jakub Jelinek <[email protected]>
>
> PR tree-optimization/94913
> * match.pd (A - B - 1 >= A to B >= A): New simplification.
>
> * gcc.dg/tree-ssa/pr94913.c: New test.
>
> --- gcc/match.pd.jj 2020-05-06 11:18:35.000000000 +0200
> +++ gcc/match.pd 2020-05-06 15:03:51.618058839 +0200
> @@ -4791,6 +4791,15 @@ (define_operator_list COND_TERNARY
> && TYPE_OVERFLOW_WRAPS (TREE_TYPE (@0)))
> (cmp @1 @0))))
>
> +/* Optimize A - B - 1 >= A into B >= A for unsigned comparisons. */
Maybe write A - B + -1 >= A to actually match what you match below
> +(for cmp (ge lt)
> + (simplify
> + (cmp:c (plus:cs (minus:s @0 @1) integer_minus_onep) @0)
on the plus :c is not needed, canonicalization will put the constant
literal second
The previous pattern has a single_use check on the minus, since
the result is always "simple" (a single stmt) the :s have no
effect (hmm, I guess a genmatch warning for this case might be nice).
And yes, if the TYPE_OVERFLOW_WRAPS checks are unnecessary remove
them please, we'll hopefully resist all attempts to ubsan
unsigned overflow ...
> + (if (ANY_INTEGRAL_TYPE_P (TREE_TYPE (@0))
> + && TYPE_UNSIGNED (TREE_TYPE (@0))
> + && TYPE_OVERFLOW_WRAPS (TREE_TYPE (@0)))
> + (cmp @1 @0))))
> +
> /* Testing for overflow is unnecessary if we already know the result. */
> /* A - B > A */
> (for cmp (gt le)
> --- gcc/testsuite/gcc.dg/tree-ssa/pr94913.c.jj 2020-05-06
> 15:20:08.306376994 +0200
> +++ gcc/testsuite/gcc.dg/tree-ssa/pr94913.c 2020-05-06 15:19:45.120725533
> +0200
> @@ -0,0 +1,33 @@
> +/* PR tree-optimization/94913 */
> +/* { dg-do compile } */
> +/* { dg-options "-O2 -fdump-tree-optimized" } */
> +/* { dg-final { scan-tree-dump " (?:b_\[0-9]+\\\(D\\\) >=
> a|a_\[0-9]+\\\(D\\\) <= b)_\[0-9]+\\\(D\\\);" "optimized" } } */
> +/* { dg-final { scan-tree-dump " (?:c_\[0-9]+\\\(D\\\) >
> d|d_\[0-9]+\\\(D\\\) < c)_\[0-9]+\\\(D\\\);" "optimized" } } */
> +/* { dg-final { scan-tree-dump " (?:f_\[0-9]+\\\(D\\\) >=
> e|e_\[0-9]+\\\(D\\\) <= f)_\[0-9]+\\\(D\\\);" "optimized" } } */
> +/* { dg-final { scan-tree-dump " (?:g_\[0-9]+\\\(D\\\) >
> h|h_\[0-9]+\\\(D\\\) < g)_\[0-9]+\\\(D\\\);" "optimized" } } */
> +
> +int
> +foo (unsigned a, unsigned b)
> +{
> + return (a - b - 1) >= a;
> +}
> +
> +int
> +bar (unsigned c, unsigned d)
> +{
> + return (c - d - 1) < c;
> +}
> +
> +int
> +baz (unsigned e, unsigned f)
> +{
> + unsigned t = e - f;
> + return (t - 1) >= e;
> +}
> +
> +int
> +qux (unsigned g, unsigned h)
> +{
> + unsigned t = g - h;
> + return (t - 1) < g;
> +}
>
> Jakub
>
>
--
Richard Biener <[email protected]>
SUSE Software Solutions Germany GmbH, Maxfeldstrasse 5, 90409 Nuernberg,
Germany; GF: Felix Imendörffer; HRB 36809 (AG Nuernberg)