Patchwork [wide-int] Simplify div_if_zero_remainder

login
register
mail settings
Submitter Richard Sandiford
Date Nov. 9, 2013, 10:55 a.m.
Message ID <87hablg7za.fsf@talisman.default>
Download mbox | patch
Permalink /patch/289967/
State New
Headers show

Comments

Richard Sandiford - Nov. 9, 2013, 10:55 a.m.
wide-int adds some code to div_if_zero_remainder to handle mismatched signs.
I think it's trying to make sure that we do the division to "infinite"
precision, extending each operand according to its own sign.  We can do
that more easily using wi::to_widest.  Using to::widest should also be
chaper.

Tested on powerpc64-linux-gnu and by rerunning the assembly comparison.
OK to install?

Thanks,
Richard
Kenneth Zadeck - Nov. 9, 2013, 3:11 p.m.
On 11/09/2013 05:55 AM, Richard Sandiford wrote:
> wide-int adds some code to div_if_zero_remainder to handle mismatched signs.
> I think it's trying to make sure that we do the division to "infinite"
> precision, extending each operand according to its own sign.  We can do
> that more easily using wi::to_widest.  Using to::widest should also be
> chaper.
>
> Tested on powerpc64-linux-gnu and by rerunning the assembly comparison.
> OK to install?
>
> Thanks,
> Richard
>
>
> Index: gcc/fold-const.c
> ===================================================================
> --- gcc/fold-const.c	2013-11-09 09:39:28.207810833 +0000
> +++ gcc/fold-const.c	2013-11-09 09:39:29.198817531 +0000
> @@ -170,31 +170,10 @@ protected_set_expr_location_unshare (tre
>   tree
>   div_if_zero_remainder (const_tree arg1, const_tree arg2)
>   {
> -  wide_int quo;
> -  wide_int warg1 = arg1;
> -  wide_int warg2 = arg2;
> -  signop sgn = TYPE_SIGN (TREE_TYPE (arg1));
> -  signop sgn2 = TYPE_SIGN (TREE_TYPE (arg2));
> +  widest_int quo;
>   
> -  if (sgn != sgn2)
> -    {
> -      /* When signedness mismatches, we promote the unsigned value to
> -	 a signed value.  We preserve the value by extending the
> -	 precision by 1 bit, iff the top bit is set.  */
> -      if (sgn == UNSIGNED)
> -	{
> -	  if (wi::neg_p (warg1))
> -	    warg1 = wide_int::from (warg1, warg1.get_precision () + 1, sgn);
> -	  sgn = SIGNED;
> -	}
> -      else
> -	{
> -	  if (wi::neg_p (warg2))
> -	    warg2 = wide_int::from (warg2, warg2.get_precision () + 1, sgn2);
> -	}
> -    }
> -
> -  if (wi::multiple_of_p (warg1, warg2, sgn, &quo))
> +  if (wi::multiple_of_p (wi::to_widest (arg1), wi::to_widest (arg2),
> +			 SIGNED, &quo))
>       return wide_int_to_tree (TREE_TYPE (arg1), quo);
>   
>     return NULL_TREE;
nice observation.

Patch

Index: gcc/fold-const.c
===================================================================
--- gcc/fold-const.c	2013-11-09 09:39:28.207810833 +0000
+++ gcc/fold-const.c	2013-11-09 09:39:29.198817531 +0000
@@ -170,31 +170,10 @@  protected_set_expr_location_unshare (tre
 tree
 div_if_zero_remainder (const_tree arg1, const_tree arg2)
 {
-  wide_int quo;
-  wide_int warg1 = arg1;
-  wide_int warg2 = arg2;
-  signop sgn = TYPE_SIGN (TREE_TYPE (arg1));
-  signop sgn2 = TYPE_SIGN (TREE_TYPE (arg2));
+  widest_int quo;
 
-  if (sgn != sgn2)
-    {
-      /* When signedness mismatches, we promote the unsigned value to
-	 a signed value.  We preserve the value by extending the
-	 precision by 1 bit, iff the top bit is set.  */
-      if (sgn == UNSIGNED)
-	{
-	  if (wi::neg_p (warg1))
-	    warg1 = wide_int::from (warg1, warg1.get_precision () + 1, sgn);
-	  sgn = SIGNED;
-	}
-      else
-	{
-	  if (wi::neg_p (warg2))
-	    warg2 = wide_int::from (warg2, warg2.get_precision () + 1, sgn2);
-	}
-    }
-
-  if (wi::multiple_of_p (warg1, warg2, sgn, &quo))
+  if (wi::multiple_of_p (wi::to_widest (arg1), wi::to_widest (arg2),
+			 SIGNED, &quo))
     return wide_int_to_tree (TREE_TYPE (arg1), quo);
 
   return NULL_TREE;