From patchwork Tue Aug 23 23:54:00 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Joseph Myers X-Patchwork-Id: 1669506 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@legolas.ozlabs.org Authentication-Results: legolas.ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=gcc.gnu.org (client-ip=8.43.85.97; helo=sourceware.org; envelope-from=gcc-patches-bounces+incoming=patchwork.ozlabs.org@gcc.gnu.org; receiver=) Received: from sourceware.org (ip-8-43-85-97.sourceware.org [8.43.85.97]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (P-384) server-digest SHA384) (No client certificate requested) by legolas.ozlabs.org (Postfix) with ESMTPS id 4MC5g765PFz1yhC for ; Wed, 24 Aug 2022 09:54:26 +1000 (AEST) Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id DA1723857351 for ; Tue, 23 Aug 2022 23:54:21 +0000 (GMT) X-Original-To: gcc-patches@gcc.gnu.org Delivered-To: gcc-patches@gcc.gnu.org Received: from esa3.mentor.iphmx.com (esa3.mentor.iphmx.com [68.232.137.180]) by sourceware.org (Postfix) with ESMTPS id 9FB523857402 for ; Tue, 23 Aug 2022 23:54:07 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.1 sourceware.org 9FB523857402 Authentication-Results: sourceware.org; dmarc=none (p=none dis=none) header.from=codesourcery.com Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=mentor.com X-IronPort-AV: E=Sophos;i="5.93,259,1654588800"; d="scan'208";a="81703501" Received: from orw-gwy-02-in.mentorg.com ([192.94.38.167]) by esa3.mentor.iphmx.com with ESMTP; 23 Aug 2022 15:54:05 -0800 IronPort-SDR: cpKPSCpTACYlFpS8ewBdGQMs7p0FiMDBfOjOQqHeDv8PCQY1R4uyYAg9wJ0mT8EFaeCjeldseG EJDFn7W9zjwNNBpMpqg7MYcXyCAaHpGP2BxSc4LBIH2Y34c3ewZbpOPu17oS0f3Ti8Zawz/D1r lk/tvtvnF1alX42hlGril6FqUUOJ/AeFNQkYc2TkCSTJ+T7U2nhOHLgMqg7+ubfcNYmfOWhae8 RwhDmd2iT7VnNPoBRVfG2qziieTkJ5Y4EKBxuDRPQWK1RC4c8xdHaiKItcQXcjQ46RS54z6E2Z g+4= Date: Tue, 23 Aug 2022 23:54:00 +0000 From: Joseph Myers X-X-Sender: jsm28@digraph.polyomino.org.uk To: Subject: tree.cc: Fix optimization of DFP default initialization Message-ID: User-Agent: Alpine 2.22 (DEB 394 2020-01-19) MIME-Version: 1.0 X-Originating-IP: [137.202.0.90] X-ClientProxiedBy: svr-ies-mbx-15.mgc.mentorg.com (139.181.222.15) To svr-ies-mbx-10.mgc.mentorg.com (139.181.222.10) X-Spam-Status: No, score=-3117.6 required=5.0 tests=BAYES_00, GIT_PATCH_0, HEADER_FROM_DIFFERENT_DOMAINS, KAM_DMARC_STATUS, SPF_HELO_PASS, SPF_PASS, TXREP, T_SCC_BODY_TEXT_LINE autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on server2.sourceware.org X-BeenThere: gcc-patches@gcc.gnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Gcc-patches mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: gcc-patches-bounces+incoming=patchwork.ozlabs.org@gcc.gnu.org Sender: "Gcc-patches" When an object of decimal floating-point type is default-initialized, GCC is inconsistent about whether it is given the all-zero-bits representation (zero with the least quantum exponent) or whether it acts like a conversion of integer 0 to the DFP type (zero with quantum exponent 0). In particular, the representation stored in memory can have all zero bits, but optimization of access to the same object based on its known constant value can then produce zero with quantum exponent 0 instead. C2x leaves the quantum exponent for default initialization implementation-defined, but that doesn't allow such inconsistency in the interpretation of a single object. All zero bits seems most appropriate; change build_real to special-case dconst0 the same way other constants are special-cased and ensure that the correct zero for the type is generated. Bootstrapped with no regressions for x86_64-pc-linux-gnu. OK to commit? gcc/ * tree.cc (build_real): Give DFP dconst0 the minimum quantum exponent for the type. gcc/testsuite/ * gcc.dg/torture/dfp-default-init-1.c, gcc.dg/torture/dfp-default-init-2.c, gcc.dg/torture/dfp-default-init-3.c: New tests. diff --git a/gcc/testsuite/gcc.dg/torture/dfp-default-init-1.c b/gcc/testsuite/gcc.dg/torture/dfp-default-init-1.c new file mode 100644 index 00000000000..f893ddb52b9 --- /dev/null +++ b/gcc/testsuite/gcc.dg/torture/dfp-default-init-1.c @@ -0,0 +1,113 @@ +/* Test that default-initialized DFP values consistently have the least quantum + exponent. */ +/* { dg-do run } */ +/* { dg-require-effective-target dfp } */ + +extern void exit (int); +extern void abort (void); +void *memset (void *, int, __SIZE_TYPE__); +int memcmp (const void *, const void *, __SIZE_TYPE__); + +#ifndef TYPE +#define TYPE _Decimal32 +#endif + +#ifndef ZEROFP +#define ZEROFP 0e-101DF +#endif + +TYPE zero_int = 0; +TYPE zero_fp = ZEROFP; +TYPE default_init; +TYPE zero_bytes; +TYPE x; + +struct s { TYPE a, b; }; +struct s s_default_init; +struct s s_empty_init = {}; +struct s s_first_int = { 0 }; +struct s s_both_int = { 0, 0 }; +struct s sx; + +const TYPE a_default_init[10]; +const TYPE a_empty_init[10] = {}; +const TYPE a_first_int[10] = { 0 }; +const TYPE a_two_int[10] = { 0, 0 }; + +#define CHECK_ZERO_BYTES(expr) \ + do \ + { \ + if (memcmp (expr, &zero_bytes, sizeof zero_bytes) != 0) \ + abort (); \ + TYPE tmp = *expr; \ + if (memcmp (&tmp, &zero_bytes, sizeof zero_bytes) != 0) \ + abort (); \ + } \ + while (0) + +#define CHECK_INT_BYTES(expr) \ + do \ + { \ + if (memcmp (expr, &zero_int, sizeof zero_int) != 0) \ + abort (); \ + TYPE tmp = *expr; \ + if (memcmp (&tmp, &zero_int, sizeof zero_int) != 0) \ + abort (); \ + } \ + while (0) + +int +main (void) +{ + memset (&zero_bytes, 0, sizeof zero_bytes); + if (memcmp (&zero_bytes, &zero_int, sizeof zero_int) == 0) + abort (); + CHECK_ZERO_BYTES (&zero_fp); + CHECK_ZERO_BYTES (&default_init); + CHECK_ZERO_BYTES (&s_default_init.a); + CHECK_ZERO_BYTES (&s_default_init.b); + CHECK_ZERO_BYTES (&s_empty_init.a); + CHECK_ZERO_BYTES (&s_empty_init.b); + CHECK_INT_BYTES (&s_first_int.a); + CHECK_ZERO_BYTES (&s_first_int.b); + CHECK_INT_BYTES (&s_both_int.a); + CHECK_INT_BYTES (&s_both_int.b); + CHECK_ZERO_BYTES (&a_default_init[0]); + CHECK_ZERO_BYTES (&a_default_init[1]); + CHECK_ZERO_BYTES (&a_default_init[2]); + CHECK_ZERO_BYTES (&a_default_init[9]); + CHECK_ZERO_BYTES (&a_empty_init[0]); + CHECK_ZERO_BYTES (&a_empty_init[1]); + CHECK_ZERO_BYTES (&a_empty_init[2]); + CHECK_ZERO_BYTES (&a_empty_init[9]); + CHECK_INT_BYTES (&a_first_int[0]); + CHECK_ZERO_BYTES (&a_first_int[1]); + CHECK_ZERO_BYTES (&a_first_int[2]); + CHECK_ZERO_BYTES (&a_first_int[9]); + CHECK_INT_BYTES (&a_two_int[0]); + CHECK_INT_BYTES (&a_two_int[1]); + CHECK_ZERO_BYTES (&a_two_int[2]); + CHECK_ZERO_BYTES (&a_two_int[9]); + struct s s2 = {}; + CHECK_ZERO_BYTES (&s2.a); + CHECK_ZERO_BYTES (&s2.b); + struct s s3 = { 0 }; + CHECK_INT_BYTES (&s3.a); + CHECK_ZERO_BYTES (&s3.b); + struct s s4 = { 0, 0 }; + CHECK_INT_BYTES (&s4.a); + CHECK_INT_BYTES (&s4.b); + struct s s5 = { 0 }; + sx = s5; + CHECK_INT_BYTES (&sx.a); + CHECK_ZERO_BYTES (&sx.b); + x = default_init; + CHECK_ZERO_BYTES (&x); + x = zero_int; + CHECK_INT_BYTES (&x); + x = s_default_init.a; + CHECK_ZERO_BYTES (&x); + x = s_default_init.b; + CHECK_ZERO_BYTES (&x); + exit (0); +} diff --git a/gcc/testsuite/gcc.dg/torture/dfp-default-init-2.c b/gcc/testsuite/gcc.dg/torture/dfp-default-init-2.c new file mode 100644 index 00000000000..30f850be2ee --- /dev/null +++ b/gcc/testsuite/gcc.dg/torture/dfp-default-init-2.c @@ -0,0 +1,8 @@ +/* Test that default-initialized DFP values consistently have the least quantum + exponent. */ +/* { dg-do run } */ +/* { dg-require-effective-target dfp } */ + +#define TYPE _Decimal64 +#define ZEROFP 0e-398DD +#include "dfp-default-init-1.c" diff --git a/gcc/testsuite/gcc.dg/torture/dfp-default-init-3.c b/gcc/testsuite/gcc.dg/torture/dfp-default-init-3.c new file mode 100644 index 00000000000..cdf73508c76 --- /dev/null +++ b/gcc/testsuite/gcc.dg/torture/dfp-default-init-3.c @@ -0,0 +1,8 @@ +/* Test that default-initialized DFP values consistently have the least quantum + exponent. */ +/* { dg-do run } */ +/* { dg-require-effective-target dfp } */ + +#define TYPE _Decimal128 +#define ZEROFP 0e-6176DL +#include "dfp-default-init-1.c" diff --git a/gcc/tree.cc b/gcc/tree.cc index fed1434d141..007c9325b17 100644 --- a/gcc/tree.cc +++ b/gcc/tree.cc @@ -2385,12 +2385,12 @@ build_real (tree type, REAL_VALUE_TYPE d) tree v; int overflow = 0; - /* dconst{1,2,m1,half} are used in various places in + /* dconst{0,1,2,m1,half} are used in various places in the middle-end and optimizers, allow them here even for decimal floating point types as an exception by converting them to decimal. */ if (DECIMAL_FLOAT_MODE_P (TYPE_MODE (type)) - && d.cl == rvc_normal + && (d.cl == rvc_normal || d.cl == rvc_zero) && !d.decimal) { if (memcmp (&d, &dconst1, sizeof (d)) == 0) @@ -2401,6 +2401,15 @@ build_real (tree type, REAL_VALUE_TYPE d) decimal_real_from_string (&d, "-1"); else if (memcmp (&d, &dconsthalf, sizeof (d)) == 0) decimal_real_from_string (&d, "0.5"); + else if (memcmp (&d, &dconst0, sizeof (d)) == 0) + { + /* Make sure to give zero the minimum quantum exponent for + the type (which corresponds to all bits zero). */ + const struct real_format *fmt = REAL_MODE_FORMAT (TYPE_MODE (type)); + char buf[16]; + sprintf (buf, "0e%d", fmt->emin - fmt->p); + decimal_real_from_string (&d, buf); + } else gcc_unreachable (); }