From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: by sourceware.org (Postfix, from userid 2153) id 142A33A3E426; Thu, 22 Apr 2021 16:49:43 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 142A33A3E426 MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Content-Type: text/plain; charset="utf-8" From: Jakub Jelinek To: gcc-cvs@gcc.gnu.org Subject: [gcc r8-10872] wide-int: Fix wi::to_mpz [PR98474] X-Act-Checkin: gcc X-Git-Author: Jakub Jelinek X-Git-Refname: refs/heads/releases/gcc-8 X-Git-Oldrev: d8e2170ab33ebd819b8848e43264dc836e344b6b X-Git-Newrev: 8cbe9fc12453026f7efc02dad569c6270d595427 Message-Id: <20210422164943.142A33A3E426@sourceware.org> Date: Thu, 22 Apr 2021 16:49:43 +0000 (GMT) X-BeenThere: gcc-cvs@gcc.gnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Gcc-cvs mailing list List-Unsubscribe: , List-Archive: List-Help: List-Subscribe: , X-List-Received-Date: Thu, 22 Apr 2021 16:49:43 -0000 https://gcc.gnu.org/g:8cbe9fc12453026f7efc02dad569c6270d595427 commit r8-10872-g8cbe9fc12453026f7efc02dad569c6270d595427 Author: Jakub Jelinek Date: Thu Dec 31 11:06:56 2020 +0100 wide-int: Fix wi::to_mpz [PR98474] The following testcase is miscompiled, because niter analysis miscomputes the number of iterations to 0. The problem is that niter analysis uses mpz_t (wonder why, wouldn't widest_int do the same job?) and when wi::to_mpz is called e.g. on the TYPE_MAX_VALUE of __uint128_t, it initializes the mpz_t result with wrong value. wi::to_mpz has code to handle negative wide_ints in signed types by inverting all bits, importing to mpz and complementing it, which is fine, but doesn't handle correctly the case when the wide_int's len (times HOST_BITS_PER_WIDE_INT) is smaller than precision when wi::neg_p. E.g. the 0xffffffffffffffffffffffffffffffff TYPE_MAX_VALUE is represented in wide_int as 0xffffffffffffffff len 1, and wi::to_mpz would create 0xffffffffffffffff mpz_t value from that. This patch handles it by adding the needed -1 host wide int words (and has also code to deal with precision that aren't multiple of HOST_BITS_PER_WIDE_INT). 2020-12-31 Jakub Jelinek PR tree-optimization/98474 * wide-int.cc (wi::to_mpz): If wide_int has MSB set, but type is unsigned and excess negative, append set bits after len until precision. * gcc.c-torture/execute/pr98474.c: New test. (cherry picked from commit a4d191d08c6acb24034af4182b3524e6ef97546c) Diff: --- gcc/testsuite/gcc.c-torture/execute/pr98474.c | 30 +++++++++++++++++++++++++++ gcc/wide-int.cc | 14 +++++++++++++ 2 files changed, 44 insertions(+) diff --git a/gcc/testsuite/gcc.c-torture/execute/pr98474.c b/gcc/testsuite/gcc.c-torture/execute/pr98474.c new file mode 100644 index 00000000000..8c287994580 --- /dev/null +++ b/gcc/testsuite/gcc.c-torture/execute/pr98474.c @@ -0,0 +1,30 @@ +/* PR tree-optimization/98474 */ + +#ifdef __SIZEOF_INT128__ +typedef __uint128_t T; +#define N (__SIZEOF_INT128__ * __CHAR_BIT__ / 2) +#else +typedef unsigned long long T; +#define N (__SIZEOF_LONG_LONG__ * __CHAR_BIT__ / 2) +#endif + +__attribute__ ((noipa)) void +foo (T *x) +{ + *x += ((T) 1) << (N + 1); +} + +int +main () +{ + T a = ((T) 1) << (N + 1); + T b = a; + T n; + foo (&b); + n = b; + while (n >= a) + n -= a; + if ((int) (n >> N) != 0) + __builtin_abort (); + return 0; +} diff --git a/gcc/wide-int.cc b/gcc/wide-int.cc index d686d7dfbe5..eb5eec4a4a6 100644 --- a/gcc/wide-int.cc +++ b/gcc/wide-int.cc @@ -230,6 +230,20 @@ wi::to_mpz (const wide_int_ref &x, mpz_t result, signop sgn) t[len - 1] = (unsigned HOST_WIDE_INT) v[len - 1] << excess >> excess; mpz_import (result, len, -1, sizeof (HOST_WIDE_INT), 0, 0, t); } + else if (excess < 0 && wi::neg_p (x)) + { + int extra + = (-excess + HOST_BITS_PER_WIDE_INT - 1) / HOST_BITS_PER_WIDE_INT; + HOST_WIDE_INT *t = XALLOCAVEC (HOST_WIDE_INT, len + extra); + for (int i = 0; i < len; i++) + t[i] = v[i]; + for (int i = 0; i < extra; i++) + t[len + i] = -1; + excess = (-excess) % HOST_BITS_PER_WIDE_INT; + if (excess) + t[len + extra - 1] = (HOST_WIDE_INT_1U << excess) - 1; + mpz_import (result, len + extra, -1, sizeof (HOST_WIDE_INT), 0, 0, t); + } else mpz_import (result, len, -1, sizeof (HOST_WIDE_INT), 0, 0, v); }