committed as revision 205599 to wide-int branch.
kenny
On 12/02/2013 05:50 AM, Richard Biener wrote:
On Sat, Nov 30, 2013 at 1:55 AM, Kenneth Zadeck
<zad...@naturalbridge.com> wrote:
Richi,
this is the first of either 2 or 3 patches to fix this. There are two
places that need be fixed for us to do 1X + 1 and this patch fixes the first
one. There was an unnecessary call to mul_full and this was the only call
to mul_full. So this patch removes the call and also the function itself.
The other place is the tree-vpn that is discussed here and will be dealt
with in the other patches.
tested on x86-64.
Ok to commit?
Ok.
Thanks,
Richard.
Kenny
On 11/29/2013 05:24 AM, Richard Biener wrote:
On Thu, Nov 28, 2013 at 6:11 PM, Kenneth Zadeck
<zad...@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
Index: gcc/wide-int.cc
===================================================================
--- gcc/wide-int.cc (revision 205597)
+++ gcc/wide-int.cc (working copy)
@@ -1247,22 +1247,18 @@ wi_pack (unsigned HOST_WIDE_INT *result,
}
/* Multiply Op1 by Op2. If HIGH is set, only the upper half of the
- result is returned. If FULL is set, the entire result is returned
- in a mode that is twice the width of the inputs. However, that
- mode needs to exist if the value is to be usable. Clients that use
- FULL need to check for this.
-
- If HIGH or FULL are not set, throw away the upper half after the
- check is made to see if it overflows. Unfortunately there is no
- better way to check for overflow than to do this. If OVERFLOW is
- nonnull, record in *OVERFLOW whether the result overflowed. SGN
- controls the signedness and is used to check overflow or if HIGH or
- FULL is set. */
+ result is returned.
+
+ If HIGH is not set, throw away the upper half after the check is
+ made to see if it overflows. Unfortunately there is no better way
+ to check for overflow than to do this. If OVERFLOW is nonnull,
+ record in *OVERFLOW whether the result overflowed. SGN controls
+ the signedness and is used to check overflow or if HIGH is set. */
unsigned int
wi::mul_internal (HOST_WIDE_INT *val, const HOST_WIDE_INT *op1,
unsigned int op1len, const HOST_WIDE_INT *op2,
unsigned int op2len, unsigned int prec, signop sgn,
- bool *overflow, bool high, bool full)
+ bool *overflow, bool high)
{
unsigned HOST_WIDE_INT o0, o1, k, t;
unsigned int i;
@@ -1313,7 +1309,7 @@ wi::mul_internal (HOST_WIDE_INT *val, co
/* If we need to check for overflow, we can only do half wide
multiplies quickly because we need to look at the top bits to
check for the overflow. */
- if ((high || full || needs_overflow)
+ if ((high || needs_overflow)
&& (prec <= HOST_BITS_PER_HALF_WIDE_INT))
{
unsigned HOST_WIDE_INT r;
@@ -1372,7 +1368,7 @@ wi::mul_internal (HOST_WIDE_INT *val, co
/* We did unsigned math above. For signed we must adjust the
product (assuming we need to see that). */
- if (sgn == SIGNED && (full || high || needs_overflow))
+ if (sgn == SIGNED && (high || needs_overflow))
{
unsigned HOST_WIDE_INT b;
if (op1[op1len-1] < 0)
@@ -1420,13 +1416,7 @@ wi::mul_internal (HOST_WIDE_INT *val, co
*overflow = true;
}
- if (full)
- {
- /* compute [2prec] <- [prec] * [prec] */
- wi_pack ((unsigned HOST_WIDE_INT *) val, r, 2 * half_blocks_needed);
- return canonize (val, blocks_needed * 2, prec * 2);
- }
- else if (high)
+ if (high)
{
/* compute [prec] <- ([prec] * [prec]) >> [prec] */
wi_pack ((unsigned HOST_WIDE_INT *) val,
Index: gcc/fold-const.c
===================================================================
--- gcc/fold-const.c (revision 205597)
+++ gcc/fold-const.c (working copy)
@@ -5962,11 +5962,12 @@ extract_muldiv_1 (tree t, tree c, enum t
assuming no overflow. */
if (tcode == code)
{
- bool overflow_p;
+ bool overflow_p = false;
+ bool overflow_mul_p;
signop sign = TYPE_SIGN (ctype);
- wide_int mul = wi::mul_full (op1, c, sign);
+ wide_int mul = wi::mul (op1, c, sign, &overflow_mul_p);
overflow_p = TREE_OVERFLOW (c) | TREE_OVERFLOW (op1);
- if (!wi::fits_to_tree_p (mul, ctype)
+ if (overflow_mul_p
&& ((sign == UNSIGNED && tcode != MULT_EXPR) || sign == SIGNED))
overflow_p = true;
if (!overflow_p)
Index: gcc/wide-int.h
===================================================================
--- gcc/wide-int.h (revision 205597)
+++ gcc/wide-int.h (working copy)
@@ -1575,7 +1575,7 @@ namespace wi
unsigned int mul_internal (HOST_WIDE_INT *, const HOST_WIDE_INT *,
unsigned int, const HOST_WIDE_INT *,
unsigned int, unsigned int, signop, bool *,
- bool, bool);
+ bool);
unsigned int divmod_internal (HOST_WIDE_INT *, unsigned int *,
HOST_WIDE_INT *, const HOST_WIDE_INT *,
unsigned int, unsigned int,
@@ -2394,7 +2394,7 @@ wi::mul (const T1 &x, const T2 &y)
}
else
result.set_len (mul_internal (val, xi.val, xi.len, yi.val, yi.len,
- precision, UNSIGNED, 0, false, false));
+ precision, UNSIGNED, 0, false));
return result;
}
@@ -2410,7 +2410,7 @@ wi::mul (const T1 &x, const T2 &y, signo
WIDE_INT_REF_FOR (T2) yi (y, precision);
result.set_len (mul_internal (val, xi.val, xi.len,
yi.val, yi.len, precision,
- sgn, overflow, false, false));
+ sgn, overflow, false));
return result;
}
@@ -2444,7 +2444,7 @@ wi::mul_high (const T1 &x, const T2 &y,
WIDE_INT_REF_FOR (T2) yi (y, precision);
result.set_len (mul_internal (val, xi.val, xi.len,
yi.val, yi.len, precision,
- sgn, 0, true, false));
+ sgn, 0, true));
return result;
}
@@ -3033,8 +3033,6 @@ namespace wi
wide_int max_value (never_used1 *);
wide_int max_value (never_used2 *);
- wide_int mul_full (const wide_int_ref &, const wide_int_ref &, signop);
-
/* FIXME: this is target dependent, so should be elsewhere.
It also seems to assume that CHAR_BIT == BITS_PER_UNIT. */
wide_int from_buffer (const unsigned char *, unsigned int);
@@ -3065,19 +3063,6 @@ namespace wi
unsigned int, unsigned int, bool);
}
-/* Perform a widening multiplication of X and Y, extending the values
- according according to SGN. */
-inline wide_int
-wi::mul_full (const wide_int_ref &x, const wide_int_ref &y, signop sgn)
-{
- gcc_checking_assert (x.precision == y.precision);
- wide_int result = wide_int::create (x.precision * 2);
- result.set_len (mul_internal (result.write_val (), x.val, x.len,
- y.val, y.len, x.precision,
- sgn, 0, false, true));
- return result;
-}
-
/* Return a PRECISION-bit integer in which the low WIDTH bits are set
and the other bits are clear, or the inverse if NEGATE_P. */
inline wide_int