Adjust LSHIFT_EXPR handling of multiple_of_p

Message ID 20220124144729.EEF2813BA5@imap2.suse-dmz.suse.de
State New
Headers
Series Adjust LSHIFT_EXPR handling of multiple_of_p |

Commit Message

Richard Biener Jan. 24, 2022, 2:47 p.m. UTC
  This removes the odd check of size_type_node when handling left-shifts
as multiplications of 1 << N and instead uses the type as specified.
It also moves left-shift handling next to multiplications where it
semantically belongs.

Boostrap and regtest pending on x86_64-unknown-linux-gnu.

OK?  (I failed to short-cut the wide_int_to_tree for a
poly_int_cst_p bottom)

Thanks,
Richard.

2022-01-24  Richard Biener  <rguenther@suse.de>

	* fold-const.cc (multiple_of_p): Re-write and move LSHIFT_EXPR
	handling.
---
 gcc/fold-const.cc | 33 ++++++++++++++++-----------------
 1 file changed, 16 insertions(+), 17 deletions(-)
  

Comments

Richard Sandiford Feb. 4, 2022, 10:08 a.m. UTC | #1
Richard Biener <rguenther@suse.de> writes:
> This removes the odd check of size_type_node when handling left-shifts
> as multiplications of 1 << N and instead uses the type as specified.
> It also moves left-shift handling next to multiplications where it
> semantically belongs.
>
> Boostrap and regtest pending on x86_64-unknown-linux-gnu.
>
> OK?  (I failed to short-cut the wide_int_to_tree for a
> poly_int_cst_p bottom)
>
> Thanks,
> Richard.
>
> 2022-01-24  Richard Biener  <rguenther@suse.de>
>
> 	* fold-const.cc (multiple_of_p): Re-write and move LSHIFT_EXPR
> 	handling.
> ---
>  gcc/fold-const.cc | 33 ++++++++++++++++-----------------
>  1 file changed, 16 insertions(+), 17 deletions(-)
>
> diff --git a/gcc/fold-const.cc b/gcc/fold-const.cc
> index b155611578d..a0a4913c45e 100644
> --- a/gcc/fold-const.cc
> +++ b/gcc/fold-const.cc
> @@ -14068,7 +14068,7 @@ int
>  multiple_of_p (tree type, const_tree top, const_tree bottom)
>  {
>    gimple *stmt;
> -  tree t1, op1, op2;
> +  tree op1, op2;
>  
>    if (operand_equal_p (top, bottom, 0))
>      return 1;
> @@ -14114,6 +14114,21 @@ multiple_of_p (tree type, const_tree top, const_tree bottom)
>        return (multiple_of_p (type, TREE_OPERAND (top, 1), bottom)
>  	      || multiple_of_p (type, TREE_OPERAND (top, 0), bottom));
>  
> +    case LSHIFT_EXPR:
> +      /* Handle X << CST as X * (1 << CST) and only process the constant.  */
> +      if (TREE_CODE (TREE_OPERAND (top, 1)) == INTEGER_CST)
> +	{
> +	  op1 = TREE_OPERAND (top, 1);
> +	  if (wi::gtu_p (TYPE_PRECISION (type), wi::to_wide (op1)))
> +	    {
> +	      wide_int mul_op
> +		= wi::one (TYPE_PRECISION (type)) << wi::to_wide (op1);
> +	      return multiple_of_p (type,
> +				    wide_int_to_tree (type, mul_op), bottom);
> +	    }
> +	}
> +      return 0;
> +

LGTM.  Sorry for the slow response.

I guess the condition could be written:

    if (wi::to_widest (op1) < TYPE_PRECISION (type))

which might be more readable, and also avoids accidentally reinterpreting
a sign.

Thanks,
Richard

>      case MINUS_EXPR:
>        /* It is impossible to prove if op0 - op1 is multiple of bottom
>  	 precisely, so be conservative here checking if both op0 and op1
> @@ -14133,22 +14148,6 @@ multiple_of_p (tree type, const_tree top, const_tree bottom)
>        return (multiple_of_p (type, op1, bottom)
>  	      && multiple_of_p (type, TREE_OPERAND (top, 0), bottom));
>  
> -    case LSHIFT_EXPR:
> -      if (TREE_CODE (TREE_OPERAND (top, 1)) == INTEGER_CST)
> -	{
> -	  op1 = TREE_OPERAND (top, 1);
> -	  /* const_binop may not detect overflow correctly,
> -	     so check for it explicitly here.  */
> -	  if (wi::gtu_p (TYPE_PRECISION (TREE_TYPE (size_one_node)),
> -			 wi::to_wide (op1))
> -	      && (t1 = fold_convert (type,
> -				     const_binop (LSHIFT_EXPR, size_one_node,
> -						  op1))) != 0
> -	      && !TREE_OVERFLOW (t1))
> -	    return multiple_of_p (type, t1, bottom);
> -	}
> -      return 0;
> -
>      CASE_CONVERT:
>        /* Can't handle conversions from non-integral or wider integral type.  */
>        if ((TREE_CODE (TREE_TYPE (TREE_OPERAND (top, 0))) != INTEGER_TYPE)
  
Richard Biener Feb. 4, 2022, 10:20 a.m. UTC | #2
On Fri, 4 Feb 2022, Richard Sandiford wrote:

> Richard Biener <rguenther@suse.de> writes:
> > This removes the odd check of size_type_node when handling left-shifts
> > as multiplications of 1 << N and instead uses the type as specified.
> > It also moves left-shift handling next to multiplications where it
> > semantically belongs.
> >
> > Boostrap and regtest pending on x86_64-unknown-linux-gnu.
> >
> > OK?  (I failed to short-cut the wide_int_to_tree for a
> > poly_int_cst_p bottom)
> >
> > Thanks,
> > Richard.
> >
> > 2022-01-24  Richard Biener  <rguenther@suse.de>
> >
> > 	* fold-const.cc (multiple_of_p): Re-write and move LSHIFT_EXPR
> > 	handling.
> > ---
> >  gcc/fold-const.cc | 33 ++++++++++++++++-----------------
> >  1 file changed, 16 insertions(+), 17 deletions(-)
> >
> > diff --git a/gcc/fold-const.cc b/gcc/fold-const.cc
> > index b155611578d..a0a4913c45e 100644
> > --- a/gcc/fold-const.cc
> > +++ b/gcc/fold-const.cc
> > @@ -14068,7 +14068,7 @@ int
> >  multiple_of_p (tree type, const_tree top, const_tree bottom)
> >  {
> >    gimple *stmt;
> > -  tree t1, op1, op2;
> > +  tree op1, op2;
> >  
> >    if (operand_equal_p (top, bottom, 0))
> >      return 1;
> > @@ -14114,6 +14114,21 @@ multiple_of_p (tree type, const_tree top, const_tree bottom)
> >        return (multiple_of_p (type, TREE_OPERAND (top, 1), bottom)
> >  	      || multiple_of_p (type, TREE_OPERAND (top, 0), bottom));
> >  
> > +    case LSHIFT_EXPR:
> > +      /* Handle X << CST as X * (1 << CST) and only process the constant.  */
> > +      if (TREE_CODE (TREE_OPERAND (top, 1)) == INTEGER_CST)
> > +	{
> > +	  op1 = TREE_OPERAND (top, 1);
> > +	  if (wi::gtu_p (TYPE_PRECISION (type), wi::to_wide (op1)))
> > +	    {
> > +	      wide_int mul_op
> > +		= wi::one (TYPE_PRECISION (type)) << wi::to_wide (op1);
> > +	      return multiple_of_p (type,
> > +				    wide_int_to_tree (type, mul_op), bottom);
> > +	    }
> > +	}
> > +      return 0;
> > +
> 
> LGTM.  Sorry for the slow response.
> 
> I guess the condition could be written:
> 
>     if (wi::to_widest (op1) < TYPE_PRECISION (type))
> 
> which might be more readable, and also avoids accidentally reinterpreting
> a sign.

Good idea - I'll adjust, re-test and push.

Thanks,
Richard.
  

Patch

diff --git a/gcc/fold-const.cc b/gcc/fold-const.cc
index b155611578d..a0a4913c45e 100644
--- a/gcc/fold-const.cc
+++ b/gcc/fold-const.cc
@@ -14068,7 +14068,7 @@  int
 multiple_of_p (tree type, const_tree top, const_tree bottom)
 {
   gimple *stmt;
-  tree t1, op1, op2;
+  tree op1, op2;
 
   if (operand_equal_p (top, bottom, 0))
     return 1;
@@ -14114,6 +14114,21 @@  multiple_of_p (tree type, const_tree top, const_tree bottom)
       return (multiple_of_p (type, TREE_OPERAND (top, 1), bottom)
 	      || multiple_of_p (type, TREE_OPERAND (top, 0), bottom));
 
+    case LSHIFT_EXPR:
+      /* Handle X << CST as X * (1 << CST) and only process the constant.  */
+      if (TREE_CODE (TREE_OPERAND (top, 1)) == INTEGER_CST)
+	{
+	  op1 = TREE_OPERAND (top, 1);
+	  if (wi::gtu_p (TYPE_PRECISION (type), wi::to_wide (op1)))
+	    {
+	      wide_int mul_op
+		= wi::one (TYPE_PRECISION (type)) << wi::to_wide (op1);
+	      return multiple_of_p (type,
+				    wide_int_to_tree (type, mul_op), bottom);
+	    }
+	}
+      return 0;
+
     case MINUS_EXPR:
       /* It is impossible to prove if op0 - op1 is multiple of bottom
 	 precisely, so be conservative here checking if both op0 and op1
@@ -14133,22 +14148,6 @@  multiple_of_p (tree type, const_tree top, const_tree bottom)
       return (multiple_of_p (type, op1, bottom)
 	      && multiple_of_p (type, TREE_OPERAND (top, 0), bottom));
 
-    case LSHIFT_EXPR:
-      if (TREE_CODE (TREE_OPERAND (top, 1)) == INTEGER_CST)
-	{
-	  op1 = TREE_OPERAND (top, 1);
-	  /* const_binop may not detect overflow correctly,
-	     so check for it explicitly here.  */
-	  if (wi::gtu_p (TYPE_PRECISION (TREE_TYPE (size_one_node)),
-			 wi::to_wide (op1))
-	      && (t1 = fold_convert (type,
-				     const_binop (LSHIFT_EXPR, size_one_node,
-						  op1))) != 0
-	      && !TREE_OVERFLOW (t1))
-	    return multiple_of_p (type, t1, bottom);
-	}
-      return 0;
-
     CASE_CONVERT:
       /* Can't handle conversions from non-integral or wider integral type.  */
       if ((TREE_CODE (TREE_TYPE (TREE_OPERAND (top, 0))) != INTEGER_TYPE)