[llvm] [Offload][Conformance] Add tests for single-precision math functions (PR #152013)

via llvm-commits llvm-commits at lists.llvm.org
Mon Aug 4 11:57:32 PDT 2025


llvmbot wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-offload

Author: Leandro Lacerda (leandrolcampos)

<details>
<summary>Changes</summary>

This patch adds a new set of conformance tests for single-precision math functions provided by the LLVM libm for GPUs.

The functions included in this set were selected based on the following criteria:
- An implementation exists in `libc/src/math/generic` (i.e., it is not just a wrapper around a compiler built-in).
- The corresponding LLVM CPU libm implementation is correctly rounded.
- The function is listed in Table 65 of the OpenCL C Specification v3.0.19.

---

Patch is 62.08 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/152013.diff


30 Files Affected:

- (modified) offload/unittests/Conformance/device_code/CMakeLists.txt (+1-1) 
- (added) offload/unittests/Conformance/device_code/Common.hpp (+38) 
- (modified) offload/unittests/Conformance/device_code/LLVMLibm.cpp (+156-12) 
- (added) offload/unittests/Conformance/tests/AcosfTest.cpp (+53) 
- (added) offload/unittests/Conformance/tests/AcoshfTest.cpp (+57) 
- (added) offload/unittests/Conformance/tests/AsinfTest.cpp (+53) 
- (added) offload/unittests/Conformance/tests/AsinhfTest.cpp (+54) 
- (added) offload/unittests/Conformance/tests/AtanfTest.cpp (+53) 
- (added) offload/unittests/Conformance/tests/AtanhfTest.cpp (+56) 
- (modified) offload/unittests/Conformance/tests/CMakeLists.txt (+25) 
- (added) offload/unittests/Conformance/tests/CbrtfTest.cpp (+53) 
- (added) offload/unittests/Conformance/tests/CosfTest.cpp (+53) 
- (added) offload/unittests/Conformance/tests/CoshfTest.cpp (+53) 
- (added) offload/unittests/Conformance/tests/CospifTest.cpp (+56) 
- (added) offload/unittests/Conformance/tests/ErffTest.cpp (+53) 
- (added) offload/unittests/Conformance/tests/Exp10fTest.cpp (+54) 
- (added) offload/unittests/Conformance/tests/Exp2fTest.cpp (+53) 
- (added) offload/unittests/Conformance/tests/ExpfTest.cpp (+53) 
- (added) offload/unittests/Conformance/tests/Expm1fTest.cpp (+54) 
- (modified) offload/unittests/Conformance/tests/Hypotf16Test.cpp (+1-4) 
- (added) offload/unittests/Conformance/tests/Log10fTest.cpp (+57) 
- (added) offload/unittests/Conformance/tests/Log1pfTest.cpp (+57) 
- (added) offload/unittests/Conformance/tests/Log2fTest.cpp (+56) 
- (added) offload/unittests/Conformance/tests/SincosfTest.cpp (+77) 
- (added) offload/unittests/Conformance/tests/SinfTest.cpp (+53) 
- (added) offload/unittests/Conformance/tests/SinhfTest.cpp (+53) 
- (added) offload/unittests/Conformance/tests/SinpifTest.cpp (+56) 
- (added) offload/unittests/Conformance/tests/TanfTest.cpp (+53) 
- (added) offload/unittests/Conformance/tests/TanhfTest.cpp (+53) 
- (added) offload/unittests/Conformance/tests/TanpifTest.cpp (+56) 


``````````diff
diff --git a/offload/unittests/Conformance/device_code/CMakeLists.txt b/offload/unittests/Conformance/device_code/CMakeLists.txt
index 9cbd11096292c..a7f504dbadc9b 100644
--- a/offload/unittests/Conformance/device_code/CMakeLists.txt
+++ b/offload/unittests/Conformance/device_code/CMakeLists.txt
@@ -1,4 +1,4 @@
-add_offload_test_device_code(LLVMLibm.cpp llvm-libm -stdlib -fno-builtin)
+add_offload_test_device_code(LLVMLibm.cpp llvm-libm -O3 -stdlib -fno-builtin -I.)
 
 add_custom_target(conformance_device_binaries DEPENDS llvm-libm.bin)
 set(OFFLOAD_CONFORMANCE_DEVICE_BINARY_DIR ${CMAKE_CURRENT_BINARY_DIR} PARENT_SCOPE)
diff --git a/offload/unittests/Conformance/device_code/Common.hpp b/offload/unittests/Conformance/device_code/Common.hpp
new file mode 100644
index 0000000000000..5f9c3bf673559
--- /dev/null
+++ b/offload/unittests/Conformance/device_code/Common.hpp
@@ -0,0 +1,38 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file
+/// This file contains common utilities for defining device kernel wrappers to
+/// math functions.
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef COMMON_HPP
+#define COMMON_HPP
+
+#include <gpuintrin.h>
+#include <stddef.h>
+#include <stdint.h>
+
+namespace common {
+
+typedef _Float16 float16;
+
+template <auto Func, typename OutType, typename... InTypes>
+__attribute__((always_inline)) void
+runKernelBody(size_t NumElements, OutType *Out, const InTypes *...Ins) {
+  uint32_t Index =
+      __gpu_num_threads_x() * __gpu_block_id_x() + __gpu_thread_id_x();
+
+  if (Index < NumElements) {
+    Out[Index] = Func(Ins[Index]...);
+  }
+}
+} // namespace common
+
+#endif // COMMON_HPP
diff --git a/offload/unittests/Conformance/device_code/LLVMLibm.cpp b/offload/unittests/Conformance/device_code/LLVMLibm.cpp
index 2c3d9bc5bf5cf..8d9412ee73c44 100644
--- a/offload/unittests/Conformance/device_code/LLVMLibm.cpp
+++ b/offload/unittests/Conformance/device_code/LLVMLibm.cpp
@@ -12,29 +12,173 @@
 ///
 //===----------------------------------------------------------------------===//
 
+#include "Common.hpp"
+
 #include <gpuintrin.h>
 #include <math.h>
 #include <stddef.h>
-#include <stdint.h>
 
-typedef _Float16 float16;
+using namespace common;
+
+//===----------------------------------------------------------------------===//
+// Helpers
+//===----------------------------------------------------------------------===//
+
+static inline float sincosfSin(float X) {
+  float SinX, CosX;
+  sincosf(X, &SinX, &CosX);
+  return SinX;
+}
+
+static inline float sincosfCos(float X) {
+  float SinX, CosX;
+  sincosf(X, &SinX, &CosX);
+  return CosX;
+}
+
+//===----------------------------------------------------------------------===//
+// Kernels
+//===----------------------------------------------------------------------===//
 
 extern "C" {
 
+__gpu_kernel void acosfKernel(const float *X, float *Out,
+                              size_t NumElements) noexcept {
+  runKernelBody<acosf>(NumElements, Out, X);
+}
+
+__gpu_kernel void acoshfKernel(const float *X, float *Out,
+                               size_t NumElements) noexcept {
+  runKernelBody<acoshf>(NumElements, Out, X);
+}
+
+__gpu_kernel void asinfKernel(const float *X, float *Out,
+                              size_t NumElements) noexcept {
+  runKernelBody<asinf>(NumElements, Out, X);
+}
+
+__gpu_kernel void asinhfKernel(const float *X, float *Out,
+                               size_t NumElements) noexcept {
+  runKernelBody<asinhf>(NumElements, Out, X);
+}
+
+__gpu_kernel void atanfKernel(const float *X, float *Out,
+                              size_t NumElements) noexcept {
+  runKernelBody<atanf>(NumElements, Out, X);
+}
+
+__gpu_kernel void atanhfKernel(const float *X, float *Out,
+                               size_t NumElements) noexcept {
+  runKernelBody<atanhf>(NumElements, Out, X);
+}
+
+__gpu_kernel void cbrtfKernel(const float *X, float *Out,
+                              size_t NumElements) noexcept {
+  runKernelBody<cbrtf>(NumElements, Out, X);
+}
+
+__gpu_kernel void cosfKernel(const float *X, float *Out,
+                             size_t NumElements) noexcept {
+  runKernelBody<cosf>(NumElements, Out, X);
+}
+
+__gpu_kernel void coshfKernel(const float *X, float *Out,
+                              size_t NumElements) noexcept {
+  runKernelBody<coshf>(NumElements, Out, X);
+}
+
+__gpu_kernel void cospifKernel(const float *X, float *Out,
+                               size_t NumElements) noexcept {
+  runKernelBody<cospif>(NumElements, Out, X);
+}
+
+__gpu_kernel void erffKernel(const float *X, float *Out,
+                             size_t NumElements) noexcept {
+  runKernelBody<erff>(NumElements, Out, X);
+}
+
+__gpu_kernel void expfKernel(const float *X, float *Out,
+                             size_t NumElements) noexcept {
+  runKernelBody<expf>(NumElements, Out, X);
+}
+
+__gpu_kernel void exp10fKernel(const float *X, float *Out,
+                               size_t NumElements) noexcept {
+  runKernelBody<exp10f>(NumElements, Out, X);
+}
+
+__gpu_kernel void exp2fKernel(const float *X, float *Out,
+                              size_t NumElements) noexcept {
+  runKernelBody<exp2f>(NumElements, Out, X);
+}
+
+__gpu_kernel void expm1fKernel(const float *X, float *Out,
+                               size_t NumElements) noexcept {
+  runKernelBody<expm1f>(NumElements, Out, X);
+}
+
 __gpu_kernel void hypotf16Kernel(const float16 *X, float16 *Y, float16 *Out,
-                                 size_t NumElements) {
-  uint32_t Index =
-      __gpu_num_threads_x() * __gpu_block_id_x() + __gpu_thread_id_x();
+                                 size_t NumElements) noexcept {
+  runKernelBody<hypotf16>(NumElements, Out, X, Y);
+}
+
+__gpu_kernel void logfKernel(const float *X, float *Out,
+                             size_t NumElements) noexcept {
+  runKernelBody<logf>(NumElements, Out, X);
+}
+
+__gpu_kernel void log10fKernel(const float *X, float *Out,
+                               size_t NumElements) noexcept {
+  runKernelBody<log10f>(NumElements, Out, X);
+}
 
-  if (Index < NumElements)
-    Out[Index] = hypotf16(X[Index], Y[Index]);
+__gpu_kernel void log1pfKernel(const float *X, float *Out,
+                               size_t NumElements) noexcept {
+  runKernelBody<log1pf>(NumElements, Out, X);
 }
 
-__gpu_kernel void logfKernel(const float *X, float *Out, size_t NumElements) {
-  uint32_t Index =
-      __gpu_num_threads_x() * __gpu_block_id_x() + __gpu_thread_id_x();
+__gpu_kernel void log2fKernel(const float *X, float *Out,
+                              size_t NumElements) noexcept {
+  runKernelBody<log2f>(NumElements, Out, X);
+}
+
+__gpu_kernel void sinfKernel(const float *X, float *Out,
+                             size_t NumElements) noexcept {
+  runKernelBody<sinf>(NumElements, Out, X);
+}
+
+__gpu_kernel void sincosfSinKernel(const float *X, float *Out,
+                                   size_t NumElements) noexcept {
+  runKernelBody<sincosfSin>(NumElements, Out, X);
+}
+
+__gpu_kernel void sincosfCosKernel(const float *X, float *Out,
+                                   size_t NumElements) noexcept {
+  runKernelBody<sincosfCos>(NumElements, Out, X);
+}
+
+__gpu_kernel void sinhfKernel(const float *X, float *Out,
+                              size_t NumElements) noexcept {
+  runKernelBody<sinhf>(NumElements, Out, X);
+}
+
+__gpu_kernel void sinpifKernel(const float *X, float *Out,
+                               size_t NumElements) noexcept {
+  runKernelBody<sinpif>(NumElements, Out, X);
+}
+
+__gpu_kernel void tanfKernel(const float *X, float *Out,
+                             size_t NumElements) noexcept {
+  runKernelBody<tanf>(NumElements, Out, X);
+}
+
+__gpu_kernel void tanhfKernel(const float *X, float *Out,
+                              size_t NumElements) noexcept {
+  runKernelBody<tanhf>(NumElements, Out, X);
+}
 
-  if (Index < NumElements)
-    Out[Index] = logf(X[Index]);
+__gpu_kernel void tanpifKernel(const float *X, float *Out,
+                               size_t NumElements) noexcept {
+  runKernelBody<tanpif>(NumElements, Out, X);
 }
 } // extern "C"
diff --git a/offload/unittests/Conformance/tests/AcosfTest.cpp b/offload/unittests/Conformance/tests/AcosfTest.cpp
new file mode 100644
index 0000000000000..e69ee3b7d1fd7
--- /dev/null
+++ b/offload/unittests/Conformance/tests/AcosfTest.cpp
@@ -0,0 +1,53 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file
+/// This file contains the conformance test of the acosf function.
+///
+//===----------------------------------------------------------------------===//
+
+#include "mathtest/CommandLineExtras.hpp"
+#include "mathtest/ExhaustiveGenerator.hpp"
+#include "mathtest/IndexedRange.hpp"
+#include "mathtest/TestConfig.hpp"
+#include "mathtest/TestRunner.hpp"
+
+#include "llvm/ADT/StringRef.h"
+
+#include <cstdlib>
+#include <math.h>
+
+namespace mathtest {
+
+template <> struct FunctionConfig<acosf> {
+  static constexpr llvm::StringRef Name = "acosf";
+  static constexpr llvm::StringRef KernelName = "acosfKernel";
+
+  // Source: The Khronos Group, The OpenCL C Specification v3.0.19, Sec. 7.4,
+  //         Table 65, Khronos Registry [July 10, 2025].
+  static constexpr uint64_t UlpTolerance = 4;
+};
+} // namespace mathtest
+
+int main(int argc, const char **argv) {
+  llvm::cl::ParseCommandLineOptions(argc, argv,
+                                    "Conformance test of the acosf function");
+
+  using namespace mathtest;
+
+  IndexedRange<float> Range;
+  ExhaustiveGenerator<float> Generator(Range);
+
+  const auto Configs = cl::getTestConfigs();
+  const llvm::StringRef DeviceBinaryDir = DEVICE_BINARY_DIR;
+  const bool IsVerbose = cl::IsVerbose;
+
+  bool Passed = runTests<acosf>(Generator, Configs, DeviceBinaryDir, IsVerbose);
+
+  return Passed ? EXIT_SUCCESS : EXIT_FAILURE;
+}
diff --git a/offload/unittests/Conformance/tests/AcoshfTest.cpp b/offload/unittests/Conformance/tests/AcoshfTest.cpp
new file mode 100644
index 0000000000000..4d43a661c3535
--- /dev/null
+++ b/offload/unittests/Conformance/tests/AcoshfTest.cpp
@@ -0,0 +1,57 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file
+/// This file contains the conformance test of the acoshf function.
+///
+//===----------------------------------------------------------------------===//
+
+#include "mathtest/CommandLineExtras.hpp"
+#include "mathtest/ExhaustiveGenerator.hpp"
+#include "mathtest/IndexedRange.hpp"
+#include "mathtest/TestConfig.hpp"
+#include "mathtest/TestRunner.hpp"
+
+#include "llvm/ADT/StringRef.h"
+
+#include <cstdlib>
+#include <limits>
+#include <math.h>
+
+namespace mathtest {
+
+template <> struct FunctionConfig<acoshf> {
+  static constexpr llvm::StringRef Name = "acoshf";
+  static constexpr llvm::StringRef KernelName = "acoshfKernel";
+
+  // Source: The Khronos Group, The OpenCL C Specification v3.0.19, Sec. 7.4,
+  //         Table 65, Khronos Registry [July 10, 2025].
+  static constexpr uint64_t UlpTolerance = 4;
+};
+} // namespace mathtest
+
+int main(int argc, const char **argv) {
+  llvm::cl::ParseCommandLineOptions(argc, argv,
+                                    "Conformance test of the acoshf function");
+
+  using namespace mathtest;
+
+  IndexedRange<float> Range(/*Begin=*/1.0f,
+                            /*End=*/std::numeric_limits<float>::infinity(),
+                            /*Inclusive=*/true);
+  ExhaustiveGenerator<float> Generator(Range);
+
+  const auto Configs = cl::getTestConfigs();
+  const llvm::StringRef DeviceBinaryDir = DEVICE_BINARY_DIR;
+  const bool IsVerbose = cl::IsVerbose;
+
+  bool Passed =
+      runTests<acoshf>(Generator, Configs, DeviceBinaryDir, IsVerbose);
+
+  return Passed ? EXIT_SUCCESS : EXIT_FAILURE;
+}
diff --git a/offload/unittests/Conformance/tests/AsinfTest.cpp b/offload/unittests/Conformance/tests/AsinfTest.cpp
new file mode 100644
index 0000000000000..991f79b111efe
--- /dev/null
+++ b/offload/unittests/Conformance/tests/AsinfTest.cpp
@@ -0,0 +1,53 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file
+/// This file contains the conformance test of the asinf function.
+///
+//===----------------------------------------------------------------------===//
+
+#include "mathtest/CommandLineExtras.hpp"
+#include "mathtest/ExhaustiveGenerator.hpp"
+#include "mathtest/IndexedRange.hpp"
+#include "mathtest/TestConfig.hpp"
+#include "mathtest/TestRunner.hpp"
+
+#include "llvm/ADT/StringRef.h"
+
+#include <cstdlib>
+#include <math.h>
+
+namespace mathtest {
+
+template <> struct FunctionConfig<asinf> {
+  static constexpr llvm::StringRef Name = "asinf";
+  static constexpr llvm::StringRef KernelName = "asinfKernel";
+
+  // Source: The Khronos Group, The OpenCL C Specification v3.0.19, Sec. 7.4,
+  //         Table 65, Khronos Registry [July 10, 2025].
+  static constexpr uint64_t UlpTolerance = 4;
+};
+} // namespace mathtest
+
+int main(int argc, const char **argv) {
+  llvm::cl::ParseCommandLineOptions(argc, argv,
+                                    "Conformance test of the asinf function");
+
+  using namespace mathtest;
+
+  IndexedRange<float> Range;
+  ExhaustiveGenerator<float> Generator(Range);
+
+  const auto Configs = cl::getTestConfigs();
+  const llvm::StringRef DeviceBinaryDir = DEVICE_BINARY_DIR;
+  const bool IsVerbose = cl::IsVerbose;
+
+  bool Passed = runTests<asinf>(Generator, Configs, DeviceBinaryDir, IsVerbose);
+
+  return Passed ? EXIT_SUCCESS : EXIT_FAILURE;
+}
diff --git a/offload/unittests/Conformance/tests/AsinhfTest.cpp b/offload/unittests/Conformance/tests/AsinhfTest.cpp
new file mode 100644
index 0000000000000..9439383772314
--- /dev/null
+++ b/offload/unittests/Conformance/tests/AsinhfTest.cpp
@@ -0,0 +1,54 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file
+/// This file contains the conformance test of the asinhf function.
+///
+//===----------------------------------------------------------------------===//
+
+#include "mathtest/CommandLineExtras.hpp"
+#include "mathtest/ExhaustiveGenerator.hpp"
+#include "mathtest/IndexedRange.hpp"
+#include "mathtest/TestConfig.hpp"
+#include "mathtest/TestRunner.hpp"
+
+#include "llvm/ADT/StringRef.h"
+
+#include <cstdlib>
+#include <math.h>
+
+namespace mathtest {
+
+template <> struct FunctionConfig<asinhf> {
+  static constexpr llvm::StringRef Name = "asinhf";
+  static constexpr llvm::StringRef KernelName = "asinhfKernel";
+
+  // Source: The Khronos Group, The OpenCL C Specification v3.0.19, Sec. 7.4,
+  //         Table 65, Khronos Registry [July 10, 2025].
+  static constexpr uint64_t UlpTolerance = 4;
+};
+} // namespace mathtest
+
+int main(int argc, const char **argv) {
+  llvm::cl::ParseCommandLineOptions(argc, argv,
+                                    "Conformance test of the asinhf function");
+
+  using namespace mathtest;
+
+  IndexedRange<float> Range;
+  ExhaustiveGenerator<float> Generator(Range);
+
+  const auto Configs = cl::getTestConfigs();
+  const llvm::StringRef DeviceBinaryDir = DEVICE_BINARY_DIR;
+  const bool IsVerbose = cl::IsVerbose;
+
+  bool Passed =
+      runTests<asinhf>(Generator, Configs, DeviceBinaryDir, IsVerbose);
+
+  return Passed ? EXIT_SUCCESS : EXIT_FAILURE;
+}
diff --git a/offload/unittests/Conformance/tests/AtanfTest.cpp b/offload/unittests/Conformance/tests/AtanfTest.cpp
new file mode 100644
index 0000000000000..64068ef6bff0c
--- /dev/null
+++ b/offload/unittests/Conformance/tests/AtanfTest.cpp
@@ -0,0 +1,53 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file
+/// This file contains the conformance test of the atanf function.
+///
+//===----------------------------------------------------------------------===//
+
+#include "mathtest/CommandLineExtras.hpp"
+#include "mathtest/ExhaustiveGenerator.hpp"
+#include "mathtest/IndexedRange.hpp"
+#include "mathtest/TestConfig.hpp"
+#include "mathtest/TestRunner.hpp"
+
+#include "llvm/ADT/StringRef.h"
+
+#include <cstdlib>
+#include <math.h>
+
+namespace mathtest {
+
+template <> struct FunctionConfig<atanf> {
+  static constexpr llvm::StringRef Name = "atanf";
+  static constexpr llvm::StringRef KernelName = "atanfKernel";
+
+  // Source: The Khronos Group, The OpenCL C Specification v3.0.19, Sec. 7.4,
+  //         Table 65, Khronos Registry [July 10, 2025].
+  static constexpr uint64_t UlpTolerance = 5;
+};
+} // namespace mathtest
+
+int main(int argc, const char **argv) {
+  llvm::cl::ParseCommandLineOptions(argc, argv,
+                                    "Conformance test of the atanf function");
+
+  using namespace mathtest;
+
+  IndexedRange<float> Range;
+  ExhaustiveGenerator<float> Generator(Range);
+
+  const auto Configs = cl::getTestConfigs();
+  const llvm::StringRef DeviceBinaryDir = DEVICE_BINARY_DIR;
+  const bool IsVerbose = cl::IsVerbose;
+
+  bool Passed = runTests<atanf>(Generator, Configs, DeviceBinaryDir, IsVerbose);
+
+  return Passed ? EXIT_SUCCESS : EXIT_FAILURE;
+}
diff --git a/offload/unittests/Conformance/tests/AtanhfTest.cpp b/offload/unittests/Conformance/tests/AtanhfTest.cpp
new file mode 100644
index 0000000000000..66b934c2f925e
--- /dev/null
+++ b/offload/unittests/Conformance/tests/AtanhfTest.cpp
@@ -0,0 +1,56 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file
+/// This file contains the conformance test of the atanhf function.
+///
+//===----------------------------------------------------------------------===//
+
+#include "mathtest/CommandLineExtras.hpp"
+#include "mathtest/ExhaustiveGenerator.hpp"
+#include "mathtest/IndexedRange.hpp"
+#include "mathtest/TestConfig.hpp"
+#include "mathtest/TestRunner.hpp"
+
+#include "llvm/ADT/StringRef.h"
+
+#include <cstdlib>
+#include <math.h>
+
+namespace mathtest {
+
+template <> struct FunctionConfig<atanhf> {
+  static constexpr llvm::StringRef Name = "atanhf";
+  static constexpr llvm::StringRef KernelName = "atanhfKernel";
+
+  // Source: The Khronos Group, The OpenCL C Specification v3.0.19, Sec. 7.4,
+  //         Table 65, Khronos Registry [July 10, 2025].
+  static constexpr uint64_t UlpTolerance = 5;
+};
+} ...
[truncated]

``````````

</details>


https://github.com/llvm/llvm-project/pull/152013


More information about the llvm-commits mailing list