From patchwork Mon Dec 21 16:58:38 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Patrick Palka X-Patchwork-Id: 1419162 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=8.43.85.97; helo=sourceware.org; envelope-from=gcc-patches-bounces@gcc.gnu.org; receiver=) Authentication-Results: ozlabs.org; dmarc=pass (p=none dis=none) header.from=gcc.gnu.org Authentication-Results: ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=gcc.gnu.org header.i=@gcc.gnu.org header.a=rsa-sha256 header.s=default header.b=XhqQ+/Ue; dkim-atps=neutral Received: from sourceware.org (unknown [8.43.85.97]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 4D05KH179kz9sVk for ; Tue, 22 Dec 2020 03:58:57 +1100 (AEDT) Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 6F36B386F47D; Mon, 21 Dec 2020 16:58:51 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 6F36B386F47D DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gcc.gnu.org; s=default; t=1608569931; bh=Gpqd63Ki0Ex+wMMZfCJRAyz1X4PoTvLb5lyizzYnMMM=; h=To:Subject:Date:List-Id:List-Unsubscribe:List-Archive:List-Post: List-Help:List-Subscribe:From:Reply-To:Cc:From; b=XhqQ+/UeTgqx9h/F7Z0u8A6R1nGloBQS5BDQFhCCJN1rY7Tn+uTmGrx+GOFQ+kyKu dvtYIyR0p06yUrqxtLqaSTminyueCslzYTsSwBQYKWfl0i6ykwVqLeXfsI8RuI+onS aFTzkXSTu8tAYPYBU4GPD70SmPAxUBHwa2qLLwig= X-Original-To: gcc-patches@gcc.gnu.org Delivered-To: gcc-patches@gcc.gnu.org Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [216.205.24.124]) by sourceware.org (Postfix) with ESMTP id 85DAE386F47D for ; Mon, 21 Dec 2020 16:58:47 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.3.2 sourceware.org 85DAE386F47D Received: from mail-qk1-f197.google.com (mail-qk1-f197.google.com [209.85.222.197]) (Using TLS) by relay.mimecast.com with ESMTP id us-mta-127-x8gl5AyaNDOBXtCty1bLFg-1; Mon, 21 Dec 2020 11:58:45 -0500 X-MC-Unique: x8gl5AyaNDOBXtCty1bLFg-1 Received: by mail-qk1-f197.google.com with SMTP id p185so3596119qkc.9 for ; Mon, 21 Dec 2020 08:58:45 -0800 (PST) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:mime-version :content-transfer-encoding; bh=Gpqd63Ki0Ex+wMMZfCJRAyz1X4PoTvLb5lyizzYnMMM=; b=btOMBYnbCOwjqCO4q7eClMK/KRhok3vhQSXhlDqAqHbOaduy7xbx0r0qIog8aDPaAi uOwEJDqPJJ08VLPtrzq9F6bj6nnM6Fw/HMbPSp+/+w3kUcCIkNEr9W8yQjs/y7SU5INo yUuk41d77dUteuHMD4JKR7/vqXiZgsKscGpGRB5aENgTUu+iTwh3FtoBDUoO1FhmAoMz OFN5L5/KarG58XCQn8zPABLUuLePbjo0B1gMrDvtYEfEClhm4fE7WNW54HAlUiFxwuNC HAZsH11NZ/g5WBCddRso3eqH4e/ueedkW/RORQqRPn8nPgjwSbqdx7bEx/PpiNCNwHrw m7YA== X-Gm-Message-State: AOAM533zEzMg3f9e6uuvANcdAzKLgfKegWKqu6zRR+QoqCOejVAOjTYS sO+PSwVdL1NaSH8NHawLofGsht2mjOCjngF22UKyNMPwm0ki3G3jxuPAiLCvZEmnektiVKUdDJH aYdmd+Yg9caqqy9Oi7kOyxUxDR9yy7oF46wj8xHOwK7Esw9bYBnZETqOD+8WqnKtTxRc= X-Received: by 2002:a37:6891:: with SMTP id d139mr18141893qkc.240.1608569924240; Mon, 21 Dec 2020 08:58:44 -0800 (PST) X-Google-Smtp-Source: ABdhPJyL9vwIRlf8hQ7M7+q1odXlaeBVQNjKsBHO8RlnR4BJL1ZxNZCFePgXs9k7lJQp8yHNqkpWNQ== X-Received: by 2002:a37:6891:: with SMTP id d139mr18141864qkc.240.1608569923874; Mon, 21 Dec 2020 08:58:43 -0800 (PST) Received: from localhost.localdomain (ool-457d493a.dyn.optonline.net. [69.125.73.58]) by smtp.gmail.com with ESMTPSA id s65sm720314qkh.91.2020.12.21.08.58.42 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 21 Dec 2020 08:58:43 -0800 (PST) To: gcc-patches@gcc.gnu.org Subject: [PATCH] libstdc++: Gracefully disable floating-point to_chars on unsupported targets Date: Mon, 21 Dec 2020 11:58:38 -0500 Message-Id: <20201221165838.1741387-1-ppalka@redhat.com> X-Mailer: git-send-email 2.30.0.rc0 MIME-Version: 1.0 X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com X-Spam-Status: No, score=-14.7 required=5.0 tests=BAYES_00, DKIMWL_WL_HIGH, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, GIT_PATCH_0, KAM_SHORT, RCVD_IN_DNSWL_NONE, RCVD_IN_MSPIKE_H3, RCVD_IN_MSPIKE_WL, SPF_HELO_NONE, SPF_PASS, TXREP, URIBL_SBL, URIBL_SBL_A autolearn=ham autolearn_force=no version=3.4.2 X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) 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: , X-Patchwork-Original-From: Patrick Palka via Gcc-patches From: Patrick Palka Reply-To: Patrick Palka Cc: libstdc++@gcc.gnu.org Errors-To: gcc-patches-bounces@gcc.gnu.org Sender: "Gcc-patches" This patch conditionally disables the floating-point std::to_chars implementation on targets whose float/double are not IEEE binary32 and binary64 respectively, until a proper fallback can be added for such targets. This fixes a bootstrap failure on non-IEEE-754 FP targets such as vax-netbsdelf. The preprocessor conditions that define the new internal libstdc++ macros for detecting the binary32 and binary64 formats were copied from the test gcc/testsuite/gcc.dg/float-exact-1.c. Tested on x86_64-pc-linux-gnu, with and without -m32, and also when artifically undefining the below new macros. Does this look OK for trunk? libstdc++-v3/ChangeLog: * include/bits/c++config (_GLIBCXX_FLOAT_IS_IEEE_BINARY_32): Define this macro. (_GLIBCXX_DOUBLE_IS_IEEE_BINARY_64): Likewise. * include/std/charconv (to_chars): Use the macros to conditionally hide the overloads for floating-point types. * src/c++17/floating_to_chars.cc: Use the macros to conditionally disable this file. (floating_type_traits): Remove redundant static assert. (floating_type_traits): Likewise. * testsuite/20_util/to_chars/double.cc: Use the macros to conditionally disable this test. * testsuite/20_util/to_chars/float.cc: Likewise. * testsuite/20_util/to_chars/long_double.cc: Likewise. Adjust dg-do directives so that we don't execute this test on targets with a large long double type and without int128. --- libstdc++-v3/include/bits/c++config | 14 ++++++++++++++ libstdc++-v3/include/std/charconv | 2 ++ libstdc++-v3/src/c++17/floating_to_chars.cc | 9 +++++---- .../testsuite/20_util/to_chars/double.cc | 2 ++ .../testsuite/20_util/to_chars/float.cc | 2 ++ .../testsuite/20_util/to_chars/long_double.cc | 17 +++++++++++++---- 6 files changed, 38 insertions(+), 8 deletions(-) diff --git a/libstdc++-v3/include/bits/c++config b/libstdc++-v3/include/bits/c++config index 8cce88aa87b..f54074a2c04 100644 --- a/libstdc++-v3/include/bits/c++config +++ b/libstdc++-v3/include/bits/c++config @@ -688,6 +688,20 @@ namespace std # endif #endif +// Define if float has the IEEE binary32 format. +#if __FLT_MANT_DIG__ == 24 \ + && __FLT_MIN_EXP__ == -125 \ + && __FLT_MAX_EXP == 128 +# define _GLIBCXX_FLOAT_IS_IEEE_BINARY32 1 +#endif + +// Define if double has the IEEE binary64 format. +#if __DBL_MANT_DIG__ == 53 \ + && __DBL_MIN_EXP__ == -1021 \ + && __DBL_MAX_EXP__ == 1024 +# define _GLIBCXX_DOUBLE_IS_IEEE_BINARY64 1 +#endif + #ifdef __has_builtin # ifdef __is_identifier // Intel and older Clang require !__is_identifier for some built-ins: diff --git a/libstdc++-v3/include/std/charconv b/libstdc++-v3/include/std/charconv index b57b0a16db2..1f005be47b1 100644 --- a/libstdc++-v3/include/std/charconv +++ b/libstdc++-v3/include/std/charconv @@ -704,6 +704,7 @@ namespace __detail // Floating-point std::to_chars +#if _GLIBCXX_FLOAT_IS_IEEE_BINARY32 && _GLIBCXX_DOUBLE_IS_IEEE_BINARY64 // Overloads for float. to_chars_result to_chars(char* __first, char* __last, float __value) noexcept; to_chars_result to_chars(char* __first, char* __last, float __value, @@ -725,6 +726,7 @@ namespace __detail chars_format __fmt) noexcept; to_chars_result to_chars(char* __first, char* __last, long double __value, chars_format __fmt, int __precision) noexcept; +#endif _GLIBCXX_END_NAMESPACE_VERSION } // namespace std diff --git a/libstdc++-v3/src/c++17/floating_to_chars.cc b/libstdc++-v3/src/c++17/floating_to_chars.cc index b7c31c746cc..6d94d46cc0a 100644 --- a/libstdc++-v3/src/c++17/floating_to_chars.cc +++ b/libstdc++-v3/src/c++17/floating_to_chars.cc @@ -22,6 +22,10 @@ // see the files COPYING3 and COPYING.RUNTIME respectively. If not, see // . +// This implementation crucially assumes float/double have the +// IEEE binary32/binary64 formats. +#if _GLIBCXX_FLOAT_IS_IEEE_BINARY32 && _GLIBCXX_DOUBLE_IS_IEEE_BINARY64 + // Activate __glibcxx_assert within this file to shake out any bugs. #define _GLIBCXX_ASSERTIONS 1 @@ -109,8 +113,6 @@ namespace template<> struct floating_type_traits { - // We (and Ryu) assume float has the IEEE binary32 format. - static_assert(__FLT_MANT_DIG__ == 24); static constexpr int mantissa_bits = 23; static constexpr int exponent_bits = 8; static constexpr bool has_implicit_leading_bit = true; @@ -124,8 +126,6 @@ namespace template<> struct floating_type_traits { - // We (and Ryu) assume double has the IEEE binary64 format. - static_assert(__DBL_MANT_DIG__ == 53); static constexpr int mantissa_bits = 52; static constexpr int exponent_bits = 11; static constexpr bool has_implicit_leading_bit = true; @@ -1565,3 +1565,4 @@ _ZSt8to_charsPcS_eSt12chars_formati(char* first, char* last, double value, _GLIBCXX_END_NAMESPACE_VERSION } // namespace std +#endif // _GLIBCXX_FLOAT_IS_IEEE_BINARY32 && _GLIBCXX_DOUBLE_IS_IEEE_BINARY64 diff --git a/libstdc++-v3/testsuite/20_util/to_chars/double.cc b/libstdc++-v3/testsuite/20_util/to_chars/double.cc index 9d1f37d3026..a52d7e7cd61 100644 --- a/libstdc++-v3/testsuite/20_util/to_chars/double.cc +++ b/libstdc++-v3/testsuite/20_util/to_chars/double.cc @@ -56952,6 +56952,7 @@ inline constexpr double_to_chars_testcase double_hex_precision_to_chars_test_cas void test01() { +#if _GLIBCXX_FLOAT_IS_IEEE_BINARY32 && _GLIBCXX_DOUBLE_IS_IEEE_BINARY64 auto handle_testcases = [] (const auto& testcases) { for (const auto [value,fmt,precision,correct] : testcases) { @@ -56991,6 +56992,7 @@ test01() handle_testcases(double_general_precision_to_chars_test_cases); handle_testcases(double_hex_precision_to_chars_test_cases); +#endif } int diff --git a/libstdc++-v3/testsuite/20_util/to_chars/float.cc b/libstdc++-v3/testsuite/20_util/to_chars/float.cc index b8901063ea0..25fa4defaa9 100644 --- a/libstdc++-v3/testsuite/20_util/to_chars/float.cc +++ b/libstdc++-v3/testsuite/20_util/to_chars/float.cc @@ -4105,6 +4105,7 @@ inline constexpr float_to_chars_testcase float_hex_precision_to_chars_test_cases void test01() { +#if _GLIBCXX_FLOAT_IS_IEEE_BINARY32 && _GLIBCXX_DOUBLE_IS_IEEE_BINARY64 auto handle_testcases = [] (const auto& testcases) { for (const auto [value,fmt,precision,correct] : testcases) { @@ -4133,6 +4134,7 @@ test01() handle_testcases(float_fixed_precision_to_chars_test_cases); handle_testcases(float_general_precision_to_chars_test_cases); handle_testcases(float_hex_precision_to_chars_test_cases); +#endif } int diff --git a/libstdc++-v3/testsuite/20_util/to_chars/long_double.cc b/libstdc++-v3/testsuite/20_util/to_chars/long_double.cc index 12ac8ae7822..e34c6c052cf 100644 --- a/libstdc++-v3/testsuite/20_util/to_chars/long_double.cc +++ b/libstdc++-v3/testsuite/20_util/to_chars/long_double.cc @@ -15,10 +15,15 @@ // with this library; see the file COPYING3. If not see // . -// is supported in C++14 as a GNU extension, but this test uses C++17 -// hexadecimal floating-point literals. -// { dg-do run { target c++17 } } -// { dg-xfail-run-if "Ryu needs __int128" { large_long_double && { ! int128 } } } +// Although is supported in C++14 as a GNU extension, this +// testcase requires C++17 due to its use hexadecimal floating-point literals. +// { dg-require-effective-target c++17 } + +// On targets with a large long double type and without int128, we forward +// the long double to_chars overloads to the double to_chars overloads, +// which leads to a loss in precision in the output relative to printf. +// { dg-do run { target { { ! large_long_double } || int128 } } } +// { dg-do compile { target { large_long_double && { ! int128 } } } } #include @@ -38,6 +43,7 @@ using namespace std; void test01() { +#if _GLIBCXX_FLOAT_IS_IEEE_BINARY32 && _GLIBCXX_DOUBLE_IS_IEEE_BINARY64 const long double hex_testcases[] = { nextdownl(numeric_limits::max()), nextupl(numeric_limits::min()), @@ -124,12 +130,14 @@ test01() VERIFY( !strcmp(to_chars_buffer, printf_buffer+strlen("0x")) ); } } +#endif } // Test the rest of the formatting modes, which go through printf. void test02() { +#if _GLIBCXX_FLOAT_IS_IEEE_BINARY32 && _GLIBCXX_DOUBLE_IS_IEEE_BINARY64 const long double growth_factor = 1.442695040888963407359924681001892137L; for (chars_format fmt : {chars_format::fixed, chars_format::scientific, chars_format::general}) @@ -189,6 +197,7 @@ test02() VERIFY( strcmp(to_chars_buffer, nearby_buffer) != 0 ); } } +#endif } int