On Thu, 7 May 2020, Jakub Jelinek wrote:

> Hi!
> 
> The following patch canonicalizes M = X >> (prec - 1); (X + M) ^ M
> for signed integral types into ABS_EXPR (X).  For X == min it is already
> UB because M is -1 and min + -1 is UB, so we can use ABS_EXPR rather than
> say ABSU_EXPR + cast.
> 
> The backend might then emit the abs code back using the shift and addition
> and xor if it is the best sequence for the target, but could do something
> different that is better.
> 
> Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk?
> 
> 2020-05-06  Jakub Jelinek  <ja...@redhat.com>
> 
>       PR tree-optimization/94783
>       * match.pd ((X + (X >> (prec - 1))) ^ (X >> (prec - 1)) to abs (X)):
>       New simplification.
> 
>       * gcc.dg/tree-ssa/pr94783.c: New test.
> 
> --- gcc/match.pd.jj   2020-05-06 15:48:23.658858289 +0200
> +++ gcc/match.pd      2020-05-06 17:47:02.035347946 +0200
> @@ -120,6 +120,18 @@ (define_operator_list COND_TERNARY
>    (with { tree utype = unsigned_type_for (TREE_TYPE (@0)); }
>     (convert (absu:utype @0)))))
>  
> +#if GIMPLE
> +/* Optimize (X + (X >> (prec - 1))) ^ (X >> (prec - 1)) into abs (X).  */
> +(simplify
> + (bit_xor:c (plus:cs @0 (rshift@2 @0 INTEGER_CST@1)) @2)
> + (if (ANY_INTEGRAL_TYPE_P (TREE_TYPE (@0))
> +      && !TYPE_UNSIGNED (TREE_TYPE (@0))
> +      && TYPE_OVERFLOW_UNDEFINED (TREE_TYPE (@0))
> +      && wi::to_widest (@1) == element_precision (TREE_TYPE (@0)) - 1
> +      && TREE_CODE (@2) == SSA_NAME
> +      && num_imm_uses (@2) == 2)

I fear this num_imm_uses test is quite fragile since match.pd patterns
are invoked on transient sequences (w/o SSA operands) as well
(that of course holds for all single_use () tests as well but that
at least allows zero uses for this very reason - still fragile since
the single use might be _in_ the IL and thus a second).

I think unconditionally using (abs @0) is simplifying things enough
(getting rid of one xor and one plus) to not worry about keeping
the (x >> (prec - 1))?

Do you really need the TYPE_OVERFLOW_UNDEFINED check?

> +  (abs @0)))
> +#endif
>  
>  /* Simplifications of operations with one constant operand and
>     simplifications to constants or single values.  */
> --- gcc/testsuite/gcc.dg/tree-ssa/pr94783.c.jj        2020-05-06 
> 17:52:35.515323297 +0200
> +++ gcc/testsuite/gcc.dg/tree-ssa/pr94783.c   2020-05-06 17:52:10.915693948 
> +0200
> @@ -0,0 +1,12 @@
> +/* PR tree-optimization/94783 */
> +/* { dg-do compile } */
> +/* { dg-options "-O2 -fdump-tree-optimized" } */
> +/* { dg-final { scan-tree-dump "ABS_EXPR" "optimized" } } */
> +/* { dg-final { scan-tree-dump-not " >> 31" "optimized" } } */
> +
> +int
> +foo (int v)
> +{
> +  int mask = v >> (__SIZEOF_INT__ * __CHAR_BIT__ - 1);
> +  return (v + mask) ^ mask;
> +}
> 
>       Jakub
> 
> 

-- 
Richard Biener <rguent...@suse.de>
SUSE Software Solutions Germany GmbH, Maxfeldstrasse 5, 90409 Nuernberg,
Germany; GF: Felix Imendörffer; HRB 36809 (AG Nuernberg)

Reply via email to