[libc-commits] [libc] [llvm] [libc][math] Add tanhbf16 function (PR #227109)

via libc-commits libc-commits at lists.llvm.org
Sun Oct 4 07:01:03 PDT 2026


https://github.com/mooofin updated https://github.com/llvm/llvm-project/pull/227109

>From 7aa00327a59cb237358eb731aff1d85fd642498f Mon Sep 17 00:00:00 2001
From: sid <siddharthqln at gmail.com>
Date: Tue, 29 Sep 2026 01:50:57 +0530
Subject: [PATCH 1/2] [libc][math] Add tanhbf16 function

---
 libc/config/baremetal/aarch64/entrypoints.txt |  1 +
 libc/config/baremetal/arm/entrypoints.txt     |  1 +
 libc/config/baremetal/riscv/entrypoints.txt   |  1 +
 libc/config/darwin/aarch64/entrypoints.txt    |  1 +
 libc/config/darwin/x86_64/entrypoints.txt     |  1 +
 libc/config/freebsd/x86_64/entrypoints.txt    |  1 +
 libc/config/gpu/amdgpu/entrypoints.txt        |  1 +
 libc/config/gpu/nvptx/entrypoints.txt         |  1 +
 libc/config/linux/aarch64/entrypoints.txt     |  1 +
 libc/config/linux/arm/entrypoints.txt         |  1 +
 libc/config/linux/riscv/entrypoints.txt       |  1 +
 libc/config/linux/x86_64/entrypoints.txt      |  1 +
 libc/config/windows/entrypoints.txt           |  1 +
 libc/docs/headers/math/index.rst              |  2 +-
 libc/shared/math.h                            |  1 +
 libc/shared/math/tanhbf16.h                   | 23 +++++
 libc/src/__support/math/CMakeLists.txt        | 16 ++++
 libc/src/__support/math/tanhbf16.h            | 85 +++++++++++++++++++
 libc/src/math/CMakeLists.txt                  |  1 +
 libc/src/math/generic/CMakeLists.txt          | 10 +++
 libc/src/math/generic/tanhbf16.cpp            | 19 +++++
 libc/src/math/tanhbf16.h                      | 21 +++++
 libc/test/shared/CMakeLists.txt               |  1 +
 libc/test/shared/shared_math_test.cpp         |  1 +
 libc/test/src/math/CMakeLists.txt             | 13 +++
 libc/test/src/math/smoke/CMakeLists.txt       | 13 +++
 libc/test/src/math/smoke/tanhbf16_test.cpp    | 69 +++++++++++++++
 libc/test/src/math/tanhbf16_test.cpp          | 33 +++++++
 .../llvm-project-overlay/libc/BUILD.bazel     | 23 +++++
 29 files changed, 343 insertions(+), 1 deletion(-)
 create mode 100644 libc/shared/math/tanhbf16.h
 create mode 100644 libc/src/__support/math/tanhbf16.h
 create mode 100644 libc/src/math/generic/tanhbf16.cpp
 create mode 100644 libc/src/math/tanhbf16.h
 create mode 100644 libc/test/src/math/smoke/tanhbf16_test.cpp
 create mode 100644 libc/test/src/math/tanhbf16_test.cpp

diff --git a/libc/config/baremetal/aarch64/entrypoints.txt b/libc/config/baremetal/aarch64/entrypoints.txt
index 114534ce61ae6..ef8e23dd1f9e8 100644
--- a/libc/config/baremetal/aarch64/entrypoints.txt
+++ b/libc/config/baremetal/aarch64/entrypoints.txt
@@ -877,6 +877,7 @@ list(APPEND TARGET_LIBM_ENTRYPOINTS
   libc.src.math.setpayloadsigbf16
   libc.src.math.sqrtbf16
   libc.src.math.tanbf16
+  libc.src.math.tanhbf16
   libc.src.math.truncbf16
   libc.src.math.totalorderbf16
   libc.src.math.totalordermagbf16
diff --git a/libc/config/baremetal/arm/entrypoints.txt b/libc/config/baremetal/arm/entrypoints.txt
index c8148815c34e3..b28c8f13b12b6 100644
--- a/libc/config/baremetal/arm/entrypoints.txt
+++ b/libc/config/baremetal/arm/entrypoints.txt
@@ -888,6 +888,7 @@ list(APPEND TARGET_LIBM_ENTRYPOINTS
   libc.src.math.setpayloadsigbf16
   libc.src.math.sqrtbf16
   libc.src.math.tanbf16
+  libc.src.math.tanhbf16
   libc.src.math.truncbf16
   libc.src.math.totalorderbf16
   libc.src.math.totalordermagbf16
diff --git a/libc/config/baremetal/riscv/entrypoints.txt b/libc/config/baremetal/riscv/entrypoints.txt
index 622d6156cff11..c8f092280afa5 100644
--- a/libc/config/baremetal/riscv/entrypoints.txt
+++ b/libc/config/baremetal/riscv/entrypoints.txt
@@ -880,6 +880,7 @@ list(APPEND TARGET_LIBM_ENTRYPOINTS
   libc.src.math.setpayloadsigbf16
   libc.src.math.sqrtbf16
   libc.src.math.tanbf16
+  libc.src.math.tanhbf16
   libc.src.math.truncbf16
   libc.src.math.totalorderbf16
   libc.src.math.totalordermagbf16
diff --git a/libc/config/darwin/aarch64/entrypoints.txt b/libc/config/darwin/aarch64/entrypoints.txt
index d702b2c5a6549..82b3cb732ad9c 100644
--- a/libc/config/darwin/aarch64/entrypoints.txt
+++ b/libc/config/darwin/aarch64/entrypoints.txt
@@ -699,6 +699,7 @@ list(APPEND TARGET_LIBM_ENTRYPOINTS
   libc.src.math.setpayloadsigbf16
   libc.src.math.sqrtbf16
   libc.src.math.tanbf16
+  libc.src.math.tanhbf16
   libc.src.math.truncbf16
   libc.src.math.totalorderbf16
   libc.src.math.totalordermagbf16
diff --git a/libc/config/darwin/x86_64/entrypoints.txt b/libc/config/darwin/x86_64/entrypoints.txt
index 716ab572f8d3c..b23cb588cbf61 100644
--- a/libc/config/darwin/x86_64/entrypoints.txt
+++ b/libc/config/darwin/x86_64/entrypoints.txt
@@ -335,6 +335,7 @@ list(APPEND TARGET_LIBM_ENTRYPOINTS
   libc.src.math.setpayloadsigbf16
   libc.src.math.sqrtbf16
   libc.src.math.tanbf16
+  libc.src.math.tanhbf16
   libc.src.math.truncbf16
   libc.src.math.totalorderbf16
   libc.src.math.totalordermagbf16
diff --git a/libc/config/freebsd/x86_64/entrypoints.txt b/libc/config/freebsd/x86_64/entrypoints.txt
index 8f6c178301c2f..05467df51f21a 100644
--- a/libc/config/freebsd/x86_64/entrypoints.txt
+++ b/libc/config/freebsd/x86_64/entrypoints.txt
@@ -632,6 +632,7 @@ list(APPEND TARGET_LIBM_ENTRYPOINTS
   libc.src.math.setpayloadsigbf16
   libc.src.math.sqrtbf16
   libc.src.math.tanbf16
+  libc.src.math.tanhbf16
   libc.src.math.truncbf16
   libc.src.math.totalorderbf16
   libc.src.math.totalordermagbf16
diff --git a/libc/config/gpu/amdgpu/entrypoints.txt b/libc/config/gpu/amdgpu/entrypoints.txt
index 5c5e5891da822..93ee4fd6e4890 100644
--- a/libc/config/gpu/amdgpu/entrypoints.txt
+++ b/libc/config/gpu/amdgpu/entrypoints.txt
@@ -748,6 +748,7 @@ list(APPEND TARGET_LIBM_ENTRYPOINTS
   libc.src.math.setpayloadsigbf16
   libc.src.math.sqrtbf16
   libc.src.math.tanbf16
+  libc.src.math.tanhbf16
   libc.src.math.truncbf16
   libc.src.math.totalorderbf16
   libc.src.math.totalordermagbf16
diff --git a/libc/config/gpu/nvptx/entrypoints.txt b/libc/config/gpu/nvptx/entrypoints.txt
index afae725484a89..b6418e7680423 100644
--- a/libc/config/gpu/nvptx/entrypoints.txt
+++ b/libc/config/gpu/nvptx/entrypoints.txt
@@ -764,6 +764,7 @@ list(APPEND TARGET_LIBM_ENTRYPOINTS
   libc.src.math.setpayloadsigbf16
   libc.src.math.sqrtbf16
   libc.src.math.tanbf16
+  libc.src.math.tanhbf16
   libc.src.math.truncbf16
   libc.src.math.totalorderbf16
   libc.src.math.totalordermagbf16
diff --git a/libc/config/linux/aarch64/entrypoints.txt b/libc/config/linux/aarch64/entrypoints.txt
index e2402b1264931..c0f2bbeae5f87 100644
--- a/libc/config/linux/aarch64/entrypoints.txt
+++ b/libc/config/linux/aarch64/entrypoints.txt
@@ -1091,6 +1091,7 @@ list(APPEND TARGET_LIBM_ENTRYPOINTS
   libc.src.math.setpayloadsigbf16
   libc.src.math.sqrtbf16
   libc.src.math.tanbf16
+  libc.src.math.tanhbf16
   libc.src.math.truncbf16
   libc.src.math.totalorderbf16
   libc.src.math.totalordermagbf16
diff --git a/libc/config/linux/arm/entrypoints.txt b/libc/config/linux/arm/entrypoints.txt
index f2a7f8e182658..66556bf8107a8 100644
--- a/libc/config/linux/arm/entrypoints.txt
+++ b/libc/config/linux/arm/entrypoints.txt
@@ -697,6 +697,7 @@ list(APPEND TARGET_LIBM_ENTRYPOINTS
   libc.src.math.setpayloadsigbf16
   libc.src.math.sqrtbf16
   libc.src.math.tanbf16
+  libc.src.math.tanhbf16
   libc.src.math.truncbf16
   libc.src.math.totalorderbf16
   libc.src.math.totalordermagbf16
diff --git a/libc/config/linux/riscv/entrypoints.txt b/libc/config/linux/riscv/entrypoints.txt
index b90ab97416a41..a38f3413d3f67 100644
--- a/libc/config/linux/riscv/entrypoints.txt
+++ b/libc/config/linux/riscv/entrypoints.txt
@@ -1164,6 +1164,7 @@ list(APPEND TARGET_LIBM_ENTRYPOINTS
   libc.src.math.setpayloadsigbf16
   libc.src.math.sqrtbf16
   libc.src.math.tanbf16
+  libc.src.math.tanhbf16
   libc.src.math.truncbf16
   libc.src.math.totalorderbf16
   libc.src.math.totalordermagbf16
diff --git a/libc/config/linux/x86_64/entrypoints.txt b/libc/config/linux/x86_64/entrypoints.txt
index 211476af8f712..a929931d799ab 100644
--- a/libc/config/linux/x86_64/entrypoints.txt
+++ b/libc/config/linux/x86_64/entrypoints.txt
@@ -1186,6 +1186,7 @@ list(APPEND TARGET_LIBM_ENTRYPOINTS
   libc.src.math.setpayloadsigbf16
   libc.src.math.sqrtbf16
   libc.src.math.tanbf16
+  libc.src.math.tanhbf16
   libc.src.math.truncbf16
   libc.src.math.totalorderbf16
   libc.src.math.totalordermagbf16
diff --git a/libc/config/windows/entrypoints.txt b/libc/config/windows/entrypoints.txt
index 3a48b49e169b3..8eea736e69339 100644
--- a/libc/config/windows/entrypoints.txt
+++ b/libc/config/windows/entrypoints.txt
@@ -425,6 +425,7 @@ list(APPEND TARGET_LIBM_ENTRYPOINTS
   libc.src.math.setpayloadsigbf16
   libc.src.math.sqrtbf16
   libc.src.math.tanbf16
+  libc.src.math.tanhbf16
   libc.src.math.truncbf16
   libc.src.math.totalorderbf16
   libc.src.math.totalordermagbf16
diff --git a/libc/docs/headers/math/index.rst b/libc/docs/headers/math/index.rst
index 67fc2e259eff9..ff3bbedeb3511 100644
--- a/libc/docs/headers/math/index.rst
+++ b/libc/docs/headers/math/index.rst
@@ -355,7 +355,7 @@ Higher Math Functions
 +-----------+------------------+-----------------+------------------------+----------------------+------------------------+------------------------+------------------------+----------------------------+
 | tan       | |check|          | |check|         |                        | |check|              |                        | |check|                | 7.12.4.7               | F.10.1.7                   |
 +-----------+------------------+-----------------+------------------------+----------------------+------------------------+------------------------+------------------------+----------------------------+
-| tanh      | |check|          |                 |                        | |check|              |                        |                        | 7.12.5.6               | F.10.2.6                   |
+| tanh      | |check|          |                 |                        | |check|              |                        | |check|                | 7.12.5.6               | F.10.2.6                   |
 +-----------+------------------+-----------------+------------------------+----------------------+------------------------+------------------------+------------------------+----------------------------+
 | tanpi     | |check|          |                 |                        | |check|              |                        |                        | 7.12.4.14              | F.10.1.14                  |
 +-----------+------------------+-----------------+------------------------+----------------------+------------------------+------------------------+------------------------+----------------------------+
diff --git a/libc/shared/math.h b/libc/shared/math.h
index 7b52cedf99c24..5df98e929588e 100644
--- a/libc/shared/math.h
+++ b/libc/shared/math.h
@@ -480,6 +480,7 @@
 #include "math/tanbf16.h"
 #include "math/tanf.h"
 #include "math/tanf16.h"
+#include "math/tanhbf16.h"
 #include "math/tanhf.h"
 #include "math/tanhf16.h"
 #include "math/tanpif.h"
diff --git a/libc/shared/math/tanhbf16.h b/libc/shared/math/tanhbf16.h
new file mode 100644
index 0000000000000..e1b115dda0f30
--- /dev/null
+++ b/libc/shared/math/tanhbf16.h
@@ -0,0 +1,23 @@
+//===-- Shared tanhbf16 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_TANHBF16_H
+#define LLVM_LIBC_SHARED_MATH_TANHBF16_H
+
+#include "shared/libc_common.h"
+#include "src/__support/math/tanhbf16.h"
+
+namespace LIBC_NAMESPACE_DECL {
+namespace shared {
+
+using math::tanhbf16;
+
+} // namespace shared
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LLVM_LIBC_SHARED_MATH_TANHBF16_H
diff --git a/libc/src/__support/math/CMakeLists.txt b/libc/src/__support/math/CMakeLists.txt
index 8d6a1495e1c11..0460c0037d2a4 100644
--- a/libc/src/__support/math/CMakeLists.txt
+++ b/libc/src/__support/math/CMakeLists.txt
@@ -5653,6 +5653,22 @@ add_header_library(
     libc.include.llvm-libc-macros.float16_macros
 )
 
+add_header_library(
+  tanhbf16
+  HDRS
+    tanhbf16.h
+  DEPENDS
+    .tanhf
+    libc.hdr.fenv_macros
+    libc.src.__support.FPUtil.bfloat16
+    libc.src.__support.FPUtil.cast
+    libc.src.__support.FPUtil.fenv_impl
+    libc.src.__support.FPUtil.fp_bits
+    libc.src.__support.FPUtil.rounding_mode
+    libc.src.__support.macros.config
+    libc.src.__support.macros.optimization
+)
+
 add_header_library(
   tanhf
   HDRS
diff --git a/libc/src/__support/math/tanhbf16.h b/libc/src/__support/math/tanhbf16.h
new file mode 100644
index 0000000000000..6713a1d452a3a
--- /dev/null
+++ b/libc/src/__support/math/tanhbf16.h
@@ -0,0 +1,85 @@
+//===-- Implementation of tanhbf16 function -------------------------------===//
+//
+// 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_TANHBF16_H
+#define LLVM_LIBC_SRC___SUPPORT_MATH_TANHBF16_H
+
+#include "hdr/fenv_macros.h"
+#include "src/__support/FPUtil/FEnvImpl.h"
+#include "src/__support/FPUtil/FPBits.h"
+#include "src/__support/FPUtil/bfloat16.h"
+#include "src/__support/FPUtil/cast.h"
+#include "src/__support/FPUtil/rounding_mode.h"
+#include "src/__support/macros/config.h"
+#include "src/__support/macros/optimization.h"
+#include "tanhf.h"
+
+namespace LIBC_NAMESPACE_DECL {
+namespace math {
+
+LIBC_INLINE bfloat16 tanhbf16(bfloat16 x) {
+  using FPBits = fputil::FPBits<bfloat16>;
+  FPBits x_bits(x);
+  uint16_t x_u = x_bits.uintval();
+  uint16_t x_abs = x_u & 0x7fffU;
+
+  if (LIBC_UNLIKELY(x_bits.is_nan())) {
+    if (x_bits.is_signaling_nan()) {
+      fputil::raise_except_if_required(FE_INVALID);
+      return FPBits::quiet_nan().get_val();
+    }
+    return x;
+  }
+
+  // tanh(+/-inf) = +/-1, and tanh(+/-0) = +/-0.
+  if (LIBC_UNLIKELY(x_bits.is_inf()))
+    return FPBits::one(x_bits.sign()).get_val();
+  if (LIBC_UNLIKELY(x_abs == 0))
+    return x;
+
+  // For |x| <= 0x1.7p-4, tanh(x) rounds to x in round-to-nearest.  For
+  // directed rounding, its magnitude is strictly smaller than |x|.
+  if (LIBC_UNLIKELY(x_abs <= 0x3db8U)) {
+    bool toward_zero = false;
+#ifndef LIBC_MATH_HAS_ASSUME_ROUND_NEAREST_ONLY
+    int rounding_mode = fputil::quick_get_round();
+    toward_zero = rounding_mode == FE_TOWARDZERO ||
+                  (rounding_mode == FE_DOWNWARD && x_bits.is_pos()) ||
+                  (rounding_mode == FE_UPWARD && x_bits.is_neg());
+#endif
+    uint16_t result = toward_zero ? static_cast<uint16_t>(x_u - 1U) : x_u;
+    int exceptions = FE_INEXACT;
+    if ((result & 0x7fffU) < 0x0080U)
+      exceptions |= FE_UNDERFLOW;
+    fputil::raise_except_if_required(exceptions);
+    return FPBits(result).get_val();
+  }
+
+  // 0x1.bcp+1 is the first bfloat16 input whose tanh rounds to 1 in
+  // round-to-nearest.  The result remains below 1 for every finite input.
+  if (LIBC_UNLIKELY(x_abs >= 0x405eU)) {
+    fputil::raise_except_if_required(FE_INEXACT);
+    bool round_to_one = true;
+#ifndef LIBC_MATH_HAS_ASSUME_ROUND_NEAREST_ONLY
+    int rounding_mode = fputil::quick_get_round();
+    round_to_one = rounding_mode == FE_TONEAREST ||
+                   (rounding_mode == FE_UPWARD && x_bits.is_pos()) ||
+                   (rounding_mode == FE_DOWNWARD && x_bits.is_neg());
+#endif
+    if (round_to_one)
+      return FPBits::one(x_bits.sign()).get_val();
+    return FPBits(static_cast<uint16_t>((x_u & 0x8000U) | 0x3f7fU)).get_val();
+  }
+
+  return fputil::cast<bfloat16>(tanhf(static_cast<float>(x)));
+}
+
+} // namespace math
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LLVM_LIBC_SRC___SUPPORT_MATH_TANHBF16_H
diff --git a/libc/src/math/CMakeLists.txt b/libc/src/math/CMakeLists.txt
index 2c7568f0b6361..49072c724d66c 100644
--- a/libc/src/math/CMakeLists.txt
+++ b/libc/src/math/CMakeLists.txt
@@ -596,6 +596,7 @@ add_math_entrypoint_object(tanf)
 add_math_entrypoint_object(tanf16)
 
 add_math_entrypoint_object(tanh)
+add_math_entrypoint_object(tanhbf16)
 add_math_entrypoint_object(tanhf)
 add_math_entrypoint_object(tanhf16)
 
diff --git a/libc/src/math/generic/CMakeLists.txt b/libc/src/math/generic/CMakeLists.txt
index 28b8e954530dd..2a6275548e3c2 100644
--- a/libc/src/math/generic/CMakeLists.txt
+++ b/libc/src/math/generic/CMakeLists.txt
@@ -3765,6 +3765,16 @@ add_entrypoint_object(
     libc.src.__support.math.sinhf16
 )
 
+add_entrypoint_object(
+  tanhbf16
+  SRCS
+    tanhbf16.cpp
+  HDRS
+    ../tanhbf16.h
+  DEPENDS
+    libc.src.__support.math.tanhbf16
+)
+
 add_entrypoint_object(
   tanhf
   SRCS
diff --git a/libc/src/math/generic/tanhbf16.cpp b/libc/src/math/generic/tanhbf16.cpp
new file mode 100644
index 0000000000000..09028eb829aa4
--- /dev/null
+++ b/libc/src/math/generic/tanhbf16.cpp
@@ -0,0 +1,19 @@
+//===-- Implementation for tanhbf16(x) function ---------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+#include "src/math/tanhbf16.h"
+#include "src/__support/common.h"
+#include "src/__support/math/tanhbf16.h"
+
+namespace LIBC_NAMESPACE_DECL {
+
+LLVM_LIBC_FUNCTION(bfloat16, tanhbf16, (bfloat16 x)) {
+  return math::tanhbf16(x);
+}
+
+} // namespace LIBC_NAMESPACE_DECL
diff --git a/libc/src/math/tanhbf16.h b/libc/src/math/tanhbf16.h
new file mode 100644
index 0000000000000..4ba909be30a91
--- /dev/null
+++ b/libc/src/math/tanhbf16.h
@@ -0,0 +1,21 @@
+//===-- Implementation header for tanhbf16 ---------------------*- 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_MATH_TANHBF16_H
+#define LLVM_LIBC_SRC_MATH_TANHBF16_H
+
+#include "src/__support/FPUtil/bfloat16.h"
+#include "src/__support/macros/config.h"
+
+namespace LIBC_NAMESPACE_DECL {
+
+bfloat16 tanhbf16(bfloat16 x);
+
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LLVM_LIBC_SRC_MATH_TANHBF16_H
diff --git a/libc/test/shared/CMakeLists.txt b/libc/test/shared/CMakeLists.txt
index 74eda7cdaf065..e9348213984a5 100644
--- a/libc/test/shared/CMakeLists.txt
+++ b/libc/test/shared/CMakeLists.txt
@@ -485,6 +485,7 @@ else()
       libc.src.__support.math.tanbf16
       libc.src.__support.math.tanf
       libc.src.__support.math.tanf16
+      libc.src.__support.math.tanhbf16
       libc.src.__support.math.tanhf
       libc.src.__support.math.tanhf16
       libc.src.__support.math.tanpif
diff --git a/libc/test/shared/shared_math_test.cpp b/libc/test/shared/shared_math_test.cpp
index 7b785331f36c6..5e715a49afcc0 100644
--- a/libc/test/shared/shared_math_test.cpp
+++ b/libc/test/shared/shared_math_test.cpp
@@ -902,5 +902,6 @@ TEST(LlvmLibcSharedMathTest, AllBFloat16) {
   EXPECT_FP_EQ(bfloat16(0.0),
                LIBC_NAMESPACE::shared::roundevenbf16(bfloat16(0.0)));
   EXPECT_FP_EQ(bfloat16(0.0), LIBC_NAMESPACE::shared::tanbf16(bfloat16(0.0)));
+  EXPECT_FP_EQ(bfloat16(0.0), LIBC_NAMESPACE::shared::tanhbf16(bfloat16(0.0)));
   EXPECT_FP_EQ(bfloat16(0.0), LIBC_NAMESPACE::shared::truncbf16(bfloat16(0.0)));
 }
diff --git a/libc/test/src/math/CMakeLists.txt b/libc/test/src/math/CMakeLists.txt
index 1fd0772aa5031..7623f7d61fece 100644
--- a/libc/test/src/math/CMakeLists.txt
+++ b/libc/test/src/math/CMakeLists.txt
@@ -2625,6 +2625,19 @@ add_fp_unittest(
     libc.src.math.sinhf16
 )
 
+add_fp_unittest(
+  tanhbf16_test
+  NEED_MPFR
+  SUITE
+    libc-math-unittests
+  SRCS
+    tanhbf16_test.cpp
+  DEPENDS
+    libc.src.math.tanhbf16
+    libc.src.__support.FPUtil.fp_bits
+    libc.src.__support.FPUtil.bfloat16
+)
+
 add_fp_unittest(
   tanhf_test
   NEED_MPFR
diff --git a/libc/test/src/math/smoke/CMakeLists.txt b/libc/test/src/math/smoke/CMakeLists.txt
index 0bfe73a2e643a..e06b5b54f5144 100644
--- a/libc/test/src/math/smoke/CMakeLists.txt
+++ b/libc/test/src/math/smoke/CMakeLists.txt
@@ -4774,6 +4774,19 @@ add_fp_unittest(
     libc.src.__support.FPUtil.cast
 )
 
+add_fp_unittest(
+  tanhbf16_test
+  SUITE
+    libc-math-smoke-tests
+  SRCS
+    tanhbf16_test.cpp
+  DEPENDS
+    libc.hdr.errno_macros
+    libc.hdr.fenv_macros
+    libc.src.math.tanhbf16
+    libc.src.__support.FPUtil.bfloat16
+)
+
 add_fp_unittest(
   tanhf_test
   SUITE
diff --git a/libc/test/src/math/smoke/tanhbf16_test.cpp b/libc/test/src/math/smoke/tanhbf16_test.cpp
new file mode 100644
index 0000000000000..0aa9383d97bbf
--- /dev/null
+++ b/libc/test/src/math/smoke/tanhbf16_test.cpp
@@ -0,0 +1,69 @@
+//===-- Unittests for tanhbf16 --------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+#include "hdr/errno_macros.h"
+#include "hdr/fenv_macros.h"
+#include "src/__support/FPUtil/bfloat16.h"
+#include "src/math/tanhbf16.h"
+#include "test/UnitTest/FPMatcher.h"
+#include "test/UnitTest/Test.h"
+
+using LlvmLibcTanhBf16Test = LIBC_NAMESPACE::testing::FPTest<bfloat16>;
+
+TEST_F(LlvmLibcTanhBf16Test, SpecialNumbers) {
+  EXPECT_FP_EQ_ALL_ROUNDING(aNaN, LIBC_NAMESPACE::tanhbf16(aNaN));
+  EXPECT_MATH_ERRNO(0);
+
+  EXPECT_FP_EQ_WITH_EXCEPTION_ALL_ROUNDING(aNaN, LIBC_NAMESPACE::tanhbf16(sNaN),
+                                           FE_INVALID);
+  EXPECT_MATH_ERRNO(0);
+
+  EXPECT_FP_EQ_ALL_ROUNDING(bfloat16(1.0f), LIBC_NAMESPACE::tanhbf16(inf));
+  EXPECT_FP_EQ_ALL_ROUNDING(bfloat16(-1.0f), LIBC_NAMESPACE::tanhbf16(neg_inf));
+  EXPECT_FP_EQ_ALL_ROUNDING(zero, LIBC_NAMESPACE::tanhbf16(zero));
+  EXPECT_FP_EQ_ALL_ROUNDING(neg_zero, LIBC_NAMESPACE::tanhbf16(neg_zero));
+  EXPECT_MATH_ERRNO(0);
+}
+
+TEST_F(LlvmLibcTanhBf16Test, SmallAndLargeValues) {
+  bfloat16 x = FPBits(uint16_t(0x3d80U)).get_val(); // 0.0625
+  bfloat16 below_x = FPBits(uint16_t(0x3d7fU)).get_val();
+  EXPECT_FP_EQ_WITH_EXCEPTION_ROUNDING_NEAREST(x, LIBC_NAMESPACE::tanhbf16(x),
+                                               FE_INEXACT);
+  EXPECT_FP_EQ_WITH_EXCEPTION_ROUNDING_DOWNWARD(
+      below_x, LIBC_NAMESPACE::tanhbf16(x), FE_INEXACT);
+
+  EXPECT_FP_EQ_WITH_EXCEPTION_ROUNDING_NEAREST(
+      bfloat16(1.0f), LIBC_NAMESPACE::tanhbf16(max_normal), FE_INEXACT);
+  EXPECT_FP_EQ_WITH_EXCEPTION_ROUNDING_DOWNWARD(
+      FPBits(uint16_t(0x3f7fU)).get_val(), LIBC_NAMESPACE::tanhbf16(max_normal),
+      FE_INEXACT);
+  EXPECT_FP_EQ_WITH_EXCEPTION_ROUNDING_UPWARD(
+      FPBits(uint16_t(0xbf7fU)).get_val(),
+      LIBC_NAMESPACE::tanhbf16(neg_max_normal), FE_INEXACT);
+  EXPECT_MATH_ERRNO(0);
+}
+
+TEST_F(LlvmLibcTanhBf16Test, TinyValues) {
+  bfloat16 smallest = FPBits(uint16_t(0x0001U)).get_val();
+  bfloat16 neg_smallest = FPBits(uint16_t(0x8001U)).get_val();
+  EXPECT_FP_EQ_WITH_EXCEPTION_ROUNDING_NEAREST(
+      smallest, LIBC_NAMESPACE::tanhbf16(smallest), FE_UNDERFLOW | FE_INEXACT);
+  EXPECT_FP_EQ_WITH_EXCEPTION_ROUNDING_DOWNWARD(
+      zero, LIBC_NAMESPACE::tanhbf16(smallest), FE_UNDERFLOW | FE_INEXACT);
+  EXPECT_FP_EQ_WITH_EXCEPTION_ROUNDING_UPWARD(
+      neg_zero, LIBC_NAMESPACE::tanhbf16(neg_smallest),
+      FE_UNDERFLOW | FE_INEXACT);
+
+  bfloat16 min_normal = FPBits(uint16_t(0x0080U)).get_val();
+  bfloat16 max_subnormal = FPBits(uint16_t(0x007fU)).get_val();
+  EXPECT_FP_EQ_WITH_EXCEPTION_ROUNDING_DOWNWARD(
+      max_subnormal, LIBC_NAMESPACE::tanhbf16(min_normal),
+      FE_UNDERFLOW | FE_INEXACT);
+  EXPECT_MATH_ERRNO(0);
+}
diff --git a/libc/test/src/math/tanhbf16_test.cpp b/libc/test/src/math/tanhbf16_test.cpp
new file mode 100644
index 0000000000000..78b28b77e0167
--- /dev/null
+++ b/libc/test/src/math/tanhbf16_test.cpp
@@ -0,0 +1,33 @@
+//===-- Exhaustive test for tanhbf16 --------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+#include "src/__support/FPUtil/bfloat16.h"
+#include "src/math/tanhbf16.h"
+#include "test/UnitTest/FPMatcher.h"
+#include "test/UnitTest/Test.h"
+#include "utils/MPFRWrapper/MPFRUtils.h"
+
+using LlvmLibcTanhBf16Test = LIBC_NAMESPACE::testing::FPTest<bfloat16>;
+
+namespace mpfr = LIBC_NAMESPACE::testing::mpfr;
+
+TEST_F(LlvmLibcTanhBf16Test, PositiveRange) {
+  for (uint32_t v = 0; v <= 0x7f80U; ++v) {
+    bfloat16 x = FPBits(static_cast<uint16_t>(v)).get_val();
+    EXPECT_MPFR_MATCH_ALL_ROUNDING(mpfr::Operation::Tanh, x,
+                                   LIBC_NAMESPACE::tanhbf16(x), 0.5);
+  }
+}
+
+TEST_F(LlvmLibcTanhBf16Test, NegativeRange) {
+  for (uint32_t v = 0x8000U; v <= 0xff80U; ++v) {
+    bfloat16 x = FPBits(static_cast<uint16_t>(v)).get_val();
+    EXPECT_MPFR_MATCH_ALL_ROUNDING(mpfr::Operation::Tanh, x,
+                                   LIBC_NAMESPACE::tanhbf16(x), 0.5);
+  }
+}
diff --git a/utils/bazel/llvm-project-overlay/libc/BUILD.bazel b/utils/bazel/llvm-project-overlay/libc/BUILD.bazel
index 72a3e709e4af4..6e7ba5300ecf7 100644
--- a/utils/bazel/llvm-project-overlay/libc/BUILD.bazel
+++ b/utils/bazel/llvm-project-overlay/libc/BUILD.bazel
@@ -11456,6 +11456,22 @@ libc_support_library(
     ],
 )
 
+libc_support_library(
+    name = "__support_math_tanhbf16",
+    hdrs = ["src/__support/math/tanhbf16.h"],
+    deps = [
+        ":__support_fputil_bfloat16",
+        ":__support_fputil_cast",
+        ":__support_fputil_fenv_impl",
+        ":__support_fputil_fp_bits",
+        ":__support_fputil_rounding_mode",
+        ":__support_math_tanhf",
+        ":__support_macros_config",
+        ":__support_macros_optimization",
+        ":hdr_fenv_macros",
+    ],
+)
+
 libc_support_library(
     name = "__support_math_tanhf",
     hdrs = ["src/__support/math/tanhf.h"],
@@ -14980,6 +14996,13 @@ libc_math_function(
     ],
 )
 
+libc_math_function(
+    name = "tanhbf16",
+    additional_deps = [
+        ":__support_math_tanhbf16",
+    ],
+)
+
 libc_math_function(
     name = "tanhf",
     additional_deps = [

>From 7207f90aaa916eee3415eb66d7bb967026f4bb5f Mon Sep 17 00:00:00 2001
From: sid <siddharthqln at gmail.com>
Date: Sun, 4 Oct 2026 19:22:01 +0530
Subject: [PATCH 2/2] fix tanhbf16 Bazel build and tests

---
 utils/bazel/llvm-project-overlay/libc/BUILD.bazel          | 3 ++-
 .../llvm-project-overlay/libc/test/src/math/BUILD.bazel    | 7 +++++++
 .../libc/test/src/math/smoke/BUILD.bazel                   | 7 +++++++
 3 files changed, 16 insertions(+), 1 deletion(-)

diff --git a/utils/bazel/llvm-project-overlay/libc/BUILD.bazel b/utils/bazel/llvm-project-overlay/libc/BUILD.bazel
index 6e7ba5300ecf7..b4d85213623e1 100644
--- a/utils/bazel/llvm-project-overlay/libc/BUILD.bazel
+++ b/utils/bazel/llvm-project-overlay/libc/BUILD.bazel
@@ -11465,9 +11465,9 @@ libc_support_library(
         ":__support_fputil_fenv_impl",
         ":__support_fputil_fp_bits",
         ":__support_fputil_rounding_mode",
-        ":__support_math_tanhf",
         ":__support_macros_config",
         ":__support_macros_optimization",
+        ":__support_math_tanhf",
         ":hdr_fenv_macros",
     ],
 )
@@ -14999,6 +14999,7 @@ libc_math_function(
 libc_math_function(
     name = "tanhbf16",
     additional_deps = [
+        ":__support_fputil_bfloat16",
         ":__support_math_tanhbf16",
     ],
 )
diff --git a/utils/bazel/llvm-project-overlay/libc/test/src/math/BUILD.bazel b/utils/bazel/llvm-project-overlay/libc/test/src/math/BUILD.bazel
index f9d21bcabeaa5..d5f02cf58bc61 100644
--- a/utils/bazel/llvm-project-overlay/libc/test/src/math/BUILD.bazel
+++ b/utils/bazel/llvm-project-overlay/libc/test/src/math/BUILD.bazel
@@ -876,6 +876,13 @@ math_mpfr_test(
     ],
 )
 
+math_mpfr_test(
+    name = "tanhbf16",
+    deps = [
+        "//libc:__support_fputil_bfloat16",
+    ],
+)
+
 math_mpfr_test(name = "tanhf")
 
 math_mpfr_test(
diff --git a/utils/bazel/llvm-project-overlay/libc/test/src/math/smoke/BUILD.bazel b/utils/bazel/llvm-project-overlay/libc/test/src/math/smoke/BUILD.bazel
index 0a79dcd33a587..e78a5e63bb24b 100644
--- a/utils/bazel/llvm-project-overlay/libc/test/src/math/smoke/BUILD.bazel
+++ b/utils/bazel/llvm-project-overlay/libc/test/src/math/smoke/BUILD.bazel
@@ -2131,6 +2131,13 @@ math_test(name = "tan")
 
 math_test(name = "tanf")
 
+math_test(
+    name = "tanhbf16",
+    deps = [
+        "//libc:__support_fputil_bfloat16",
+    ],
+)
+
 math_test(name = "tanhf")
 
 math_test(name = "tanpif")



More information about the libc-commits mailing list