diff mbox

[wide-int] small cleanup in wide-int.*

Message ID 529E04A3.9060806@naturalbridge.com
State New
Headers show

Commit Message

Kenneth Zadeck Dec. 3, 2013, 4:19 p.m. UTC
On 11/29/2013 05:24 AM, Richard Biener wrote:
> On Thu, Nov 28, 2013 at 6:11 PM, Kenneth Zadeck
> <zadeck@naturalbridge.com> wrote:
>> This patch does three things in wide-int:
>>
>> 1) it cleans up some comments.
>> 2) removes a small amount of trash.
>> 3) it changes the max size of the wide int from being 4x of
>> MAX_BITSIZE_MODE_ANY_INT to 2x +1.   This should improve large muls and divs
>> as well as perhaps help with some cache behavior.
> @@ -235,8 +233,8 @@ along with GCC; see the file COPYING3.
>      range of a multiply.  This code needs 2n + 2 bits.  */
>
>   #define WIDE_INT_MAX_ELTS \
> -  ((4 * MAX_BITSIZE_MODE_ANY_INT + HOST_BITS_PER_WIDE_INT - 1) \
> -   / HOST_BITS_PER_WIDE_INT)
> +  (((2 * MAX_BITSIZE_MODE_ANY_INT + HOST_BITS_PER_WIDE_INT - 1) \
> +    / HOST_BITS_PER_WIDE_INT) + 1)
>
> I always wondered why VRP (if that is the only reason we do 2*n+1)
> cannot simply use FIXED_WIDE_INT(MAX_BITSIZE_MODE_ANY_INT*2 + 1)?
> Other widest_int users should not suffer IMHO.  widest_int should
> strictly cover all modes that the target can do any arithmetic on
> (thus not XImode or OImode on x86_64).
>
> Richard.
>
>> ok to commit
enclosed is the code to change the large multiplies in tree-vrp as well 
as sets the size of the WIDE_INT_MAX_ELTS as we have discussed.

Bootstrapped and tested on x86-64.

ok to commit?

kenny

Comments

Richard Sandiford Dec. 3, 2013, 4:52 p.m. UTC | #1
Kenneth Zadeck <zadeck@naturalbridge.com> writes:
> Index: tree-vrp.c
> ===================================================================
> --- tree-vrp.c	(revision 205597)
> +++ tree-vrp.c	(working copy)
> @@ -2611,22 +2611,28 @@ extract_range_from_binary_expr_1 (value_
>  
>        signop sign = TYPE_SIGN (expr_type);
>        unsigned int prec = TYPE_PRECISION (expr_type);
> -      unsigned int prec2 = (prec * 2) + (sign == UNSIGNED ? 2 : 0);
>  
>        if (range_int_cst_p (&vr0)
>  	  && range_int_cst_p (&vr1)
>  	  && TYPE_OVERFLOW_WRAPS (expr_type))
>  	{
> -	  wide_int sizem1 = wi::mask (prec, false, prec2);
> -	  wide_int size = sizem1 + 1;
> +	  /* vrp_int is twice as wide as anything that the target
> +	     supports so it can support a full width multiply.  No
> +	     need to add any more padding for an extra sign bit
> +	     because that comes with the way that WIDE_INT_MAX_ELTS is
> +	     defined.  */ 
> +	  typedef FIXED_WIDE_INT (WIDE_INT_MAX_PRECISION * 2) 
> +	    vrp_int;
> +	  vrp_int sizem1 = wi::mask <vrp_int> (prec, false);
> +	  vrp_int size = sizem1 + 1;
>  
>  	  /* Extend the values using the sign of the result to PREC2.
>  	     From here on out, everthing is just signed math no matter
>  	     what the input types were.  */
> -	  wide_int min0 = wide_int::from (vr0.min, prec2, sign);
> -	  wide_int max0 = wide_int::from (vr0.max, prec2, sign);
> -	  wide_int min1 = wide_int::from (vr1.min, prec2, sign);
> -	  wide_int max1 = wide_int::from (vr1.max, prec2, sign);
> +	  vrp_int min0 = wi::to_vrp (vr0.min);
> +	  vrp_int max0 = wi::to_vrp (vr0.max);
> +	  vrp_int min1 = wi::to_vrp (vr1.min);
> +	  vrp_int max1 = wi::to_vrp (vr1.max);

I think we should avoid putting to_vrp in tree.h if vrp_int is only
local to this block.  Instead you could have:

	  typedef generic_wide_int
             <wi::extended_tree <WIDE_INT_MAX_PRECISION * 2> > vrp_int_cst;
          ...
          vrp_int_cst min0 = vr0.min;
          vrp_int_cst max0 = vr0.max;
          vrp_int_cst min1 = vr1.min;
          vrp_int_cst max1 = vr1.max;

> @@ -228,15 +228,16 @@ along with GCC; see the file COPYING3.
>  #endif
>  
>  /* The MAX_BITSIZE_MODE_ANY_INT is automatically generated by a very
> -   early examination of the target's mode file.  Thus it is safe that
> -   some small multiple of this number is easily larger than any number
> -   that that target could compute.  The place in the compiler that
> -   currently needs the widest ints is the code that determines the
> -   range of a multiply.  This code needs 2n + 2 bits.  */
> -
> +   early examination of the target's mode file.  The WIDE_INT_MAX_ELTS
> +   can accomodate at least 1 more bit so that unsigned numbers of that
> +   mode can be represented.  This will accomodate every place in the
> +   compiler except for a multiply routine in tree-vrp.  That function
> +   makes its own arrangements for larger wide-ints.  */

I think we should drop the "This will accomodate..." bit, since it'll soon
get out of date.  Maybe something like:

    Note that it is still possible to create fixed_wide_ints that have
    precisions greater than MAX_BITSIZE_MODE_ANY_INT.  This can be useful
    when representing a double-width multiplication result, for example.  */

>  #define WIDE_INT_MAX_ELTS \
> -  ((4 * MAX_BITSIZE_MODE_ANY_INT + HOST_BITS_PER_WIDE_INT - 1) \
> -   / HOST_BITS_PER_WIDE_INT)
> +  (((MAX_BITSIZE_MODE_ANY_INT + HOST_BITS_PER_WIDE_INT - 1)	\
> +    / HOST_BITS_PER_WIDE_INT) + 1)

I think this should be:

  (MAX_BITSIZE_MODE_ANY_INT / HOST_BITS_PER_WIDE_INT + 1)

We only need an extra HWI if MAX_BITSIZE_MODE_ANY_INT is an exact multiple
of HOST_BITS_PER_WIDE_INT.

Looks good to me otherwise FWIW.

You probably already realise this, but for avoidance of doubt, Richard
was also asking that we reduce MAX_BITSIZE_MODE_ANY_INT to 128 on x86_64,
since that's the largest scalar_mode_supported_p mode.

Thanks,
Richard
Mike Stump Dec. 3, 2013, 6:32 p.m. UTC | #2
On Dec 3, 2013, at 8:52 AM, Richard Sandiford <rsandifo@linux.vnet.ibm.com> wrote:
> You probably already realise this, but for avoidance of doubt, Richard
> was also asking that we reduce MAX_BITSIZE_MODE_ANY_INT to 128 on x86_64,
> since that's the largest scalar_mode_supported_p mode.

Personally, I'd love to see scalar_mode_supported_p be auto-generated from the gen*.c programs; then, we could just add a line to that program to synthesize this value.  Absent that, which I think is a nice long term direction to shoot for, we'd need yet another #define for the target to explain the largest supported size.
diff mbox

Patch

Index: tree-vrp.c
===================================================================
--- tree-vrp.c	(revision 205597)
+++ tree-vrp.c	(working copy)
@@ -2611,22 +2611,28 @@  extract_range_from_binary_expr_1 (value_
 
       signop sign = TYPE_SIGN (expr_type);
       unsigned int prec = TYPE_PRECISION (expr_type);
-      unsigned int prec2 = (prec * 2) + (sign == UNSIGNED ? 2 : 0);
 
       if (range_int_cst_p (&vr0)
 	  && range_int_cst_p (&vr1)
 	  && TYPE_OVERFLOW_WRAPS (expr_type))
 	{
-	  wide_int sizem1 = wi::mask (prec, false, prec2);
-	  wide_int size = sizem1 + 1;
+	  /* vrp_int is twice as wide as anything that the target
+	     supports so it can support a full width multiply.  No
+	     need to add any more padding for an extra sign bit
+	     because that comes with the way that WIDE_INT_MAX_ELTS is
+	     defined.  */ 
+	  typedef FIXED_WIDE_INT (WIDE_INT_MAX_PRECISION * 2) 
+	    vrp_int;
+	  vrp_int sizem1 = wi::mask <vrp_int> (prec, false);
+	  vrp_int size = sizem1 + 1;
 
 	  /* Extend the values using the sign of the result to PREC2.
 	     From here on out, everthing is just signed math no matter
 	     what the input types were.  */
-	  wide_int min0 = wide_int::from (vr0.min, prec2, sign);
-	  wide_int max0 = wide_int::from (vr0.max, prec2, sign);
-	  wide_int min1 = wide_int::from (vr1.min, prec2, sign);
-	  wide_int max1 = wide_int::from (vr1.max, prec2, sign);
+	  vrp_int min0 = wi::to_vrp (vr0.min);
+	  vrp_int max0 = wi::to_vrp (vr0.max);
+	  vrp_int min1 = wi::to_vrp (vr1.min);
+	  vrp_int max1 = wi::to_vrp (vr1.max);
 
 	  /* Canonicalize the intervals.  */
 	  if (sign == UNSIGNED)
@@ -2644,17 +2650,17 @@  extract_range_from_binary_expr_1 (value_
 		}
 	    }
 
-	  wide_int prod0 = min0 * min1;
-	  wide_int prod1 = min0 * max1;
-	  wide_int prod2 = max0 * min1;
-	  wide_int prod3 = max0 * max1;
+	  vrp_int prod0 = min0 * min1;
+	  vrp_int prod1 = min0 * max1;
+	  vrp_int prod2 = max0 * min1;
+	  vrp_int prod3 = max0 * max1;
 
 	  /* Sort the 4 products so that min is in prod0 and max is in
 	     prod3.  */
 	  /* min0min1 > max0max1 */
 	  if (wi::gts_p (prod0, prod3))
 	    {
-	      wide_int tmp = prod3;
+	      vrp_int tmp = prod3;
 	      prod3 = prod0;
 	      prod0 = tmp;
 	    }
@@ -2662,21 +2668,21 @@  extract_range_from_binary_expr_1 (value_
 	  /* min0max1 > max0min1 */
 	  if (wi::gts_p (prod1, prod2))
 	    {
-	      wide_int tmp = prod2;
+	      vrp_int tmp = prod2;
 	      prod2 = prod1;
 	      prod1 = tmp;
 	    }
 
 	  if (wi::gts_p (prod0, prod1))
 	    {
-	      wide_int tmp = prod1;
+	      vrp_int tmp = prod1;
 	      prod1 = prod0;
 	      prod0 = tmp;
 	    }
 
 	  if (wi::gts_p (prod2, prod3))
 	    {
-	      wide_int tmp = prod3;
+	      vrp_int tmp = prod3;
 	      prod3 = prod2;
 	      prod2 = tmp;
 	    }
Index: tree.h
===================================================================
--- tree.h	(revision 205597)
+++ tree.h	(working copy)
@@ -4565,10 +4565,12 @@  namespace wi
     static const unsigned int precision = N;
   };
 
-  generic_wide_int <extended_tree <MAX_BITSIZE_MODE_ANY_INT> >
+  generic_wide_int <extended_tree <WIDE_INT_MAX_PRECISION> >
   to_widest (const_tree);
 
   generic_wide_int <extended_tree <ADDR_MAX_PRECISION> > to_offset (const_tree);
+
+  generic_wide_int <extended_tree <WIDE_INT_MAX_PRECISION * 2> > to_vrp (const_tree);
 }
 
 inline unsigned int
@@ -4586,7 +4588,7 @@  wi::int_traits <const_tree>::decompose (
 			  precision);
 }
 
-inline generic_wide_int <wi::extended_tree <MAX_BITSIZE_MODE_ANY_INT> >
+inline generic_wide_int <wi::extended_tree <WIDE_INT_MAX_PRECISION> >
 wi::to_widest (const_tree t)
 {
   return t;
@@ -4597,6 +4599,12 @@  wi::to_offset (const_tree t)
 {
   return t;
 }
+
+inline generic_wide_int <wi::extended_tree <WIDE_INT_MAX_PRECISION * 2> >
+wi::to_vrp (const_tree t)
+{
+  return t;
+}
 
 template <int N>
 inline wi::extended_tree <N>::extended_tree (const_tree t)
Index: wide-int.h
===================================================================
--- wide-int.h	(revision 205599)
+++ wide-int.h	(working copy)
@@ -228,15 +228,16 @@  along with GCC; see the file COPYING3.
 #endif
 
 /* The MAX_BITSIZE_MODE_ANY_INT is automatically generated by a very
-   early examination of the target's mode file.  Thus it is safe that
-   some small multiple of this number is easily larger than any number
-   that that target could compute.  The place in the compiler that
-   currently needs the widest ints is the code that determines the
-   range of a multiply.  This code needs 2n + 2 bits.  */
-
+   early examination of the target's mode file.  The WIDE_INT_MAX_ELTS
+   can accomodate at least 1 more bit so that unsigned numbers of that
+   mode can be represented.  This will accomodate every place in the
+   compiler except for a multiply routine in tree-vrp.  That function
+   makes its own arrangements for larger wide-ints.  */
 #define WIDE_INT_MAX_ELTS \
-  ((4 * MAX_BITSIZE_MODE_ANY_INT + HOST_BITS_PER_WIDE_INT - 1) \
-   / HOST_BITS_PER_WIDE_INT)
+  (((MAX_BITSIZE_MODE_ANY_INT + HOST_BITS_PER_WIDE_INT - 1)	\
+    / HOST_BITS_PER_WIDE_INT) + 1)
+
+#define WIDE_INT_MAX_PRECISION (WIDE_INT_MAX_ELTS * HOST_BITS_PER_WIDE_INT)
 
 /* This is the max size of any pointer on any machine.  It does not
    seem to be as easy to sniff this out of the machine description as
@@ -291,7 +292,7 @@  struct wide_int_storage;
 
 typedef generic_wide_int <wide_int_storage> wide_int;
 typedef FIXED_WIDE_INT (ADDR_MAX_PRECISION) offset_int;
-typedef FIXED_WIDE_INT (MAX_BITSIZE_MODE_ANY_INT) widest_int;
+typedef FIXED_WIDE_INT (WIDE_INT_MAX_PRECISION) widest_int;
 
 template <bool SE>
 struct wide_int_ref_storage;