[libc-commits] [clang] [libc] [llvm] [libc][math] change bf16fmal to be header-only and constexpr-compat (PR #181666)
via libc-commits
libc-commits at lists.llvm.org
Mon Feb 16 06:49:34 PST 2026
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 <janmejayapanda400 at gmail.com>
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")
More information about the libc-commits
mailing list