From patchwork Fri Nov 29 20:53:30 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Joseph Myers X-Patchwork-Id: 1202592 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=gcc.gnu.org (client-ip=209.132.180.131; helo=sourceware.org; envelope-from=gcc-patches-return-514894-incoming=patchwork.ozlabs.org@gcc.gnu.org; receiver=) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=codesourcery.com Authentication-Results: ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=gcc.gnu.org header.i=@gcc.gnu.org header.b="Wx3Sz6iA"; dkim-atps=neutral Received: from sourceware.org (server1.sourceware.org [209.132.180.131]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 47PmvL3FZZz9sPW for ; Sat, 30 Nov 2019 07:53:47 +1100 (AEDT) DomainKey-Signature: a=rsa-sha1; c=nofws; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender:date :from:to:subject:message-id:mime-version:content-type; q=dns; s= default; b=Yl4rnMh7pe2pLRvSy4nSVdBwD9oO9NrfR77kT+S0B7+d/haMQ3Ym9 QSwV1gaP7H7tsgWgjAxini5DvNAM71seroV0grCR6ZNNukC/6vtef7mVwi0YB/EO duBV9zhF0f/5bqZuFOmEfq5/e6onXpdLQMzP6F6IVaO4iJq7TpR/h4= DKIM-Signature: v=1; a=rsa-sha1; c=relaxed; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender:date :from:to:subject:message-id:mime-version:content-type; s= default; bh=sFeejfPY34nOJbz+4K4NvWq68EY=; b=Wx3Sz6iAOoUC13QHt33i j6yL07pKIyYXKzstKfAVR5bFz6U8nGVAW39M4YsVMLANnGMwezvzdgHYh4bXCUWv k7gHJUT8uJnW5bzqFx7PArsiJIDqxZM9h20OcTuYZcwwK5ebvVziSt8PUafXhtFB Hsrqs6h5Z49mKkX4QCfu6aw= Received: (qmail 55894 invoked by alias); 29 Nov 2019 20:53:39 -0000 Mailing-List: contact gcc-patches-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Archive: List-Post: List-Help: Sender: gcc-patches-owner@gcc.gnu.org Delivered-To: mailing list gcc-patches@gcc.gnu.org Received: (qmail 55886 invoked by uid 89); 29 Nov 2019 20:53:39 -0000 Authentication-Results: sourceware.org; auth=none X-Spam-SWARE-Status: No, score=-7.3 required=5.0 tests=AWL, BAYES_00, GIT_PATCH_2, GIT_PATCH_3, KAM_ASCII_DIVIDERS, SPF_PASS autolearn=ham version=3.3.1 spammy=quantum, 1100, backporting, wrongcode X-HELO: esa1.mentor.iphmx.com Received: from esa1.mentor.iphmx.com (HELO esa1.mentor.iphmx.com) (68.232.129.153) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Fri, 29 Nov 2019 20:53:37 +0000 IronPort-SDR: aEZMrqjFjoIid8UuvRVv6q2EgewO1idpGORzHgC2Se+hxHuPC7DcxgV93IxWbBKD7CAVFfwqUv C9tuCk3vV1loFZscJTyUBihBCMvLmZarAAUyWn/PHy34G8ehi0SA/xP9SY1vZVcaYCA/jEUEfL wj5hYh6JpsKGmjqniqk+luL/U2n6ZnEjRkHWoSN5WjFmLIw842ziECksVY0zkAd6k/KShcnYXG fSaNmJJ7esALS6BlhDWVFZT3cPhf58Zb4xfNE6dTJtp+rqC7N63Y8E3XKSCD1tDIjYeNt0cBY0 1mc= Received: from orw-gwy-01-in.mentorg.com ([192.94.38.165]) by esa1.mentor.iphmx.com with ESMTP; 29 Nov 2019 12:53:35 -0800 IronPort-SDR: YDh6kiji3fSTBQnVf6EPXf2OLdxeSPCncMjawjLd3vgecgsUkbd0LlpBy4VEg0eTRFB7qiqE+k l7TCTmb1x1J/SPUADeTlsfxo47zwtqyTxagyxziHvW0DLK9GFUCZUspaZ/bHuvuUaeq8t+gXfv q9HryN4pLHBfg3jeFDRoF8+emrMKVskL9ZlSuYtUysMVWxKVlZSfhIX1O2KIz5EG8GAjoiLcZs /H/F4vw3kn+2EvDIACgjetmzHLVWi6Zpx85cSX87rECDv6h3KVpZ+BTuwfuW9oCgackNmoRRxk DFU= Date: Fri, 29 Nov 2019 20:53:30 +0000 From: Joseph Myers To: Subject: Fix libdecnumber handling of non-canonical BID significands (PR middle-end/91226) Message-ID: User-Agent: Alpine 2.21 (DEB 202 2017-01-01) MIME-Version: 1.0 As reported in bug 91226, the libdecnumber code used on the host to interpret DFP values in the BID encoding fails, for _Decimal64 and _Decimal128, to check for the case where a significand is too large and so specified in IEEE 754 to be a non-canonical encoding of the zero significand. This patch adds the required handling of that case, together with tests both using -O2 (testing this host code) and -O0 (testing libgcc code, which already worked before the patch); the tests also cover _Decimal32, which already had the required check. In the _Decimal128 case, where the code previously completely ignored the case where the first four bits of the combination field are 1100, 1101 or 1110, the logic for determining the correct quantum exponent in that case is also newly added by this patch, so tests are added for that as well (again, libgcc already handled it correctly when the conversion was done at runtime rather than at compile time). Bootstrapped with no regressions for x86_64-pc-linux-gnu. OK to commit (to trunk)? (Note 1: we don't have a maintainer for libdecnumber. Note 2: as a wrong-code fix, this could be considered later for backporting to release branches if no problems appear with it on trunk. Note 3: presumably binutils-gdb will pick this up at some point through a merge of libdecnumber from the GCC repository.) libdecnumber: 2019-11-29 Joseph Myers PR middle-end/91226 * bid/bid2dpd_dpd2bid.c (_bid_to_dpd64): Handle non-canonical significands. (_bid_to_dpd128): Likewise. Check for case where combination field starts 1100, 1101 or 1110. gcc/testsuite: 2019-11-29 Joseph Myers PR middle-end/91226 * gcc.dg/dfp/bid-non-canonical-d128-1.c, gcc.dg/dfp/bid-non-canonical-d128-2.c, gcc.dg/dfp/bid-non-canonical-d128-3.c, gcc.dg/dfp/bid-non-canonical-d128-4.c, gcc.dg/dfp/bid-non-canonical-d32-1.c, gcc.dg/dfp/bid-non-canonical-d32-2.c, gcc.dg/dfp/bid-non-canonical-d64-1.c, gcc.dg/dfp/bid-non-canonical-d64-2.c: New tests. Index: gcc/testsuite/gcc.dg/dfp/bid-non-canonical-d128-1.c =================================================================== --- gcc/testsuite/gcc.dg/dfp/bid-non-canonical-d128-1.c (nonexistent) +++ gcc/testsuite/gcc.dg/dfp/bid-non-canonical-d128-1.c (working copy) @@ -0,0 +1,30 @@ +/* Test non-canonical BID significands: _Decimal128. Bug 91226. */ +/* { dg-do run { target { { i?86-*-* x86_64-*-* } && lp64 } } } */ +/* { dg-options "-std=gnu2x -O2" } */ + +extern void abort (void); +extern void exit (int); + +union u +{ + _Decimal128 d128; + unsigned __int128 u128; +}; + +#define U128(hi, lo) (((unsigned __int128) lo) \ + | (((unsigned __int128) hi) << 64)) + +int +main (void) +{ + unsigned __int128 i = U128 (0x3041ed09bead87c0ULL, 0x378d8e6400000001ULL); + union u x; + _Decimal128 d128; + x.u128 = i; + d128 = x.d128; + volatile double d = d128; + if (d == 0) + exit (0); + else + abort (); +} Index: gcc/testsuite/gcc.dg/dfp/bid-non-canonical-d128-2.c =================================================================== --- gcc/testsuite/gcc.dg/dfp/bid-non-canonical-d128-2.c (nonexistent) +++ gcc/testsuite/gcc.dg/dfp/bid-non-canonical-d128-2.c (working copy) @@ -0,0 +1,42 @@ +/* Test non-canonical BID significands: _Decimal128, case where + combination field starts 11. Bug 91226. */ +/* { dg-do run { target { { i?86-*-* x86_64-*-* } && lp64 } } } */ +/* { dg-options "-std=gnu2x -O2" } */ + +extern void abort (void); +extern void exit (int); + +union u +{ + _Decimal128 d128; + unsigned __int128 u128; +}; + +#define U128(hi, lo) (((unsigned __int128) lo) \ + | (((unsigned __int128) hi) << 64)) + +int +main (void) +{ + unsigned __int128 i = U128 (0x6e79000000000000ULL, 0x1ULL); + union u x; + _Decimal128 d128; + x.u128 = i; + d128 = x.d128; + volatile double d = d128; + if (d != 0) + abort (); + /* The above number should have quantum exponent 1234. */ + _Decimal128 t1233 = 0.e1233DL, t1234 = 0.e1234DL, t1235 = 0.e1235DL; + _Decimal128 dx; + dx = d128 + t1233; + if (__builtin_memcmp (&dx, &t1233, 16) != 0) + abort (); + dx = d128 + t1234; + if (__builtin_memcmp (&dx, &t1234, 16) != 0) + abort (); + dx = d128 + t1235; + if (__builtin_memcmp (&dx, &t1234, 16) != 0) + abort (); + exit (0); +} Index: gcc/testsuite/gcc.dg/dfp/bid-non-canonical-d128-3.c =================================================================== --- gcc/testsuite/gcc.dg/dfp/bid-non-canonical-d128-3.c (nonexistent) +++ gcc/testsuite/gcc.dg/dfp/bid-non-canonical-d128-3.c (working copy) @@ -0,0 +1,5 @@ +/* Test non-canonical BID significands: _Decimal128. Bug 91226. */ +/* { dg-do run { target { { i?86-*-* x86_64-*-* } && lp64 } } } */ +/* { dg-options "-std=gnu2x -O0" } */ + +#include "bid-non-canonical-d128-1.c" Index: gcc/testsuite/gcc.dg/dfp/bid-non-canonical-d128-4.c =================================================================== --- gcc/testsuite/gcc.dg/dfp/bid-non-canonical-d128-4.c (nonexistent) +++ gcc/testsuite/gcc.dg/dfp/bid-non-canonical-d128-4.c (working copy) @@ -0,0 +1,6 @@ +/* Test non-canonical BID significands: _Decimal128, case where + combination field starts 11. Bug 91226. */ +/* { dg-do run { target { { i?86-*-* x86_64-*-* } && lp64 } } } */ +/* { dg-options "-std=gnu2x -O0" } */ + +#include "bid-non-canonical-d128-2.c" Index: gcc/testsuite/gcc.dg/dfp/bid-non-canonical-d32-1.c =================================================================== --- gcc/testsuite/gcc.dg/dfp/bid-non-canonical-d32-1.c (nonexistent) +++ gcc/testsuite/gcc.dg/dfp/bid-non-canonical-d32-1.c (working copy) @@ -0,0 +1,26 @@ +/* Test non-canonical BID significands: _Decimal32. Bug 91226. */ +/* { dg-do run { target i?86-*-* x86_64-*-* } } */ +/* { dg-options "-std=gnu2x -O2" } */ + +extern void abort (void); +extern void exit (int); + +union u +{ + _Decimal32 d32; + unsigned int u32; +}; + +int +main (void) +{ + union u x; + _Decimal32 d32; + x.u32 = 0x6cb89681U; + d32 = x.d32; + volatile double d = d32; + if (d == 0) + exit (0); + else + abort (); +} Index: gcc/testsuite/gcc.dg/dfp/bid-non-canonical-d32-2.c =================================================================== --- gcc/testsuite/gcc.dg/dfp/bid-non-canonical-d32-2.c (nonexistent) +++ gcc/testsuite/gcc.dg/dfp/bid-non-canonical-d32-2.c (working copy) @@ -0,0 +1,5 @@ +/* Test non-canonical BID significands: _Decimal32. Bug 91226. */ +/* { dg-do run { target i?86-*-* x86_64-*-* } } */ +/* { dg-options "-std=gnu2x -O0" } */ + +#include "bid-non-canonical-d32-1.c" Index: gcc/testsuite/gcc.dg/dfp/bid-non-canonical-d64-1.c =================================================================== --- gcc/testsuite/gcc.dg/dfp/bid-non-canonical-d64-1.c (nonexistent) +++ gcc/testsuite/gcc.dg/dfp/bid-non-canonical-d64-1.c (working copy) @@ -0,0 +1,26 @@ +/* Test non-canonical BID significands: _Decimal64. Bug 91226. */ +/* { dg-do run { target i?86-*-* x86_64-*-* } } */ +/* { dg-options "-std=gnu2x -O2" } */ + +extern void abort (void); +extern void exit (int); + +union u +{ + _Decimal64 d64; + unsigned long long int u64; +}; + +int +main (void) +{ + union u x; + _Decimal64 d64; + x.u64 = 0x6c7386f26fc10001ULL; + d64 = x.d64; + volatile double d = d64; + if (d == 0) + exit (0); + else + abort (); +} Index: gcc/testsuite/gcc.dg/dfp/bid-non-canonical-d64-2.c =================================================================== --- gcc/testsuite/gcc.dg/dfp/bid-non-canonical-d64-2.c (nonexistent) +++ gcc/testsuite/gcc.dg/dfp/bid-non-canonical-d64-2.c (working copy) @@ -0,0 +1,5 @@ +/* Test non-canonical BID significands: _Decimal64. Bug 91226. */ +/* { dg-do run { target i?86-*-* x86_64-*-* } } */ +/* { dg-options "-std=gnu2x -O0" } */ + +#include "bid-non-canonical-d64-1.c" Index: libdecnumber/bid/bid2dpd_dpd2bid.c =================================================================== --- libdecnumber/bid/bid2dpd_dpd2bid.c (revision 278845) +++ libdecnumber/bid/bid2dpd_dpd2bid.c (working copy) @@ -189,6 +189,8 @@ _bid_to_dpd64 (_Decimal64 *pres, _Decimal64 *px) { if ((comb & 0xc00) == 0xc00) { /* G0..G1 = 11 -> exp is G2..G11 */ exp = (comb) & 0x3ff; bcoeff = (x & 0x0007ffffffffffffull) | 0x0020000000000000ull; + if (bcoeff >= 10000000000000000ull) + bcoeff = 0; } else { exp = (comb >> 2) & 0x3ff; bcoeff = (x & 0x001fffffffffffffull); @@ -298,9 +300,23 @@ _bid_to_dpd128 (_Decimal128 *pres, _Decimal128 *px if ((comb & 0x1e000) == 0x1e000) { res = x; } else { /* normal number */ - exp = ((x.w[1] & 0x7fff000000000000ull) >> 49) & 0x3fff; - bcoeff.w[1] = (x.w[1] & 0x0001ffffffffffffull); - bcoeff.w[0] = x.w[0]; + if ((comb & 0x18000) == 0x18000) { + /* Noncanonical significand (prepending 8 or 9 to any 110-bit + trailing significand field produces a value above 10^34). */ + exp = (comb & 0x7fff) >> 1; + bcoeff.w[1] = 0; + bcoeff.w[0] = 0; + } else { + exp = ((x.w[1] & 0x7fff000000000000ull) >> 49) & 0x3fff; + bcoeff.w[1] = (x.w[1] & 0x0001ffffffffffffull); + bcoeff.w[0] = x.w[0]; + if (bcoeff.w[1] > 0x1ed09bead87c0ull + || (bcoeff.w[1] == 0x1ed09bead87c0ull + && bcoeff.w[0] >= 0x378d8e6400000000ull)) { + bcoeff.w[1] = 0; + bcoeff.w[0] = 0; + } + } d1018 = reciprocals10_128[18]; __mul_128x128_high (BH, bcoeff, d1018); amount = recip_scale[18];