diff options
author | Richard Sandiford <rsandifo@gcc.gnu.org> | 2015-08-05 14:23:42 +0000 |
---|---|---|
committer | Richard Sandiford <rsandifo@gcc.gnu.org> | 2015-08-05 14:23:42 +0000 |
commit | dcc74ead1e18da4a7f096ee98424452bc13706da (patch) | |
tree | c75a92c189139311327aecf6784d8ccfed383eac | |
parent | 96b4d193052a70096edb80ed5315b8da6b53e89f (diff) | |
download | gcc-dcc74ead1e18da4a7f096ee98424452bc13706da.zip gcc-dcc74ead1e18da4a7f096ee98424452bc13706da.tar.gz gcc-dcc74ead1e18da4a7f096ee98424452bc13706da.tar.bz2 |
re PR middle-end/66311 (Problems with some integer(16) values)
gcc/
PR middle-end/66311
* wide-int.cc (wi::from_mpz): Make sure that absolute mpz value
is zero- rather than sign-extended.
gcc/testsuite/
2015-08-05 Francois-Xavier Coudert <fxcoudert@gcc.gnu.org>
PR middle-end/66311
* gfortran.dg/pr66311.f90: New file.
From-SVN: r226632
-rw-r--r-- | gcc/ChangeLog | 6 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 5 | ||||
-rw-r--r-- | gcc/testsuite/gfortran.dg/pr66311.f90 | 60 | ||||
-rw-r--r-- | gcc/wide-int.cc | 13 |
4 files changed, 81 insertions, 3 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 7fe826f..7643309 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,5 +1,11 @@ 2015-08-05 Richard Sandiford <richard.sandiford@arm.com> + PR middle-end/66311 + * wide-int.cc (wi::from_mpz): Make sure that absolute mpz value + is zero- rather than sign-extended. + +2015-08-05 Richard Sandiford <richard.sandiford@arm.com> + * target-insns.def (can_extend): Delete. 2015-08-05 Richard Biener <rguenther@suse.de> diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 5ca71c9..e81d1df 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2015-08-05 Francois-Xavier Coudert <fxcoudert@gcc.gnu.org> + + PR middle-end/66311 + * gfortran.dg/pr66311.f90: New file. + 2015-08-05 Richard Biener <rguenther@suse.de> PR tree-optimization/67121 diff --git a/gcc/testsuite/gfortran.dg/pr66311.f90 b/gcc/testsuite/gfortran.dg/pr66311.f90 new file mode 100644 index 0000000..dc40cb6 --- /dev/null +++ b/gcc/testsuite/gfortran.dg/pr66311.f90 @@ -0,0 +1,60 @@ +! { dg-do run } +! { dg-additional-options "-fno-range-check -w" } +! +! Check that we can print large constants +! +! "-fno-range-check -w" is used so the testcase compiles even with targets +! that don't support large integer kinds. + +program test + use iso_fortran_env, only : ikinds => integer_kinds + implicit none + + ! Largest integer kind + integer, parameter :: k = ikinds(size(ikinds)) + integer, parameter :: hk = k / 2 + + if (k <= 8) stop + + call check(9000000000000000000_k, "9000000000000000000") + call check(90000000000000000000_k, "90000000000000000000") + call check(int(huge(1_hk), kind=k), "9223372036854775807") + call check(2_k**63, "9223372036854775808") + call check(10000000000000000000_k, "10000000000000000000") + call check(18446744065119617024_k, "18446744065119617024") + call check(2_k**64 - 1, "18446744073709551615") + call check(2_k**64, "18446744073709551616") + call check(20000000000000000000_k, "20000000000000000000") + call check(huge(0_k), "170141183460469231731687303715884105727") + call check(huge(0_k)-1, "170141183460469231731687303715884105726") + + call check(-9000000000000000000_k, "-9000000000000000000") + call check(-90000000000000000000_k, "-90000000000000000000") + call check(-int(huge(1_hk), kind=k), "-9223372036854775807") + call check(-2_k**63, "-9223372036854775808") + call check(-10000000000000000000_k, "-10000000000000000000") + call check(-18446744065119617024_k, "-18446744065119617024") + call check(-(2_k**64 - 1), "-18446744073709551615") + call check(-2_k**64, "-18446744073709551616") + call check(-20000000000000000000_k, "-20000000000000000000") + call check(-huge(0_k), "-170141183460469231731687303715884105727") + call check(-(huge(0_k)-1), "-170141183460469231731687303715884105726") + call check(-huge(0_k)-1, "-170141183460469231731687303715884105728") + + call check(2_k * huge(1_hk), "18446744073709551614") + call check((-2_k) * huge(1_hk), "-18446744073709551614") + +contains + + subroutine check (i, str) + implicit none + integer(kind=k), intent(in), value :: i + character(len=*), intent(in) :: str + + character(len=100) :: buffer + write(buffer,*) i + if (adjustl(buffer) /= adjustl(str)) call abort + end subroutine + +end + diff --git a/gcc/wide-int.cc b/gcc/wide-int.cc index 13ba10c..9a93660 100644 --- a/gcc/wide-int.cc +++ b/gcc/wide-int.cc @@ -252,13 +252,15 @@ wi::from_mpz (const_tree type, mpz_t x, bool wrap) } /* Determine the number of unsigned HOST_WIDE_INTs that are required - for representing the value. The code to calculate count is + for representing the absolute value. The code to calculate count is extracted from the GMP manual, section "Integer Import and Export": http://gmplib.org/manual/Integer-Import-and-Export.html */ numb = CHAR_BIT * sizeof (HOST_WIDE_INT); count = (mpz_sizeinbase (x, 2) + numb - 1) / numb; HOST_WIDE_INT *val = res.write_val (); - /* Write directly to the wide_int storage if possible, otherwise leave + /* Read the absolute value. + + Write directly to the wide_int storage if possible, otherwise leave GMP to allocate the memory for us. It might be slightly more efficient to use mpz_tdiv_r_2exp for the latter case, but the situation is pathological and it seems safer to operate on the original mpz value @@ -276,7 +278,12 @@ wi::from_mpz (const_tree type, mpz_t x, bool wrap) memcpy (val, valres, count * sizeof (HOST_WIDE_INT)); free (valres); } - res.set_len (canonize (val, count, prec)); + /* Zero-extend the absolute value to PREC bits. */ + if (count < BLOCKS_NEEDED (prec) && val[count - 1] < 0) + val[count++] = 0; + else + count = canonize (val, count, prec); + res.set_len (count); if (mpz_sgn (x) < 0) res = -res; |