libstdc++: Use if consteval rather than if (std::__is_constant_evaluated()) for {,b}float16_t nextafter [PR117321]

Message ID ZyCj3ly2nCDEcXDo@tucnak
State New
Headers
Series libstdc++: Use if consteval rather than if (std::__is_constant_evaluated()) for {,b}float16_t nextafter [PR117321] |

Checks

Context Check Description
linaro-tcwg-bot/tcwg_gcc_build--master-arm success Build passed
linaro-tcwg-bot/tcwg_gcc_check--master-arm success Test passed
linaro-tcwg-bot/tcwg_gcc_build--master-aarch64 fail Patch failed to apply

Commit Message

Jakub Jelinek Oct. 29, 2024, 8:59 a.m. UTC
  Hi!

The nextafter_c++23.cc testcase fails to link at -O0.
The problem is that eventhough std::__is_constant_evaluated() has
always_inline attribute, that at -O0 just means that we inline the
call, but its result is still assigned to a temporary which is tested
later, nothing at -O0 propagates that false into the if and optimizes
away the if body.  And the __builtin_nextafterf16{,b} calls are meant
to be used solely for constant evaluation, the C libraries don't
define nextafterf16 these days.

As __STDCPP_FLOAT16_T__ and __STDCPP_BFLOAT16_T__ are predefined right
now only by GCC, not by clang which doesn't implement the extended floating
point types paper, and as they are predefined in C++23 and later modes only,
I think we can just use if consteval which is folded already during the FE
and the body isn't included even at -O0.  I've added a feature test for
that just in case clang implements those and implements those in some weird
way.  Note, if (__builtin_is_constant_evaluted()) would work correctly too,
that is also folded to false at gimplification time and the corresponding
if block not emitted at all.  But for -O0 it can't be wrapped into a helper
inline function.

Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk?

2024-10-29  Jakub Jelinek  <jakub@redhat.com>

	PR libstdc++/117321
	* include/c_global/cmath (nextafter(_Float16, _Float16)): Use
	if consteval rather than if (std::__is_constant_evaluated()) around
	the __builtin_nextafterf16 call.
	(nextafter(__gnu_cxx::__bfloat16_t, __gnu_cxx::__bfloat16_t)): Use
	if consteval rather than if (std::__is_constant_evaluated()) around
	the __builtin_nextafterf16b call.
	* testsuite/26_numerics/headers/cmath/117321.cc: New test.


	Jakub
  

Comments

Jonathan Wakely Oct. 29, 2024, 9:07 a.m. UTC | #1
On Tue, 29 Oct 2024, 09:00 Jakub Jelinek, <jakub@redhat.com> wrote:

> Hi!
>
> The nextafter_c++23.cc testcase fails to link at -O0.
> The problem is that eventhough std::__is_constant_evaluated() has
> always_inline attribute, that at -O0 just means that we inline the
> call, but its result is still assigned to a temporary which is tested
> later, nothing at -O0 propagates that false into the if and optimizes
> away the if body.  And the __builtin_nextafterf16{,b} calls are meant
> to be used solely for constant evaluation, the C libraries don't
> define nextafterf16 these days.
>
> As __STDCPP_FLOAT16_T__ and __STDCPP_BFLOAT16_T__ are predefined right
> now only by GCC, not by clang which doesn't implement the extended floating
> point types paper, and as they are predefined in C++23 and later modes
> only,
> I think we can just use if consteval which is folded already during the FE
> and the body isn't included even at -O0.  I've added a feature test for
> that just in case clang implements those and implements those in some weird
> way.  Note, if (__builtin_is_constant_evaluted()) would work correctly too,
> that is also folded to false at gimplification time and the corresponding
> if block not emitted at all.  But for -O0 it can't be wrapped into a helper
> inline function.
>
> Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk?
>

OK, thanks


> 2024-10-29  Jakub Jelinek  <jakub@redhat.com>
>
>         PR libstdc++/117321
>         * include/c_global/cmath (nextafter(_Float16, _Float16)): Use
>         if consteval rather than if (std::__is_constant_evaluated()) around
>         the __builtin_nextafterf16 call.
>         (nextafter(__gnu_cxx::__bfloat16_t, __gnu_cxx::__bfloat16_t)): Use
>         if consteval rather than if (std::__is_constant_evaluated()) around
>         the __builtin_nextafterf16b call.
>         * testsuite/26_numerics/headers/cmath/117321.cc: New test.
>
> --- libstdc++-v3/include/c_global/cmath.jj      2024-09-25
> 17:25:07.227360607 +0200
> +++ libstdc++-v3/include/c_global/cmath 2024-10-28 13:10:46.348655046 +0100
> @@ -2880,8 +2880,12 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
>    constexpr _Float16
>    nextafter(_Float16 __x, _Float16 __y)
>    {
> -    if (std::__is_constant_evaluated())
> -      return __builtin_nextafterf16(__x, __y);
> +#if __cpp_if_consteval >= 202106L
> +    // Can't use if (std::__is_constant_evaluated()) here, as it
> +    // doesn't guarantee optimizing the body away at -O0 and
> +    // nothing defines nextafterf16.
> +    if consteval { return __builtin_nextafterf16(__x, __y); }
> +#endif
>  #ifdef __INT16_TYPE__
>      using __float16_int_type = __INT16_TYPE__;
>  #else
> @@ -3598,8 +3602,12 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
>    constexpr __gnu_cxx::__bfloat16_t
>    nextafter(__gnu_cxx::__bfloat16_t __x, __gnu_cxx::__bfloat16_t __y)
>    {
> -    if (std::__is_constant_evaluated())
> -      return __builtin_nextafterf16b(__x, __y);
> +#if __cpp_if_consteval >= 202106L
> +    // Can't use if (std::__is_constant_evaluated()) here, as it
> +    // doesn't guarantee optimizing the body away at -O0 and
> +    // nothing defines nextafterf16b.
> +    if consteval { return __builtin_nextafterf16b(__x, __y); }
> +#endif
>  #ifdef __INT16_TYPE__
>      using __bfloat16_int_type = __INT16_TYPE__;
>  #else
> --- libstdc++-v3/testsuite/26_numerics/headers/cmath/117321.cc.jj
>  2024-10-28 12:56:10.699876240 +0100
> +++ libstdc++-v3/testsuite/26_numerics/headers/cmath/117321.cc  2024-10-28
> 12:56:59.875189173 +0100
> @@ -0,0 +1,5 @@
> +// { dg-do run { target c++23 } }
> +// { dg-require-cmath "" }
> +// { dg-additional-options "-O0" }
> +
> +#include "nextafter_c++23.cc"
>
>         Jakub
>
>
  

Patch

--- libstdc++-v3/include/c_global/cmath.jj	2024-09-25 17:25:07.227360607 +0200
+++ libstdc++-v3/include/c_global/cmath	2024-10-28 13:10:46.348655046 +0100
@@ -2880,8 +2880,12 @@  _GLIBCXX_BEGIN_NAMESPACE_VERSION
   constexpr _Float16
   nextafter(_Float16 __x, _Float16 __y)
   {
-    if (std::__is_constant_evaluated())
-      return __builtin_nextafterf16(__x, __y);
+#if __cpp_if_consteval >= 202106L
+    // Can't use if (std::__is_constant_evaluated()) here, as it
+    // doesn't guarantee optimizing the body away at -O0 and
+    // nothing defines nextafterf16.
+    if consteval { return __builtin_nextafterf16(__x, __y); }
+#endif
 #ifdef __INT16_TYPE__
     using __float16_int_type = __INT16_TYPE__;
 #else
@@ -3598,8 +3602,12 @@  _GLIBCXX_BEGIN_NAMESPACE_VERSION
   constexpr __gnu_cxx::__bfloat16_t
   nextafter(__gnu_cxx::__bfloat16_t __x, __gnu_cxx::__bfloat16_t __y)
   {
-    if (std::__is_constant_evaluated())
-      return __builtin_nextafterf16b(__x, __y);
+#if __cpp_if_consteval >= 202106L
+    // Can't use if (std::__is_constant_evaluated()) here, as it
+    // doesn't guarantee optimizing the body away at -O0 and
+    // nothing defines nextafterf16b.
+    if consteval { return __builtin_nextafterf16b(__x, __y); }
+#endif
 #ifdef __INT16_TYPE__
     using __bfloat16_int_type = __INT16_TYPE__;
 #else
--- libstdc++-v3/testsuite/26_numerics/headers/cmath/117321.cc.jj	2024-10-28 12:56:10.699876240 +0100
+++ libstdc++-v3/testsuite/26_numerics/headers/cmath/117321.cc	2024-10-28 12:56:59.875189173 +0100
@@ -0,0 +1,5 @@ 
+// { dg-do run { target c++23 } }
+// { dg-require-cmath "" }
+// { dg-additional-options "-O0" }
+
+#include "nextafter_c++23.cc"