PR82547: Undetected overflow for UNSIGNED wide_ints
wi::add_large and wi::sub_large weren't setting the overflow bit correctly for unsigned operations if the result needed fewer HWIs than the precision. 2017-11-22 Richard Sandiford <richard.sandiford@linaro.org> gcc/ PR middle-end/82547 * wide-int.cc (wi::add_large, wi::sub_large): Fix overflow detection for unsigned values with fewer HWIs than the precision. (test_overflow): New function. (wide_int_cc_tests): Call it. From-SVN: r255059
This commit is contained in:
parent
a76ef9c5a8
commit
2131f7f5b7
2 changed files with 53 additions and 5 deletions
|
@ -1,3 +1,11 @@
|
|||
2017-11-22 Richard Sandiford <richard.sandiford@linaro.org>
|
||||
|
||||
PR middle-end/82547
|
||||
* wide-int.cc (wi::add_large, wi::sub_large): Fix overflow detection
|
||||
for unsigned values with fewer HWIs than the precision.
|
||||
(test_overflow): New function.
|
||||
(wide_int_cc_tests): Call it.
|
||||
|
||||
2017-11-22 Richard Sandiford <richard.sandiford@linaro.org>
|
||||
|
||||
* emit-rtl.c (init_derived_machine_modes): Make sure ptr_mode
|
||||
|
|
|
@ -1158,7 +1158,7 @@ wi::add_large (HOST_WIDE_INT *val, const HOST_WIDE_INT *op0,
|
|||
val[len] = mask0 + mask1 + carry;
|
||||
len++;
|
||||
if (overflow)
|
||||
*overflow = false;
|
||||
*overflow = (sgn == UNSIGNED && carry);
|
||||
}
|
||||
else if (overflow)
|
||||
{
|
||||
|
@ -1552,7 +1552,7 @@ wi::sub_large (HOST_WIDE_INT *val, const HOST_WIDE_INT *op0,
|
|||
val[len] = mask0 - mask1 - borrow;
|
||||
len++;
|
||||
if (overflow)
|
||||
*overflow = false;
|
||||
*overflow = (sgn == UNSIGNED && borrow);
|
||||
}
|
||||
else if (overflow)
|
||||
{
|
||||
|
@ -2345,14 +2345,54 @@ static void run_all_wide_int_tests ()
|
|||
test_comparisons <VALUE_TYPE> ();
|
||||
}
|
||||
|
||||
/* Test overflow conditions. */
|
||||
|
||||
static void
|
||||
test_overflow ()
|
||||
{
|
||||
static int precs[] = { 31, 32, 33, 63, 64, 65, 127, 128 };
|
||||
static int offsets[] = { 16, 1, 0 };
|
||||
for (unsigned int i = 0; i < ARRAY_SIZE (precs); ++i)
|
||||
for (unsigned int j = 0; j < ARRAY_SIZE (offsets); ++j)
|
||||
{
|
||||
int prec = precs[i];
|
||||
int offset = offsets[j];
|
||||
bool overflow;
|
||||
wide_int sum, diff;
|
||||
|
||||
sum = wi::add (wi::max_value (prec, UNSIGNED) - offset, 1,
|
||||
UNSIGNED, &overflow);
|
||||
ASSERT_EQ (sum, -offset);
|
||||
ASSERT_EQ (overflow, offset == 0);
|
||||
|
||||
sum = wi::add (1, wi::max_value (prec, UNSIGNED) - offset,
|
||||
UNSIGNED, &overflow);
|
||||
ASSERT_EQ (sum, -offset);
|
||||
ASSERT_EQ (overflow, offset == 0);
|
||||
|
||||
diff = wi::sub (wi::max_value (prec, UNSIGNED) - offset,
|
||||
wi::max_value (prec, UNSIGNED),
|
||||
UNSIGNED, &overflow);
|
||||
ASSERT_EQ (diff, -offset);
|
||||
ASSERT_EQ (overflow, offset != 0);
|
||||
|
||||
diff = wi::sub (wi::max_value (prec, UNSIGNED) - offset,
|
||||
wi::max_value (prec, UNSIGNED) - 1,
|
||||
UNSIGNED, &overflow);
|
||||
ASSERT_EQ (diff, 1 - offset);
|
||||
ASSERT_EQ (overflow, offset > 1);
|
||||
}
|
||||
}
|
||||
|
||||
/* Run all of the selftests within this file, for all value types. */
|
||||
|
||||
void
|
||||
wide_int_cc_tests ()
|
||||
{
|
||||
run_all_wide_int_tests <wide_int> ();
|
||||
run_all_wide_int_tests <offset_int> ();
|
||||
run_all_wide_int_tests <widest_int> ();
|
||||
run_all_wide_int_tests <wide_int> ();
|
||||
run_all_wide_int_tests <offset_int> ();
|
||||
run_all_wide_int_tests <widest_int> ();
|
||||
test_overflow ();
|
||||
}
|
||||
|
||||
} // namespace selftest
|
||||
|
|
Loading…
Add table
Reference in a new issue