https://github.com/Serosh-commits updated https://github.com/llvm/llvm-project/pull/181666
>From 63f1baa715ede594d6cf1ba45ae5e97a759eb1a0 Mon Sep 17 00:00:00 2001 From: Serosh-commits <[email protected]> Date: Mon, 16 Feb 2026 19:13:42 +0530 Subject: [PATCH] [libc][math] Refactor bf16fmal to be header-only and constexpr-compatible --- clang/test/AST/ByteCode/gh175432.cpp | 6 +++ libc/shared/math/bf16fmal.h | 24 ++++++++++ libc/src/__support/FPUtil/BasicOperations.h | 44 ++++++++++--------- libc/src/__support/FPUtil/FMA.h | 14 ++++-- libc/src/__support/FPUtil/bfloat16.h | 20 ++++----- .../__support/FPUtil/comparison_operations.h | 14 +++--- libc/src/__support/FPUtil/generic/FMA.h | 21 ++++----- libc/src/__support/FPUtil/generic/add_sub.h | 26 +++++------ libc/src/__support/FPUtil/generic/div.h | 8 ++-- libc/src/__support/FPUtil/generic/mul.h | 8 ++-- libc/src/__support/math/CMakeLists.txt | 11 +++++ libc/src/__support/math/bf16fmal.h | 28 ++++++++++++ libc/src/math/bf16fmal.h | 1 + libc/src/math/generic/CMakeLists.txt | 4 +- libc/src/math/generic/bf16fmal.cpp | 8 ++-- libc/test/src/math/smoke/bf16fmal_test.cpp | 3 ++ .../llvm-project-overlay/libc/BUILD.bazel | 19 ++++++++ 17 files changed, 179 insertions(+), 80 deletions(-) create mode 100644 clang/test/AST/ByteCode/gh175432.cpp create mode 100644 libc/shared/math/bf16fmal.h create mode 100644 libc/src/__support/math/bf16fmal.h diff --git a/clang/test/AST/ByteCode/gh175432.cpp b/clang/test/AST/ByteCode/gh175432.cpp new file mode 100644 index 0000000000000..ab4ca8206c17a --- /dev/null +++ b/clang/test/AST/ByteCode/gh175432.cpp @@ -0,0 +1,6 @@ +// RUN: %clang_cc1 -fexperimental-new-constant-interpreter -verify %s + +constexpr const int *foo[][2] = { {nullptr, int}, }; // expected-error {{expected '(' for function-style cast or type construction}} \ + // expected-note {{declared here}} +static_assert(foo[0][0] == nullptr, ""); // expected-error {{constant expression}} \ + // expected-note {{initializer of 'foo' is unknown}} diff --git a/libc/shared/math/bf16fmal.h b/libc/shared/math/bf16fmal.h new file mode 100644 index 0000000000000..db3e246ccf26f --- /dev/null +++ b/libc/shared/math/bf16fmal.h @@ -0,0 +1,24 @@ +//===-- Shared bf16fmal function --------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_LIBC_SHARED_MATH_BF16FMAL_H +#define LLVM_LIBC_SHARED_MATH_BF16FMAL_H + +#include "src/__support/math/bf16fmal.h" + +namespace LIBC_NAMESPACE_DECL { + +namespace shared { + +using math::bf16fmal; + +} // namespace shared + +} // namespace LIBC_NAMESPACE_DECL + +#endif // LLVM_LIBC_SHARED_MATH_BF16FMAL_H diff --git a/libc/src/__support/FPUtil/BasicOperations.h b/libc/src/__support/FPUtil/BasicOperations.h index ca7be6676630a..1ddcbd13f5afc 100644 --- a/libc/src/__support/FPUtil/BasicOperations.h +++ b/libc/src/__support/FPUtil/BasicOperations.h @@ -26,14 +26,15 @@ namespace LIBC_NAMESPACE_DECL { namespace fputil { template <typename T, cpp::enable_if_t<cpp::is_floating_point_v<T>, int> = 0> -LIBC_INLINE T abs(T x) { +LIBC_INLINE constexpr T abs(T x) { return FPBits<T>(x).abs().get_val(); } namespace internal { template <typename T> -LIBC_INLINE cpp::enable_if_t<cpp::is_floating_point_v<T>, T> max(T x, T y) { +LIBC_INLINE constexpr cpp::enable_if_t<cpp::is_floating_point_v<T>, T> +max(T x, T y) { FPBits<T> x_bits(x); FPBits<T> y_bits(y); @@ -47,11 +48,11 @@ LIBC_INLINE cpp::enable_if_t<cpp::is_floating_point_v<T>, T> max(T x, T y) { #ifdef LIBC_TYPES_HAS_FLOAT16 #if defined(__LIBC_USE_BUILTIN_FMAXF16_FMINF16) -template <> LIBC_INLINE float16 max(float16 x, float16 y) { +template <> LIBC_INLINE constexpr float16 max(float16 x, float16 y) { return __builtin_fmaxf16(x, y); } #elif !defined(LIBC_TARGET_ARCH_IS_AARCH64) -template <> LIBC_INLINE float16 max(float16 x, float16 y) { +template <> LIBC_INLINE constexpr float16 max(float16 x, float16 y) { FPBits<float16> x_bits(x); FPBits<float16> y_bits(y); @@ -63,17 +64,18 @@ template <> LIBC_INLINE float16 max(float16 x, float16 y) { #endif // LIBC_TYPES_HAS_FLOAT16 #if defined(__LIBC_USE_BUILTIN_FMAX_FMIN) && !defined(LIBC_TARGET_ARCH_IS_X86) -template <> LIBC_INLINE float max(float x, float y) { +template <> LIBC_INLINE constexpr float max(float x, float y) { return __builtin_fmaxf(x, y); } -template <> LIBC_INLINE double max(double x, double y) { +template <> LIBC_INLINE constexpr double max(double x, double y) { return __builtin_fmax(x, y); } #endif template <typename T> -LIBC_INLINE cpp::enable_if_t<cpp::is_floating_point_v<T>, T> min(T x, T y) { +LIBC_INLINE constexpr cpp::enable_if_t<cpp::is_floating_point_v<T>, T> +min(T x, T y) { FPBits<T> x_bits(x); FPBits<T> y_bits(y); @@ -87,11 +89,11 @@ LIBC_INLINE cpp::enable_if_t<cpp::is_floating_point_v<T>, T> min(T x, T y) { #ifdef LIBC_TYPES_HAS_FLOAT16 #if defined(__LIBC_USE_BUILTIN_FMAXF16_FMINF16) -template <> LIBC_INLINE float16 min(float16 x, float16 y) { +template <> LIBC_INLINE constexpr float16 min(float16 x, float16 y) { return __builtin_fminf16(x, y); } #elif !defined(LIBC_TARGET_ARCH_IS_AARCH64) -template <> LIBC_INLINE float16 min(float16 x, float16 y) { +template <> LIBC_INLINE constexpr float16 min(float16 x, float16 y) { FPBits<float16> x_bits(x); FPBits<float16> y_bits(y); @@ -103,11 +105,11 @@ template <> LIBC_INLINE float16 min(float16 x, float16 y) { #endif // LIBC_TYPES_HAS_FLOAT16 #if defined(__LIBC_USE_BUILTIN_FMAX_FMIN) && !defined(LIBC_TARGET_ARCH_IS_X86) -template <> LIBC_INLINE float min(float x, float y) { +template <> LIBC_INLINE constexpr float min(float x, float y) { return __builtin_fminf(x, y); } -template <> LIBC_INLINE double min(double x, double y) { +template <> LIBC_INLINE constexpr double min(double x, double y) { return __builtin_fmin(x, y); } #endif @@ -115,7 +117,7 @@ template <> LIBC_INLINE double min(double x, double y) { } // namespace internal template <typename T, cpp::enable_if_t<cpp::is_floating_point_v<T>, int> = 0> -LIBC_INLINE T fmin(T x, T y) { +LIBC_INLINE constexpr T fmin(T x, T y) { const FPBits<T> bitx(x), bity(y); if (bitx.is_nan()) @@ -126,7 +128,7 @@ LIBC_INLINE T fmin(T x, T y) { } template <typename T, cpp::enable_if_t<cpp::is_floating_point_v<T>, int> = 0> -LIBC_INLINE T fmax(T x, T y) { +LIBC_INLINE constexpr T fmax(T x, T y) { FPBits<T> bitx(x), bity(y); if (bitx.is_nan()) @@ -137,7 +139,7 @@ LIBC_INLINE T fmax(T x, T y) { } template <typename T, cpp::enable_if_t<cpp::is_floating_point_v<T>, int> = 0> -LIBC_INLINE T fmaximum(T x, T y) { +LIBC_INLINE constexpr T fmaximum(T x, T y) { FPBits<T> bitx(x), bity(y); if (bitx.is_nan()) @@ -148,7 +150,7 @@ LIBC_INLINE T fmaximum(T x, T y) { } template <typename T, cpp::enable_if_t<cpp::is_floating_point_v<T>, int> = 0> -LIBC_INLINE T fminimum(T x, T y) { +LIBC_INLINE constexpr T fminimum(T x, T y) { const FPBits<T> bitx(x), bity(y); if (bitx.is_nan()) @@ -159,7 +161,7 @@ LIBC_INLINE T fminimum(T x, T y) { } template <typename T, cpp::enable_if_t<cpp::is_floating_point_v<T>, int> = 0> -LIBC_INLINE T fmaximum_num(T x, T y) { +LIBC_INLINE constexpr T fmaximum_num(T x, T y) { FPBits<T> bitx(x), bity(y); if (bitx.is_signaling_nan() || bity.is_signaling_nan()) { fputil::raise_except_if_required(FE_INVALID); @@ -174,7 +176,7 @@ LIBC_INLINE T fmaximum_num(T x, T y) { } template <typename T, cpp::enable_if_t<cpp::is_floating_point_v<T>, int> = 0> -LIBC_INLINE T fminimum_num(T x, T y) { +LIBC_INLINE constexpr T fminimum_num(T x, T y) { FPBits<T> bitx(x), bity(y); if (bitx.is_signaling_nan() || bity.is_signaling_nan()) { fputil::raise_except_if_required(FE_INVALID); @@ -189,7 +191,7 @@ LIBC_INLINE T fminimum_num(T x, T y) { } template <typename T, cpp::enable_if_t<cpp::is_floating_point_v<T>, int> = 0> -LIBC_INLINE T fmaximum_mag(T x, T y) { +LIBC_INLINE constexpr T fmaximum_mag(T x, T y) { FPBits<T> bitx(x), bity(y); if (abs(x) > abs(y)) @@ -200,7 +202,7 @@ LIBC_INLINE T fmaximum_mag(T x, T y) { } template <typename T, cpp::enable_if_t<cpp::is_floating_point_v<T>, int> = 0> -LIBC_INLINE T fminimum_mag(T x, T y) { +LIBC_INLINE constexpr T fminimum_mag(T x, T y) { FPBits<T> bitx(x), bity(y); if (abs(x) < abs(y)) @@ -211,7 +213,7 @@ LIBC_INLINE T fminimum_mag(T x, T y) { } template <typename T, cpp::enable_if_t<cpp::is_floating_point_v<T>, int> = 0> -LIBC_INLINE T fmaximum_mag_num(T x, T y) { +LIBC_INLINE constexpr T fmaximum_mag_num(T x, T y) { FPBits<T> bitx(x), bity(y); if (abs(x) > abs(y)) @@ -222,7 +224,7 @@ LIBC_INLINE T fmaximum_mag_num(T x, T y) { } template <typename T, cpp::enable_if_t<cpp::is_floating_point_v<T>, int> = 0> -LIBC_INLINE T fminimum_mag_num(T x, T y) { +LIBC_INLINE constexpr T fminimum_mag_num(T x, T y) { FPBits<T> bitx(x), bity(y); if (abs(x) < abs(y)) diff --git a/libc/src/__support/FPUtil/FMA.h b/libc/src/__support/FPUtil/FMA.h index 2cafb4c0974e3..3e9491b7209db 100644 --- a/libc/src/__support/FPUtil/FMA.h +++ b/libc/src/__support/FPUtil/FMA.h @@ -19,14 +19,20 @@ namespace LIBC_NAMESPACE_DECL { namespace fputil { template <typename OutType, typename InType> -LIBC_INLINE OutType fma(InType x, InType y, InType z) { +LIBC_INLINE constexpr OutType fma(InType x, InType y, InType z) { + static_assert(cpp::is_floating_point_v<InType> && + sizeof(OutType) <= sizeof(InType), + "fma requires InType to be floating point and OutType to be " + "same or smaller size."); return generic::fma<OutType>(x, y, z); } #ifdef LIBC_TARGET_CPU_HAS_FMA #ifdef LIBC_TARGET_CPU_HAS_FMA_FLOAT -template <> LIBC_INLINE float fma(float x, float y, float z) { +template <> LIBC_INLINE constexpr float fma(float x, float y, float z) { + if (cpp::is_constant_evaluated()) + return generic::fma<float>(x, y, z); #if __has_builtin(__builtin_elementwise_fma) return __builtin_elementwise_fma(x, y, z); #else @@ -36,7 +42,9 @@ template <> LIBC_INLINE float fma(float x, float y, float z) { #endif // LIBC_TARGET_CPU_HAS_FMA_FLOAT #ifdef LIBC_TARGET_CPU_HAS_FMA_DOUBLE -template <> LIBC_INLINE double fma(double x, double y, double z) { +template <> LIBC_INLINE constexpr double fma(double x, double y, double z) { + if (cpp::is_constant_evaluated()) + return generic::fma<double>(x, y, z); #if __has_builtin(__builtin_elementwise_fma) return __builtin_elementwise_fma(x, y, z); #else diff --git a/libc/src/__support/FPUtil/bfloat16.h b/libc/src/__support/FPUtil/bfloat16.h index 13e151208567d..bd38e81e3a85a 100644 --- a/libc/src/__support/FPUtil/bfloat16.h +++ b/libc/src/__support/FPUtil/bfloat16.h @@ -68,27 +68,27 @@ struct BFloat16 { return static_cast<T>(static_cast<float>(*this)); } - LIBC_INLINE bool operator==(BFloat16 other) const { + LIBC_INLINE constexpr bool operator==(BFloat16 other) const { return fputil::equals(*this, other); } - LIBC_INLINE bool operator!=(BFloat16 other) const { + LIBC_INLINE constexpr bool operator!=(BFloat16 other) const { return !fputil::equals(*this, other); } - LIBC_INLINE bool operator<(BFloat16 other) const { + LIBC_INLINE constexpr bool operator<(BFloat16 other) const { return fputil::less_than(*this, other); } - LIBC_INLINE bool operator<=(BFloat16 other) const { + LIBC_INLINE constexpr bool operator<=(BFloat16 other) const { return fputil::less_than_or_equals(*this, other); } - LIBC_INLINE bool operator>(BFloat16 other) const { + LIBC_INLINE constexpr bool operator>(BFloat16 other) const { return fputil::greater_than(*this, other); } - LIBC_INLINE bool operator>=(BFloat16 other) const { + LIBC_INLINE constexpr bool operator>=(BFloat16 other) const { return fputil::greater_than_or_equals(*this, other); } @@ -98,19 +98,19 @@ struct BFloat16 { return result.get_val(); } - LIBC_INLINE BFloat16 operator+(BFloat16 other) const { + LIBC_INLINE constexpr BFloat16 operator+(BFloat16 other) const { return fputil::generic::add<BFloat16>(*this, other); } - LIBC_INLINE BFloat16 operator-(BFloat16 other) const { + LIBC_INLINE constexpr BFloat16 operator-(BFloat16 other) const { return fputil::generic::sub<BFloat16>(*this, other); } - LIBC_INLINE BFloat16 operator*(BFloat16 other) const { + LIBC_INLINE constexpr BFloat16 operator*(BFloat16 other) const { return fputil::generic::mul<bfloat16>(*this, other); } - LIBC_INLINE BFloat16 operator/(BFloat16 other) const { + LIBC_INLINE constexpr BFloat16 operator/(BFloat16 other) const { return fputil::generic::div<bfloat16>(*this, other); } }; // struct BFloat16 diff --git a/libc/src/__support/FPUtil/comparison_operations.h b/libc/src/__support/FPUtil/comparison_operations.h index ff62ce085513b..01092b4ae6efe 100644 --- a/libc/src/__support/FPUtil/comparison_operations.h +++ b/libc/src/__support/FPUtil/comparison_operations.h @@ -26,8 +26,8 @@ namespace fputil { // (iii) -inf != +inf // 3. Any comparison with NaN returns false template <typename T> -LIBC_INLINE cpp::enable_if_t<cpp::is_floating_point_v<T>, bool> equals(T x, - T y) { +LIBC_INLINE constexpr cpp::enable_if_t<cpp::is_floating_point_v<T>, bool> +equals(T x, T y) { using FPBits = FPBits<T>; FPBits x_bits(x); FPBits y_bits(y); @@ -52,8 +52,8 @@ LIBC_INLINE cpp::enable_if_t<cpp::is_floating_point_v<T>, bool> equals(T x, // 2. x < +inf (x != +inf) // 3. Any comparison with NaN return false template <typename T> -LIBC_INLINE cpp::enable_if_t<cpp::is_floating_point_v<T>, bool> less_than(T x, - T y) { +LIBC_INLINE constexpr cpp::enable_if_t<cpp::is_floating_point_v<T>, bool> +less_than(T x, T y) { using FPBits = FPBits<T>; FPBits x_bits(x); FPBits y_bits(y); @@ -87,7 +87,7 @@ LIBC_INLINE cpp::enable_if_t<cpp::is_floating_point_v<T>, bool> less_than(T x, // Implements compareSignalingGreater predicate // x < y => y > x template <typename T> -LIBC_INLINE cpp::enable_if_t<cpp::is_floating_point_v<T>, bool> +LIBC_INLINE constexpr cpp::enable_if_t<cpp::is_floating_point_v<T>, bool> greater_than(T x, T y) { return less_than(y, x); } @@ -95,7 +95,7 @@ greater_than(T x, T y) { // Implements compareSignalingLessEqual predicate // x <= y => (x < y) || (x == y) template <typename T> -LIBC_INLINE cpp::enable_if_t<cpp::is_floating_point_v<T>, bool> +LIBC_INLINE constexpr cpp::enable_if_t<cpp::is_floating_point_v<T>, bool> less_than_or_equals(T x, T y) { return less_than(x, y) || equals(x, y); } @@ -103,7 +103,7 @@ less_than_or_equals(T x, T y) { // Implements compareSignalingGreaterEqual predicate // x >= y => (x > y) || (x == y) => (y < x) || (x == y) template <typename T> -LIBC_INLINE cpp::enable_if_t<cpp::is_floating_point_v<T>, bool> +LIBC_INLINE constexpr cpp::enable_if_t<cpp::is_floating_point_v<T>, bool> greater_than_or_equals(T x, T y) { return less_than(y, x) || equals(x, y); } diff --git a/libc/src/__support/FPUtil/generic/FMA.h b/libc/src/__support/FPUtil/generic/FMA.h index bec312e44b1b1..d55f8797106c8 100644 --- a/libc/src/__support/FPUtil/generic/FMA.h +++ b/libc/src/__support/FPUtil/generic/FMA.h @@ -29,16 +29,16 @@ namespace fputil { namespace generic { template <typename OutType, typename InType> -LIBC_INLINE cpp::enable_if_t<cpp::is_floating_point_v<OutType> && - cpp::is_floating_point_v<InType> && - sizeof(OutType) <= sizeof(InType), - OutType> +LIBC_INLINE constexpr cpp::enable_if_t<cpp::is_floating_point_v<OutType> && + cpp::is_floating_point_v<InType> && + sizeof(OutType) <= sizeof(InType), + OutType> fma(InType x, InType y, InType z); // TODO(lntue): Implement fmaf that is correctly rounded to all rounding modes. // The implementation below only is only correct for the default rounding mode, // round-to-nearest tie-to-even. -template <> LIBC_INLINE float fma<float>(float x, float y, float z) { +template <> LIBC_INLINE constexpr float fma<float>(float x, float y, float z) { // Product is exact. double prod = static_cast<double>(x) * static_cast<double>(y); double z_d = static_cast<double>(z); @@ -90,7 +90,8 @@ namespace internal { // Extract the sticky bits and shift the `mantissa` to the right by // `shift_length`. template <typename T> -LIBC_INLINE cpp::enable_if_t<is_unsigned_integral_or_big_int_v<T>, bool> +LIBC_INLINE constexpr cpp::enable_if_t<is_unsigned_integral_or_big_int_v<T>, + bool> shift_mantissa(int shift_length, T &mant) { if (shift_length >= cpp::numeric_limits<T>::digits) { mant = 0; @@ -105,10 +106,10 @@ shift_mantissa(int shift_length, T &mant) { } // namespace internal template <typename OutType, typename InType> -LIBC_INLINE cpp::enable_if_t<cpp::is_floating_point_v<OutType> && - cpp::is_floating_point_v<InType> && - sizeof(OutType) <= sizeof(InType), - OutType> +LIBC_INLINE constexpr cpp::enable_if_t<cpp::is_floating_point_v<OutType> && + cpp::is_floating_point_v<InType> && + sizeof(OutType) <= sizeof(InType), + OutType> fma(InType x, InType y, InType z) { using OutFPBits = FPBits<OutType>; using OutStorageType = typename OutFPBits::StorageType; diff --git a/libc/src/__support/FPUtil/generic/add_sub.h b/libc/src/__support/FPUtil/generic/add_sub.h index 9f3ecff0eb233..69ce52aec6d1a 100644 --- a/libc/src/__support/FPUtil/generic/add_sub.h +++ b/libc/src/__support/FPUtil/generic/add_sub.h @@ -27,10 +27,10 @@ namespace LIBC_NAMESPACE_DECL { namespace fputil::generic { template <bool IsSub, typename OutType, typename InType> -LIBC_INLINE cpp::enable_if_t<cpp::is_floating_point_v<OutType> && - cpp::is_floating_point_v<InType> && - sizeof(OutType) <= sizeof(InType), - OutType> +LIBC_INLINE constexpr cpp::enable_if_t<cpp::is_floating_point_v<OutType> && + cpp::is_floating_point_v<InType> && + sizeof(OutType) <= sizeof(InType), + OutType> add_or_sub(InType x, InType y) { using OutFPBits = FPBits<OutType>; using OutStorageType = typename OutFPBits::StorageType; @@ -175,7 +175,7 @@ add_or_sub(InType x, InType y) { InStorageType aligned_min_mant = static_cast<InStorageType>( min_mant >> cpp::min(alignment, RESULT_MANTISSA_LEN)); - bool aligned_min_mant_sticky; + bool aligned_min_mant_sticky = false; if (alignment <= GUARD_BITS_LEN) aligned_min_mant_sticky = false; @@ -201,19 +201,19 @@ add_or_sub(InType x, InType y) { } template <typename OutType, typename InType> -LIBC_INLINE cpp::enable_if_t<cpp::is_floating_point_v<OutType> && - cpp::is_floating_point_v<InType> && - sizeof(OutType) <= sizeof(InType), - OutType> +LIBC_INLINE constexpr cpp::enable_if_t<cpp::is_floating_point_v<OutType> && + cpp::is_floating_point_v<InType> && + sizeof(OutType) <= sizeof(InType), + OutType> add(InType x, InType y) { return add_or_sub</*IsSub=*/false, OutType>(x, y); } template <typename OutType, typename InType> -LIBC_INLINE cpp::enable_if_t<cpp::is_floating_point_v<OutType> && - cpp::is_floating_point_v<InType> && - sizeof(OutType) <= sizeof(InType), - OutType> +LIBC_INLINE constexpr cpp::enable_if_t<cpp::is_floating_point_v<OutType> && + cpp::is_floating_point_v<InType> && + sizeof(OutType) <= sizeof(InType), + OutType> sub(InType x, InType y) { return add_or_sub</*IsSub=*/true, OutType>(x, y); } diff --git a/libc/src/__support/FPUtil/generic/div.h b/libc/src/__support/FPUtil/generic/div.h index bf7d0b7112ca9..85026bb3fd40f 100644 --- a/libc/src/__support/FPUtil/generic/div.h +++ b/libc/src/__support/FPUtil/generic/div.h @@ -26,10 +26,10 @@ namespace LIBC_NAMESPACE_DECL { namespace fputil::generic { template <typename OutType, typename InType> -LIBC_INLINE cpp::enable_if_t<cpp::is_floating_point_v<OutType> && - cpp::is_floating_point_v<InType> && - sizeof(OutType) <= sizeof(InType), - OutType> +LIBC_INLINE constexpr cpp::enable_if_t<cpp::is_floating_point_v<OutType> && + cpp::is_floating_point_v<InType> && + sizeof(OutType) <= sizeof(InType), + OutType> div(InType x, InType y) { using OutFPBits = FPBits<OutType>; using OutStorageType = typename OutFPBits::StorageType; diff --git a/libc/src/__support/FPUtil/generic/mul.h b/libc/src/__support/FPUtil/generic/mul.h index 20d9a77792762..22c6859946180 100644 --- a/libc/src/__support/FPUtil/generic/mul.h +++ b/libc/src/__support/FPUtil/generic/mul.h @@ -25,10 +25,10 @@ namespace LIBC_NAMESPACE_DECL { namespace fputil::generic { template <typename OutType, typename InType> -LIBC_INLINE cpp::enable_if_t<cpp::is_floating_point_v<OutType> && - cpp::is_floating_point_v<InType> && - sizeof(OutType) <= sizeof(InType), - OutType> +LIBC_INLINE constexpr cpp::enable_if_t<cpp::is_floating_point_v<OutType> && + cpp::is_floating_point_v<InType> && + sizeof(OutType) <= sizeof(InType), + OutType> mul(InType x, InType y) { using OutFPBits = FPBits<OutType>; using OutStorageType = typename OutFPBits::StorageType; diff --git a/libc/src/__support/math/CMakeLists.txt b/libc/src/__support/math/CMakeLists.txt index aaab78c01a891..fc8f10badb31c 100644 --- a/libc/src/__support/math/CMakeLists.txt +++ b/libc/src/__support/math/CMakeLists.txt @@ -814,6 +814,17 @@ add_header_library( libc.include.llvm-libc-macros.float16_macros ) +add_header_library( + bf16fmal + HDRS + bf16fmal.h + DEPENDS + libc.src.__support.macros.config + libc.src.__support.FPUtil.fma + libc.src.__support.FPUtil.bfloat16 + libc.src.__support.macros.properties.types +) + add_header_library( ilogb HDRS diff --git a/libc/src/__support/math/bf16fmal.h b/libc/src/__support/math/bf16fmal.h new file mode 100644 index 0000000000000..706183db8239e --- /dev/null +++ b/libc/src/__support/math/bf16fmal.h @@ -0,0 +1,28 @@ +//===-- Implementation header for bf16fmal ----------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_LIBC_SRC___SUPPORT_MATH_BF16FMAL_H +#define LLVM_LIBC_SRC___SUPPORT_MATH_BF16FMAL_H + +#include "src/__support/FPUtil/FMA.h" +#include "src/__support/FPUtil/bfloat16.h" +#include "src/__support/macros/config.h" +#include "src/__support/macros/properties/types.h" + +namespace LIBC_NAMESPACE_DECL { +namespace math { + +LIBC_INLINE constexpr bfloat16 bf16fmal(long double x, long double y, + long double z) { + return fputil::fma<bfloat16>(x, y, z); +} + +} // namespace math +} // namespace LIBC_NAMESPACE_DECL + +#endif // LLVM_LIBC_SRC___SUPPORT_MATH_BF16FMAL_H diff --git a/libc/src/math/bf16fmal.h b/libc/src/math/bf16fmal.h index b92f17b7ee8d6..69338c5d2ada6 100644 --- a/libc/src/math/bf16fmal.h +++ b/libc/src/math/bf16fmal.h @@ -11,6 +11,7 @@ #include "src/__support/macros/config.h" #include "src/__support/macros/properties/types.h" +#include "src/__support/math/bf16fmal.h" namespace LIBC_NAMESPACE_DECL { diff --git a/libc/src/math/generic/CMakeLists.txt b/libc/src/math/generic/CMakeLists.txt index 75b51b4587bea..6c67fc67b1b0c 100644 --- a/libc/src/math/generic/CMakeLists.txt +++ b/libc/src/math/generic/CMakeLists.txt @@ -5263,10 +5263,8 @@ add_entrypoint_object( ../bf16fmal.h DEPENDS libc.src.__support.common - libc.src.__support.FPUtil.bfloat16 - libc.src.__support.FPUtil.fma libc.src.__support.macros.config - libc.src.__support.macros.properties.types + libc.src.__support.math.bf16fmal ) add_entrypoint_object( diff --git a/libc/src/math/generic/bf16fmal.cpp b/libc/src/math/generic/bf16fmal.cpp index f31ec6904760b..408b5b8765498 100644 --- a/libc/src/math/generic/bf16fmal.cpp +++ b/libc/src/math/generic/bf16fmal.cpp @@ -7,16 +7,14 @@ //===----------------------------------------------------------------------===// #include "src/math/bf16fmal.h" - -#include "src/__support/FPUtil/FMA.h" -#include "src/__support/FPUtil/bfloat16.h" #include "src/__support/common.h" -#include "src/__support/macros/config.h" +#include "src/__support/math/bf16fmal.h" namespace LIBC_NAMESPACE_DECL { LLVM_LIBC_FUNCTION(bfloat16, bf16fmal, (long double x, long double y, long double z)) { - return fputil::fma<bfloat16>(x, y, z); + return math::bf16fmal(x, y, z); } + } // namespace LIBC_NAMESPACE_DECL diff --git a/libc/test/src/math/smoke/bf16fmal_test.cpp b/libc/test/src/math/smoke/bf16fmal_test.cpp index 4c45e2c64312d..44bc2417843c4 100644 --- a/libc/test/src/math/smoke/bf16fmal_test.cpp +++ b/libc/test/src/math/smoke/bf16fmal_test.cpp @@ -12,3 +12,6 @@ #include "src/math/bf16fmal.h" LIST_NARROWING_FMA_TESTS(bfloat16, long double, LIBC_NAMESPACE::bf16fmal) + +static_assert(LIBC_NAMESPACE::math::bf16fmal(1.0l, 2.0l, 3.0l) == + bfloat16(5.0f)); diff --git a/utils/bazel/llvm-project-overlay/libc/BUILD.bazel b/utils/bazel/llvm-project-overlay/libc/BUILD.bazel index 608180b90e87b..01f8c1a6344de 100644 --- a/utils/bazel/llvm-project-overlay/libc/BUILD.bazel +++ b/utils/bazel/llvm-project-overlay/libc/BUILD.bazel @@ -3006,6 +3006,18 @@ libc_support_library( ], ) +libc_support_library( + name = "__support_math_bf16fmal", + hdrs = ["src/__support/math/bf16fmal.h"], + deps = [ + ":__support_common", + ":__support_fputil_fma", + ":__support_fputil_bfloat16", + ":__support_macros_config", + ":__support_macros_properties_types", + ], +) + libc_support_library( name = "__support_math_ffma", hdrs = ["src/__support/math/ffma.h"], @@ -4716,6 +4728,13 @@ libc_math_function( additional_deps = [":__support_math_f16fmal"], ) +libc_math_function( + name = "bf16fmal", + additional_deps = [ + ":__support_math_bf16fmal", + ], +) + libc_math_function(name = "f16mul") libc_math_function(name = "f16mulf") _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
