re PR middle-end/50708 (Infinite loop between rshift_double and lshift_double if count is LONG_MIN)
2012-03-29 Richard Guenther <rguenther@suse.de> PR middle-end/50708 * double-int.h (rshift_double): Remove. * double-int.c (lshift_double): Use absu_hwi to make count positive. (rshift_double): Make static, take unsigned count argument, remove handling of negative count argument. (double_int_rshift): Dispatch to lshift_double. From-SVN: r185951
This commit is contained in:
parent
0b28472897
commit
477fcae3e8
3 changed files with 78 additions and 77 deletions
|
@ -1,3 +1,13 @@
|
|||
2012-03-29 Richard Guenther <rguenther@suse.de>
|
||||
|
||||
PR middle-end/50708
|
||||
* double-int.h (rshift_double): Remove.
|
||||
* double-int.c (lshift_double): Use absu_hwi to make count
|
||||
positive.
|
||||
(rshift_double): Make static, take unsigned count argument,
|
||||
remove handling of negative count argument.
|
||||
(double_int_rshift): Dispatch to lshift_double.
|
||||
|
||||
2012-03-28 H.J. Lu <hongjiu.lu@intel.com>
|
||||
|
||||
* config/i386/biarch64.h (TARGET_64BIT_DEFAULT): Add
|
||||
|
|
142
gcc/double-int.c
142
gcc/double-int.c
|
@ -186,88 +186,19 @@ mul_double_with_sign (unsigned HOST_WIDE_INT l1, HOST_WIDE_INT h1,
|
|||
return (*hv < 0 ? ~(toplow & tophigh) : toplow | tophigh) != 0;
|
||||
}
|
||||
|
||||
/* Shift the doubleword integer in L1, H1 left by COUNT places
|
||||
keeping only PREC bits of result.
|
||||
Shift right if COUNT is negative.
|
||||
ARITH nonzero specifies arithmetic shifting; otherwise use logical shift.
|
||||
Store the value as two `HOST_WIDE_INT' pieces in *LV and *HV. */
|
||||
|
||||
void
|
||||
lshift_double (unsigned HOST_WIDE_INT l1, HOST_WIDE_INT h1,
|
||||
HOST_WIDE_INT count, unsigned int prec,
|
||||
unsigned HOST_WIDE_INT *lv, HOST_WIDE_INT *hv, bool arith)
|
||||
{
|
||||
unsigned HOST_WIDE_INT signmask;
|
||||
|
||||
if (count < 0)
|
||||
{
|
||||
rshift_double (l1, h1, -count, prec, lv, hv, arith);
|
||||
return;
|
||||
}
|
||||
|
||||
if (SHIFT_COUNT_TRUNCATED)
|
||||
count %= prec;
|
||||
|
||||
if (count >= 2 * HOST_BITS_PER_WIDE_INT)
|
||||
{
|
||||
/* Shifting by the host word size is undefined according to the
|
||||
ANSI standard, so we must handle this as a special case. */
|
||||
*hv = 0;
|
||||
*lv = 0;
|
||||
}
|
||||
else if (count >= HOST_BITS_PER_WIDE_INT)
|
||||
{
|
||||
*hv = l1 << (count - HOST_BITS_PER_WIDE_INT);
|
||||
*lv = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
*hv = (((unsigned HOST_WIDE_INT) h1 << count)
|
||||
| (l1 >> (HOST_BITS_PER_WIDE_INT - count - 1) >> 1));
|
||||
*lv = l1 << count;
|
||||
}
|
||||
|
||||
/* Sign extend all bits that are beyond the precision. */
|
||||
|
||||
signmask = -((prec > HOST_BITS_PER_WIDE_INT
|
||||
? ((unsigned HOST_WIDE_INT) *hv
|
||||
>> (prec - HOST_BITS_PER_WIDE_INT - 1))
|
||||
: (*lv >> (prec - 1))) & 1);
|
||||
|
||||
if (prec >= 2 * HOST_BITS_PER_WIDE_INT)
|
||||
;
|
||||
else if (prec >= HOST_BITS_PER_WIDE_INT)
|
||||
{
|
||||
*hv &= ~((HOST_WIDE_INT) (-1) << (prec - HOST_BITS_PER_WIDE_INT));
|
||||
*hv |= signmask << (prec - HOST_BITS_PER_WIDE_INT);
|
||||
}
|
||||
else
|
||||
{
|
||||
*hv = signmask;
|
||||
*lv &= ~((unsigned HOST_WIDE_INT) (-1) << prec);
|
||||
*lv |= signmask << prec;
|
||||
}
|
||||
}
|
||||
|
||||
/* Shift the doubleword integer in L1, H1 right by COUNT places
|
||||
keeping only PREC bits of result. Shift left if COUNT is negative.
|
||||
ARITH nonzero specifies arithmetic shifting; otherwise use logical shift.
|
||||
keeping only PREC bits of result. ARITH nonzero specifies
|
||||
arithmetic shifting; otherwise use logical shift.
|
||||
Store the value as two `HOST_WIDE_INT' pieces in *LV and *HV. */
|
||||
|
||||
void
|
||||
static void
|
||||
rshift_double (unsigned HOST_WIDE_INT l1, HOST_WIDE_INT h1,
|
||||
HOST_WIDE_INT count, unsigned int prec,
|
||||
unsigned HOST_WIDE_INT count, unsigned int prec,
|
||||
unsigned HOST_WIDE_INT *lv, HOST_WIDE_INT *hv,
|
||||
bool arith)
|
||||
{
|
||||
unsigned HOST_WIDE_INT signmask;
|
||||
|
||||
if (count < 0)
|
||||
{
|
||||
lshift_double (l1, h1, -count, prec, lv, hv, arith);
|
||||
return;
|
||||
}
|
||||
|
||||
signmask = (arith
|
||||
? -((unsigned HOST_WIDE_INT) h1 >> (HOST_BITS_PER_WIDE_INT - 1))
|
||||
: 0);
|
||||
|
@ -317,6 +248,69 @@ rshift_double (unsigned HOST_WIDE_INT l1, HOST_WIDE_INT h1,
|
|||
}
|
||||
}
|
||||
|
||||
/* Shift the doubleword integer in L1, H1 left by COUNT places
|
||||
keeping only PREC bits of result.
|
||||
Shift right if COUNT is negative.
|
||||
ARITH nonzero specifies arithmetic shifting; otherwise use logical shift.
|
||||
Store the value as two `HOST_WIDE_INT' pieces in *LV and *HV. */
|
||||
|
||||
void
|
||||
lshift_double (unsigned HOST_WIDE_INT l1, HOST_WIDE_INT h1,
|
||||
HOST_WIDE_INT count, unsigned int prec,
|
||||
unsigned HOST_WIDE_INT *lv, HOST_WIDE_INT *hv, bool arith)
|
||||
{
|
||||
unsigned HOST_WIDE_INT signmask;
|
||||
|
||||
if (count < 0)
|
||||
{
|
||||
rshift_double (l1, h1, absu_hwi (count), prec, lv, hv, arith);
|
||||
return;
|
||||
}
|
||||
|
||||
if (SHIFT_COUNT_TRUNCATED)
|
||||
count %= prec;
|
||||
|
||||
if (count >= 2 * HOST_BITS_PER_WIDE_INT)
|
||||
{
|
||||
/* Shifting by the host word size is undefined according to the
|
||||
ANSI standard, so we must handle this as a special case. */
|
||||
*hv = 0;
|
||||
*lv = 0;
|
||||
}
|
||||
else if (count >= HOST_BITS_PER_WIDE_INT)
|
||||
{
|
||||
*hv = l1 << (count - HOST_BITS_PER_WIDE_INT);
|
||||
*lv = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
*hv = (((unsigned HOST_WIDE_INT) h1 << count)
|
||||
| (l1 >> (HOST_BITS_PER_WIDE_INT - count - 1) >> 1));
|
||||
*lv = l1 << count;
|
||||
}
|
||||
|
||||
/* Sign extend all bits that are beyond the precision. */
|
||||
|
||||
signmask = -((prec > HOST_BITS_PER_WIDE_INT
|
||||
? ((unsigned HOST_WIDE_INT) *hv
|
||||
>> (prec - HOST_BITS_PER_WIDE_INT - 1))
|
||||
: (*lv >> (prec - 1))) & 1);
|
||||
|
||||
if (prec >= 2 * HOST_BITS_PER_WIDE_INT)
|
||||
;
|
||||
else if (prec >= HOST_BITS_PER_WIDE_INT)
|
||||
{
|
||||
*hv &= ~((HOST_WIDE_INT) (-1) << (prec - HOST_BITS_PER_WIDE_INT));
|
||||
*hv |= signmask << (prec - HOST_BITS_PER_WIDE_INT);
|
||||
}
|
||||
else
|
||||
{
|
||||
*hv = signmask;
|
||||
*lv &= ~((unsigned HOST_WIDE_INT) (-1) << prec);
|
||||
*lv |= signmask << prec;
|
||||
}
|
||||
}
|
||||
|
||||
/* Divide doubleword integer LNUM, HNUM by doubleword integer LDEN, HDEN
|
||||
for a quotient (stored in *LQUO, *HQUO) and remainder (in *LREM, *HREM).
|
||||
CODE is a tree code for a kind of division, one of
|
||||
|
@ -895,7 +889,7 @@ double_int
|
|||
double_int_rshift (double_int a, HOST_WIDE_INT count, unsigned int prec, bool arith)
|
||||
{
|
||||
double_int ret;
|
||||
rshift_double (a.low, a.high, count, prec, &ret.low, &ret.high, arith);
|
||||
lshift_double (a.low, a.high, -count, prec, &ret.low, &ret.high, arith);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
|
@ -300,9 +300,6 @@ extern int mul_double_with_sign (unsigned HOST_WIDE_INT, HOST_WIDE_INT,
|
|||
extern void lshift_double (unsigned HOST_WIDE_INT, HOST_WIDE_INT,
|
||||
HOST_WIDE_INT, unsigned int,
|
||||
unsigned HOST_WIDE_INT *, HOST_WIDE_INT *, bool);
|
||||
extern void rshift_double (unsigned HOST_WIDE_INT, HOST_WIDE_INT,
|
||||
HOST_WIDE_INT, unsigned int,
|
||||
unsigned HOST_WIDE_INT *, HOST_WIDE_INT *, bool);
|
||||
extern int div_and_round_double (unsigned, int, unsigned HOST_WIDE_INT,
|
||||
HOST_WIDE_INT, unsigned HOST_WIDE_INT,
|
||||
HOST_WIDE_INT, unsigned HOST_WIDE_INT *,
|
||||
|
|
Loading…
Add table
Reference in a new issue