* [PATCH] libstdc++: Gracefully disable floating-point to_chars on unsupported targets
@ 2020-12-21 16:58 Patrick Palka
2020-12-21 18:32 ` Jonathan Wakely
0 siblings, 1 reply; 4+ messages in thread
From: Patrick Palka @ 2020-12-21 16:58 UTC (permalink / raw)
To: gcc-patches; +Cc: libstdc++, Patrick Palka
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<float>): Remove redundant static assert.
(floating_type_traits<double>): 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
// <http://www.gnu.org/licenses/>.
+// 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<float>
{
- // 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<double>
{
- // 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
// <http://www.gnu.org/licenses/>.
-// <charconv> 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 <charconv> 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 <charconv>
@@ -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<long double>::max()),
nextupl(numeric_limits<long double>::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
--
2.30.0.rc0
^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [PATCH] libstdc++: Gracefully disable floating-point to_chars on unsupported targets
2020-12-21 16:58 [PATCH] libstdc++: Gracefully disable floating-point to_chars on unsupported targets Patrick Palka
@ 2020-12-21 18:32 ` Jonathan Wakely
2020-12-21 20:18 ` Patrick Palka
0 siblings, 1 reply; 4+ messages in thread
From: Jonathan Wakely @ 2020-12-21 18:32 UTC (permalink / raw)
To: Patrick Palka; +Cc: gcc-patches, libstdc++
On 21/12/20 11:58 -0500, Patrick Palka via Libstdc++ wrote:
>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<float>): Remove redundant static assert.
> (floating_type_traits<double>): 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
> // <http://www.gnu.org/licenses/>.
>
>+// 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<float>
> {
>- // 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<double>
> {
>- // 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
If I'm reading this right, the compiler is going to churn through
50000 lines defining arrays of numbers, and then do nothing with them.
This would mean you could { dg-require-effective-targets ieee-floats }
so the whole testcase is skipped:
--- a/libstdc++-v3/testsuite/lib/libstdc++.exp
+++ b/libstdc++-v3/testsuite/lib/libstdc++.exp
@@ -1323,6 +1323,14 @@ proc check_effective_target_futex { } {
}]
}
+# Return 1 if float and double have the IEEE binary32 and binary64 formats.
+proc check_effective_target_ieee-floats { } {
+ return [check_v3_target_prop_cached et_ieee_floats {
+ set cond "_GLIBCXX_FLOAT_IS_IEEE_BINARY32 && _GLIBCXX_DOUBLE_IS_IEEE_BINARY64"
+ return [v3_check_preprocessor_condition ieee_floats $cond]
+ }]
+}
+
set additional_prunes ""
if { [info exists env(GCC_RUNTEST_PARALLELIZE_DIR)] \
If something like that works, please do that.
OK for trunk with that if it works, and as in your patch otherwise.
^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [PATCH] libstdc++: Gracefully disable floating-point to_chars on unsupported targets
2020-12-21 18:32 ` Jonathan Wakely
@ 2020-12-21 20:18 ` Patrick Palka
2020-12-21 23:02 ` Maciej W. Rozycki
0 siblings, 1 reply; 4+ messages in thread
From: Patrick Palka @ 2020-12-21 20:18 UTC (permalink / raw)
To: Jonathan Wakely; +Cc: Patrick Palka, gcc-patches, libstdc++
On Mon, 21 Dec 2020, Jonathan Wakely wrote:
> On 21/12/20 11:58 -0500, Patrick Palka via Libstdc++ wrote:
> > 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<float>): Remove redundant static assert.
> > (floating_type_traits<double>): 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
> > // <http://www.gnu.org/licenses/>.
> >
> > +// 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<float>
> > {
> > - // 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<double>
> > {
> > - // 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
>
> If I'm reading this right, the compiler is going to churn through
> 50000 lines defining arrays of numbers, and then do nothing with them.
>
> This would mean you could { dg-require-effective-targets ieee-floats }
> so the whole testcase is skipped:
>
> --- a/libstdc++-v3/testsuite/lib/libstdc++.exp
> +++ b/libstdc++-v3/testsuite/lib/libstdc++.exp
> @@ -1323,6 +1323,14 @@ proc check_effective_target_futex { } {
> }]
> }
>
> +# Return 1 if float and double have the IEEE binary32 and binary64 formats.
> +proc check_effective_target_ieee-floats { } {
> + return [check_v3_target_prop_cached et_ieee_floats {
> + set cond "_GLIBCXX_FLOAT_IS_IEEE_BINARY32 &&
> _GLIBCXX_DOUBLE_IS_IEEE_BINARY64"
> + return [v3_check_preprocessor_condition ieee_floats $cond]
> + }]
> +}
> +
> set additional_prunes ""
>
> if { [info exists env(GCC_RUNTEST_PARALLELIZE_DIR)] \
>
> If something like that works, please do that.
>
> OK for trunk with that if it works, and as in your patch otherwise.
Thanks a lot, this cleaner approach using a new effective target seems
to work well. Here's what I've committed after another round of testing
on x86_64-pc-linux-gnu:
-- >8 --
Subject: [PATCH] libstdc++: Disable floating-point std::to_chars on
unsupported targets
This patch conditionally disables the floating-point std::to_chars
implementation on targets whose float and double aren't IEEE binary32
and binary64, 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 new preprocessor tests in c++config that detect the binary32 and
binary64 formats were copied from gcc/testsuite/gcc.dg/float-exact-1.c.
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 these 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<float>): Remove redundant static assert.
(floating_type_traits<double>): Likewise.
* testsuite/20_util/to_chars/double.cc: Run this test only on
ieee-floats effective targets.
* testsuite/20_util/to_chars/float.cc: Likewise.
* testsuite/20_util/to_chars/long_double.cc: Likewise.
* testsuite/lib/libstdc++.exp
(check_effective_target_ieee-floats): Define new proc for
detecting whether float and double have the IEEE binary32 and
binary64 formats.
---
libstdc++-v3/include/bits/c++config | 14 ++++++++++++++
libstdc++-v3/include/std/charconv | 2 ++
libstdc++-v3/src/c++17/floating_to_chars.cc | 10 ++++++----
libstdc++-v3/testsuite/20_util/to_chars/double.cc | 1 +
libstdc++-v3/testsuite/20_util/to_chars/float.cc | 1 +
.../testsuite/20_util/to_chars/long_double.cc | 1 +
libstdc++-v3/testsuite/lib/libstdc++.exp | 8 ++++++++
7 files changed, 33 insertions(+), 4 deletions(-)
diff --git a/libstdc++-v3/include/bits/c++config b/libstdc++-v3/include/bits/c++config
index 8cce88aa87b..be0961a9d9e 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..c6e80693aad 100644
--- a/libstdc++-v3/include/std/charconv
+++ b/libstdc++-v3/include/std/charconv
@@ -702,6 +702,7 @@ namespace __detail
chars_format __fmt = chars_format::general) noexcept;
#endif
+#if _GLIBCXX_FLOAT_IS_IEEE_BINARY32 && _GLIBCXX_DOUBLE_IS_IEEE_BINARY64
// Floating-point std::to_chars
// Overloads for float.
@@ -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..6e154365aee 100644
--- a/libstdc++-v3/src/c++17/floating_to_chars.cc
+++ b/libstdc++-v3/src/c++17/floating_to_chars.cc
@@ -40,6 +40,10 @@
#include <string_view>
#include <type_traits>
+// This implementation crucially assumes float/double have the
+// IEEE binary32/binary64 formats.
+#if _GLIBCXX_FLOAT_IS_IEEE_BINARY32 && _GLIBCXX_DOUBLE_IS_IEEE_BINARY64
+
// Determine the binary format of 'long double'.
// We support the binary64, float80 (i.e. x86 80-bit extended precision),
@@ -109,8 +113,6 @@ namespace
template<>
struct floating_type_traits<float>
{
- // 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<double>
{
- // 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,5 @@ _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..bb6f74424ed 100644
--- a/libstdc++-v3/testsuite/20_util/to_chars/double.cc
+++ b/libstdc++-v3/testsuite/20_util/to_chars/double.cc
@@ -32,6 +32,7 @@
// DEALINGS IN THE SOFTWARE.
// { dg-do run { target c++17 } }
+// { dg-require-effective-target ieee-floats }
#include <charconv>
diff --git a/libstdc++-v3/testsuite/20_util/to_chars/float.cc b/libstdc++-v3/testsuite/20_util/to_chars/float.cc
index b8901063ea0..0c8dd4f66df 100644
--- a/libstdc++-v3/testsuite/20_util/to_chars/float.cc
+++ b/libstdc++-v3/testsuite/20_util/to_chars/float.cc
@@ -32,6 +32,7 @@
// DEALINGS IN THE SOFTWARE.
// { dg-do run { target c++17 } }
+// { dg-require-effective-target ieee-floats }
#include <charconv>
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..f89daa2c665 100644
--- a/libstdc++-v3/testsuite/20_util/to_chars/long_double.cc
+++ b/libstdc++-v3/testsuite/20_util/to_chars/long_double.cc
@@ -19,6 +19,7 @@
// hexadecimal floating-point literals.
// { dg-do run { target c++17 } }
// { dg-xfail-run-if "Ryu needs __int128" { large_long_double && { ! int128 } } }
+// { dg-require-effective-target ieee-floats }
#include <charconv>
diff --git a/libstdc++-v3/testsuite/lib/libstdc++.exp b/libstdc++-v3/testsuite/lib/libstdc++.exp
index b7d7b906de4..6e5634ef1d2 100644
--- a/libstdc++-v3/testsuite/lib/libstdc++.exp
+++ b/libstdc++-v3/testsuite/lib/libstdc++.exp
@@ -1323,6 +1323,14 @@ proc check_effective_target_futex { } {
}]
}
+# Return 1 if float and double have the IEEE binary32 and binary64 formats.
+proc check_effective_target_ieee-floats { } {
+ return [check_v3_target_prop_cached et_ieee_floats {
+ set cond "_GLIBCXX_FLOAT_IS_IEEE_BINARY32 && _GLIBCXX_DOUBLE_IS_IEEE_BINARY64"
+ return [v3_check_preprocessor_condition ieee_floats $cond]
+ }]
+}
+
set additional_prunes ""
if { [info exists env(GCC_RUNTEST_PARALLELIZE_DIR)] \
--
2.30.0.rc0
^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [PATCH] libstdc++: Gracefully disable floating-point to_chars on unsupported targets
2020-12-21 20:18 ` Patrick Palka
@ 2020-12-21 23:02 ` Maciej W. Rozycki
0 siblings, 0 replies; 4+ messages in thread
From: Maciej W. Rozycki @ 2020-12-21 23:02 UTC (permalink / raw)
To: Patrick Palka; +Cc: Jonathan Wakely, libstdc++, gcc-patches
On Mon, 21 Dec 2020, Patrick Palka via Gcc-patches wrote:
> This patch conditionally disables the floating-point std::to_chars
> implementation on targets whose float and double aren't IEEE binary32
> and binary64, 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.
And I have actually verified this change as posted makes `vax-netbsdelf'
GCC build again. I haven't run any regression testing though.
Thanks for the fix and the short RTT!
Maciej
^ permalink raw reply [flat|nested] 4+ messages in thread
end of thread, other threads:[~2020-12-21 23:02 UTC | newest]
Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-12-21 16:58 [PATCH] libstdc++: Gracefully disable floating-point to_chars on unsupported targets Patrick Palka
2020-12-21 18:32 ` Jonathan Wakely
2020-12-21 20:18 ` Patrick Palka
2020-12-21 23:02 ` Maciej W. Rozycki
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).