From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: by sourceware.org (Postfix, from userid 2153) id C42E33858D33; Thu, 2 Mar 2023 08:28:20 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org C42E33858D33 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gcc.gnu.org; s=default; t=1677745700; bh=2Hs+Kt6j3tR4KFUDPD4fvvPzkQ/+WMp7J0rV/UDUwpA=; h=From:To:Subject:Date:From; b=kzTRN0gdK4k1xm6Z/+ORBOMUp7hwNnHC82AgH1JhuCz138JPBxxxtakww4V3jhRUj RAjMoSyrp7hLVsr9a0/W/24rU/tkC2HZlWJjO6mXw7YH/f4kotz9JQ3760NJFC802Y 7grdWA92C6NCvjOPVJdsUYfFhjxQqEjmvE5unzU0= MIME-Version: 1.0 Content-Transfer-Encoding: 8bit Content-Type: text/plain; charset="utf-8" From: Jakub Jelinek To: gcc-cvs@gcc.gnu.org Subject: [gcc r13-6408] fold-const: Ignore padding bits in native_interpret_expr REAL_CST reverse verification [PR108934] X-Act-Checkin: gcc X-Git-Author: Jakub Jelinek X-Git-Refname: refs/heads/master X-Git-Oldrev: f0ef740d54f47ff614eb02e13e8f4cb11dfbb140 X-Git-Newrev: cc88366a80e35b3e53141f49d3071010ff3c2ef8 Message-Id: <20230302082820.C42E33858D33@sourceware.org> Date: Thu, 2 Mar 2023 08:28:20 +0000 (GMT) List-Id: https://gcc.gnu.org/g:cc88366a80e35b3e53141f49d3071010ff3c2ef8 commit r13-6408-gcc88366a80e35b3e53141f49d3071010ff3c2ef8 Author: Jakub Jelinek Date: Thu Mar 2 09:27:40 2023 +0100 fold-const: Ignore padding bits in native_interpret_expr REAL_CST reverse verification [PR108934] In the following testcase we try to std::bit_cast a (pair of) integral value(s) which has some non-zero bits in the place of x86 long double (for 64-bit 16 byte type with 10 bytes actually loaded/stored by hw, for 32-bit 12 byte) and starting with my PR104522 change we reject that as native_interpret_expr fails on it. The PR104522 change extends what has been done before for MODE_COMPOSITE_P (but those don't have any padding bits) to all floating point types, because e.g. the exact x86 long double has various bit combinations we don't support, like pseudo-(denormals,infinities,NaNs) or unnormals. The HW handles some of those as exceptional cases and others similarly to the non-pseudo ones. But for the padding bits it actually doesn't load/store those bits at all, it loads/stores 10 bytes. So, I think we should exempt the padding bits from the reverse comparison (the native_encode_expr bits for the padding will be all zeros), which the following patch does. For bit_cast it is similar to e.g. ignoring padding bits if the destination is a structure which has padding bits in there. The change changed auto-init-4.c to how it has been behaving before the PR105259 change, where some more VCEs can be now done. 2023-03-02 Jakub Jelinek PR c++/108934 * fold-const.cc (native_interpret_expr) : Before memcmp comparison copy the bytes from ptr to a temporary buffer and clearing padding bits in there. * gcc.target/i386/auto-init-4.c: Revert PR105259 change. * g++.target/i386/pr108934.C: New test. Diff: --- gcc/fold-const.cc | 6 ++++-- gcc/testsuite/g++.target/i386/pr108934.C | 28 ++++++++++++++++++++++++++++ gcc/testsuite/gcc.target/i386/auto-init-4.c | 5 ++--- 3 files changed, 34 insertions(+), 5 deletions(-) diff --git a/gcc/fold-const.cc b/gcc/fold-const.cc index 9aaea71a2fc..99882ef820a 100644 --- a/gcc/fold-const.cc +++ b/gcc/fold-const.cc @@ -8873,11 +8873,13 @@ native_interpret_expr (tree type, const unsigned char *ptr, int len) valid values that GCC can't really represent accurately. See PR95450. Even for other modes, e.g. x86 XFmode can have some bit combinationations which GCC doesn't preserve. */ - unsigned char buf[24]; + unsigned char buf[24 * 2]; scalar_float_mode mode = SCALAR_FLOAT_TYPE_MODE (type); int total_bytes = GET_MODE_SIZE (mode); + memcpy (buf + 24, ptr, total_bytes); + clear_type_padding_in_mask (type, buf + 24); if (native_encode_expr (ret, buf, total_bytes, 0) != total_bytes - || memcmp (ptr, buf, total_bytes) != 0) + || memcmp (buf + 24, buf, total_bytes) != 0) return NULL_TREE; return ret; } diff --git a/gcc/testsuite/g++.target/i386/pr108934.C b/gcc/testsuite/g++.target/i386/pr108934.C new file mode 100644 index 00000000000..bd8f0ffd820 --- /dev/null +++ b/gcc/testsuite/g++.target/i386/pr108934.C @@ -0,0 +1,28 @@ +// PR c++/108934 +// { dg-do compile { target c++11 } } + +struct S { unsigned long long a[2]; }; +struct T { unsigned long long b[6]; }; +struct U { unsigned long long c[2]; long double d; unsigned long long e[2]; }; + +#if __SIZEOF_LONG_DOUBLE__ == 16 && __LDBL_MANT_DIG__ == 64 && __SIZEOF_LONG_LONG__ == 8 +constexpr long double +foo (S x) +{ + return __builtin_bit_cast (long double, x); +} + +constexpr S a = { 0ULL, 0xffffffffffff0000ULL }; +constexpr long double b = foo (a); +static_assert (b == 0.0L, ""); + +constexpr U +bar (T x) +{ + return __builtin_bit_cast (U, x); +} + +constexpr T c = { 0ULL, 0ULL, 0ULL, 0xffffffffffff0000ULL, 0ULL, 0ULL }; +constexpr U d = bar (c); +static_assert (d.d == 0.0L, ""); +#endif diff --git a/gcc/testsuite/gcc.target/i386/auto-init-4.c b/gcc/testsuite/gcc.target/i386/auto-init-4.c index 5b4fd870c36..d9af8f30bb0 100644 --- a/gcc/testsuite/gcc.target/i386/auto-init-4.c +++ b/gcc/testsuite/gcc.target/i386/auto-init-4.c @@ -15,6 +15,5 @@ long double foo() } -/* The long double init isn't expanded optimally, see PR105259. For ia32 - it uses zero-initialization. */ -/* { dg-final { scan-assembler-times "long\t-16843010" 3 } } */ +/* { dg-final { scan-assembler-times "long\t-16843010" 5  { target { ! ia32 } } } } */ +/* { dg-final { scan-assembler-times "long\t-16843010" 3  { target { ia32 } } } } */