[PATCH] forwprop: Pattern recognize more rotates [PR94344]

Richard Biener rguenther@suse.de
Tue Mar 31 08:51:56 GMT 2020


On Tue, 31 Mar 2020, Jakub Jelinek wrote:

> Hi!
> 
> The following patch adjusts simplify_rotate to recognize more rotates,
> basically we allow even some same precision integral -> integral
> conversions, with the requirement that the RSHIFT_EXPR operand has to be
> done in unsigned type (i.e. logical right shift), so that we compensate for
> the combiner no longer being able to simplify those into rotates on some
> targets.
> 
> Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk?

OK.

Thanks,
Richard.

> 2020-03-31  Jakub Jelinek  <jakub@redhat.com>
> 
> 	PR rtl-optimization/94344
> 	* tree-ssa-forwprop.c (simplify_rotate): Handle also same precision
> 	conversions, either on both operands of |^+ or just one.  Handle
> 	also extra same precision conversion on RSHIFT_EXPR first operand
> 	provided RSHIFT_EXPR is performed in unsigned type.
> 
> 	* gcc.dg/pr94344.c: New test.
> 
> --- gcc/tree-ssa-forwprop.c.jj	2020-03-23 19:43:00.309774530 +0100
> +++ gcc/tree-ssa-forwprop.c	2020-03-30 14:50:16.303668479 +0200
> @@ -1562,14 +1562,14 @@ simplify_rotate (gimple_stmt_iterator *g
>    for (i = 0; i < 2; i++)
>      defcodefor_name (arg[i], &def_code[i], &def_arg1[i], &def_arg2[i]);
>  
> -  /* Look through narrowing conversions.  */
> +  /* Look through narrowing (or same precision) conversions.  */
>    if (CONVERT_EXPR_CODE_P (def_code[0])
>        && CONVERT_EXPR_CODE_P (def_code[1])
>        && INTEGRAL_TYPE_P (TREE_TYPE (def_arg1[0]))
>        && INTEGRAL_TYPE_P (TREE_TYPE (def_arg1[1]))
>        && TYPE_PRECISION (TREE_TYPE (def_arg1[0]))
>  	 == TYPE_PRECISION (TREE_TYPE (def_arg1[1]))
> -      && TYPE_PRECISION (TREE_TYPE (def_arg1[0])) > TYPE_PRECISION (rtype)
> +      && TYPE_PRECISION (TREE_TYPE (def_arg1[0])) >= TYPE_PRECISION (rtype)
>        && has_single_use (arg[0])
>        && has_single_use (arg[1]))
>      {
> @@ -1579,6 +1579,21 @@ simplify_rotate (gimple_stmt_iterator *g
>  	  defcodefor_name (arg[i], &def_code[i], &def_arg1[i], &def_arg2[i]);
>  	}
>      }
> +  else
> +    {
> +      /* Handle signed rotate; the RSHIFT_EXPR has to be done
> +	 in unsigned type but LSHIFT_EXPR could be signed.  */
> +      i = (def_code[0] == LSHIFT_EXPR || def_code[0] == RSHIFT_EXPR);
> +      if (CONVERT_EXPR_CODE_P (def_code[i])
> +	  && (def_code[1 - i] == LSHIFT_EXPR || def_code[1 - i] == RSHIFT_EXPR)
> +	  && INTEGRAL_TYPE_P (TREE_TYPE (def_arg1[i]))
> +	  && TYPE_PRECISION (rtype) == TYPE_PRECISION (TREE_TYPE (def_arg1[i]))
> +	  && has_single_use (arg[i]))
> +	{
> +	  arg[i] = def_arg1[i];
> +	  defcodefor_name (arg[i], &def_code[i], &def_arg1[i], &def_arg2[i]);
> +	}
> +    }
>  
>    /* One operand has to be LSHIFT_EXPR and one RSHIFT_EXPR.  */
>    for (i = 0; i < 2; i++)
> @@ -1608,8 +1623,33 @@ simplify_rotate (gimple_stmt_iterator *g
>    if (!operand_equal_for_phi_arg_p (def_arg1[0], def_arg1[1])
>        || !types_compatible_p (TREE_TYPE (def_arg1[0]),
>  			      TREE_TYPE (def_arg1[1])))
> -    return false;
> -  if (!TYPE_UNSIGNED (TREE_TYPE (def_arg1[0])))
> +    {
> +      if ((TYPE_PRECISION (TREE_TYPE (def_arg1[0]))
> +	   != TYPE_PRECISION (TREE_TYPE (def_arg1[1])))
> +	  || (TYPE_UNSIGNED (TREE_TYPE (def_arg1[0]))
> +	      == TYPE_UNSIGNED (TREE_TYPE (def_arg1[1]))))
> +	return false;
> +
> +      /* Handle signed rotate; the RSHIFT_EXPR has to be done
> +	 in unsigned type but LSHIFT_EXPR could be signed.  */
> +      i = def_code[0] != RSHIFT_EXPR;
> +      if (!TYPE_UNSIGNED (TREE_TYPE (def_arg1[i])))
> +	return false;
> +
> +      tree tem;
> +      enum tree_code code;
> +      defcodefor_name (def_arg1[i], &code, &tem, NULL);
> +      if (!CONVERT_EXPR_CODE_P (code)
> +	  || !INTEGRAL_TYPE_P (TREE_TYPE (tem))
> +	  || TYPE_PRECISION (TREE_TYPE (tem)) != TYPE_PRECISION (rtype))
> +	return false;
> +      def_arg1[i] = tem;
> +      if (!operand_equal_for_phi_arg_p (def_arg1[0], def_arg1[1])
> +	  || !types_compatible_p (TREE_TYPE (def_arg1[0]),
> +				  TREE_TYPE (def_arg1[1])))
> +	return false;
> +    }
> +  else if (!TYPE_UNSIGNED (TREE_TYPE (def_arg1[0])))
>      return false;
>  
>    /* CNT1 + CNT2 == B case above.  */
> --- gcc/testsuite/gcc.dg/pr94344.c.jj	2020-03-30 14:49:53.005016600 +0200
> +++ gcc/testsuite/gcc.dg/pr94344.c	2020-03-30 14:47:41.495981569 +0200
> @@ -0,0 +1,53 @@
> +/* PR rtl-optimization/94344 */
> +/* { dg-do compile { target { ilp32 || lp64 } } } */
> +/* { dg-options "-O2 -fdump-tree-forwprop1" } */
> +/* { dg-final { scan-tree-dump-times " r>> 27;" 4 "forwprop1" } } */
> +/* { dg-final { scan-tree-dump-times " r>> 59;" 4 "forwprop1" } } */
> +
> +int
> +f1 (int x)
> +{
> +  return (x << 5) | (int)((unsigned int)x >> 27);
> +}
> +
> +unsigned int
> +f2 (int x)
> +{
> +  return (x << 5) | ((unsigned int)x >> 27);
> +}
> +
> +long long int
> +f3 (long long int x)
> +{
> +  return (x << 5) | (long long int)((unsigned long long int)x >> 59);
> +}
> +
> +unsigned long long int
> +f4 (long long int x)
> +{
> +  return (x << 5) | ((unsigned long long int)x >> 59);
> +}
> +
> +int
> +f5 (int x)
> +{
> +  return (int)((unsigned int)x >> 27) | (x << 5);
> +}
> +
> +unsigned int
> +f6 (int x)
> +{
> +  return ((unsigned int)x >> 27) | (x << 5);
> +}
> +
> +long long int
> +f7 (long long int x)
> +{
> +  return (long long int)((unsigned long long int)x >> 59) | (x << 5);
> +}
> +
> +unsigned long long int
> +f8 (long long int x)
> +{
> +  return ((unsigned long long int)x >> 59) | (x << 5);
> +}
> 
> 	Jakub
> 
> 

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


More information about the Gcc-patches mailing list