Skip to content

[libc][math] Add initial support for C23 float128 math functions, starting with copysignf128. #71731

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Nov 10, 2023

Conversation

lntue
Copy link
Contributor

@lntue lntue commented Nov 8, 2023

No description provided.

@llvmbot
Copy link
Member

llvmbot commented Nov 8, 2023

@llvm/pr-subscribers-libc

Author: None (lntue)

Changes

Full diff: https://github.com/llvm/llvm-project/pull/71731.diff

18 Files Affected:

  • (modified) libc/CMakeLists.txt (+1)
  • (added) libc/cmake/modules/check_compiler_features.cmake (+59)
  • (added) libc/cmake/modules/compiler_features/check_float128.cpp (+5)
  • (added) libc/cmake/modules/compiler_features/check_float16.cpp (+5)
  • (modified) libc/config/linux/x86_64/entrypoints.txt (+7)
  • (modified) libc/spec/spec.td (+3)
  • (modified) libc/spec/stdc.td (+1)
  • (modified) libc/src/__support/CPP/type_traits/is_floating_point.h (+6)
  • (modified) libc/src/__support/FPUtil/FloatProperties.h (+31)
  • (modified) libc/src/__support/macros/properties/compiler.h (+19)
  • (modified) libc/src/math/CMakeLists.txt (+1)
  • (added) libc/src/math/copysignf128.h (+20)
  • (modified) libc/src/math/generic/CMakeLists.txt (+15-3)
  • (added) libc/src/math/generic/copysignf128.cpp (+20)
  • (modified) libc/test/src/__support/FPUtil/fpbits_test.cpp (+72)
  • (modified) libc/test/src/math/smoke/CMakeLists.txt (+16)
  • (modified) libc/test/src/math/smoke/CopySignTest.h (+11-10)
  • (added) libc/test/src/math/smoke/copysignf128_test.cpp (+13)
diff --git a/libc/CMakeLists.txt b/libc/CMakeLists.txt
index 414be906336bf3f..60a68dc616c9ecb 100644
--- a/libc/CMakeLists.txt
+++ b/libc/CMakeLists.txt
@@ -245,6 +245,7 @@ option(LIBC_INCLUDE_DOCS "Build the libc documentation." ${LLVM_INCLUDE_DOCS})
 
 include(CMakeParseArguments)
 include(LLVMLibCCheckCpuFeatures)
+include(check_compiler_features)
 include(LLVMLibCRules)
 
 if(EXISTS "${LIBC_SOURCE_DIR}/config/${LIBC_TARGET_OS}/${LIBC_TARGET_ARCHITECTURE}/entrypoints.txt")
diff --git a/libc/cmake/modules/check_compiler_features.cmake b/libc/cmake/modules/check_compiler_features.cmake
new file mode 100644
index 000000000000000..61db94d1b202ecb
--- /dev/null
+++ b/libc/cmake/modules/check_compiler_features.cmake
@@ -0,0 +1,59 @@
+# ------------------------------------------------------------------------------
+# Compiler features definition and flags
+# ------------------------------------------------------------------------------
+
+# Initialize ALL_COMPILER_FEATURES as empty list.
+set(ALL_COMPILER_FEATURES "float16;float128")
+
+# Making sure ALL_COMPILER_FEATURES is sorted.
+list(SORT ALL_COMPILER_FEATURES)
+
+# Function to check whether the compiler supports the provided set of features.
+# Usage:
+# compiler_supports(
+#   <output variable>
+#   <list of cpu features>
+# )
+function(compiler_supports output_var features)
+  _intersection(var "${LIBC_CPU_FEATURES}" "${features}")
+  if("${var}" STREQUAL "${features}")
+    set(${output_var} TRUE PARENT_SCOPE)
+  else()
+    unset(${output_var} PARENT_SCOPE)
+  endif()
+endfunction()
+
+# ------------------------------------------------------------------------------
+# Internal helpers and utilities.
+# ------------------------------------------------------------------------------
+
+# Computes the intersection between two lists.
+function(_intersection output_var list1 list2)
+  foreach(element IN LISTS list1)
+    if("${list2}" MATCHES "(^|;)${element}(;|$)")
+      list(APPEND tmp "${element}")
+    endif()
+  endforeach()
+  set(${output_var} ${tmp} PARENT_SCOPE)
+endfunction()
+
+set(AVAILABLE_COMPILER_FEATURES "")
+
+# Try compile a C file to check if flag is supported.
+set(CMAKE_TRY_COMPILE_TARGET_TYPE STATIC_LIBRARY)
+foreach(feature IN LISTS ALL_COMPILER_FEATURES)
+  try_compile(
+    has_feature
+    ${CMAKE_CURRENT_BINARY_DIR}/compiler_features
+    SOURCES ${LIBC_SOURCE_DIR}/cmake/modules/compiler_features/check_${feature}.cpp
+    COMPILE_DEFINITIONS -I${LIBC_SOURCE_DIR} ${LIBC_COMPILE_OPTIONS_NATIVE}
+  )
+  if(has_feature)
+    list(APPEND AVAILABLE_COMPILER_FEATURES ${feature})
+    if(${feature} STREQUAL "float128")
+      set(LIBC_COMPILER_HAS_FLOAT128 TRUE)
+    endif()
+  endif()
+endforeach()
+
+message(STATUS "Compiler features available: ${AVAILABLE_COMPILER_FEATURES}")
diff --git a/libc/cmake/modules/compiler_features/check_float128.cpp b/libc/cmake/modules/compiler_features/check_float128.cpp
new file mode 100644
index 000000000000000..1dcfe80da0a0eb1
--- /dev/null
+++ b/libc/cmake/modules/compiler_features/check_float128.cpp
@@ -0,0 +1,5 @@
+#include "src/__support/macros/properties/compiler.h"
+
+#ifndef LIBC_COMPILER_HAS_FLOAT128
+#error unsupported
+#endif
diff --git a/libc/cmake/modules/compiler_features/check_float16.cpp b/libc/cmake/modules/compiler_features/check_float16.cpp
new file mode 100644
index 000000000000000..33d0da621b18ade
--- /dev/null
+++ b/libc/cmake/modules/compiler_features/check_float16.cpp
@@ -0,0 +1,5 @@
+#include "src/__support/macros/properties/compiler.h"
+
+#ifndef LIBC_COMPILER_HAS_FLOAT16
+#error unsupported
+#endif
diff --git a/libc/config/linux/x86_64/entrypoints.txt b/libc/config/linux/x86_64/entrypoints.txt
index 31ea282edb59126..83bc8461999ed66 100644
--- a/libc/config/linux/x86_64/entrypoints.txt
+++ b/libc/config/linux/x86_64/entrypoints.txt
@@ -360,6 +360,13 @@ set(TARGET_LIBM_ENTRYPOINTS
     libc.src.math.truncl
 )
 
+if(LIBC_COMPILER_HAS_FLOAT128)
+  list(APPEND TARGET_LIBM_ENTRYPOINTS
+    # math.h C23 _Float128 entrypoints
+    libc.src.math.copysignf128
+  )
+endif()
+
 if(LLVM_LIBC_FULL_BUILD)
   list(APPEND TARGET_LIBC_ENTRYPOINTS
     # assert.h entrypoints
diff --git a/libc/spec/spec.td b/libc/spec/spec.td
index ac0fba3bd0af788..981507a05412a14 100644
--- a/libc/spec/spec.td
+++ b/libc/spec/spec.td
@@ -50,6 +50,9 @@ def DoubleType : NamedType<"double">;
 def LongDoubleType : NamedType<"long double">;
 def CharType : NamedType<"char">;
 
+// TODO: Add compatibility layer to use C23 type _Float128 if possible.
+def Float128Type : NamedType<"__float128">
+
 // Common types
 def VoidPtr : PtrType<VoidType>;
 def VoidPtrPtr : PtrType<VoidPtr>;
diff --git a/libc/spec/stdc.td b/libc/spec/stdc.td
index 239d8f9843cfc0f..4e38cb742d2844e 100644
--- a/libc/spec/stdc.td
+++ b/libc/spec/stdc.td
@@ -358,6 +358,7 @@ def StdC : StandardSpec<"stdc"> {
           FunctionSpec<"copysign", RetValSpec<DoubleType>, [ArgSpec<DoubleType>, ArgSpec<DoubleType>]>,
           FunctionSpec<"copysignf", RetValSpec<FloatType>, [ArgSpec<FloatType>, ArgSpec<FloatType>]>,
           FunctionSpec<"copysignl", RetValSpec<LongDoubleType>, [ArgSpec<LongDoubleType>, ArgSpec<LongDoubleType>]>,
+          FunctionSpec<"copysignf128", RetValSpec<Float128Type>, [ArgSpec<Float128Type>, ArgSpec<Float128Type>]>,
 
           FunctionSpec<"ceil", RetValSpec<DoubleType>, [ArgSpec<DoubleType>]>,
           FunctionSpec<"ceilf", RetValSpec<FloatType>, [ArgSpec<FloatType>]>,
diff --git a/libc/src/__support/CPP/type_traits/is_floating_point.h b/libc/src/__support/CPP/type_traits/is_floating_point.h
index 2df75a072c3606c..bcd204102997540 100644
--- a/libc/src/__support/CPP/type_traits/is_floating_point.h
+++ b/libc/src/__support/CPP/type_traits/is_floating_point.h
@@ -11,6 +11,7 @@
 #include "src/__support/CPP/type_traits/is_same.h"
 #include "src/__support/CPP/type_traits/remove_cv.h"
 #include "src/__support/macros/attributes.h"
+#include "src/__support/macros/properties/compiler.h"
 
 namespace LIBC_NAMESPACE::cpp {
 
@@ -23,8 +24,13 @@ template <typename T> struct is_floating_point {
   }
 
 public:
+#if defined(LIBC_COMPILER_HAS_FLOAT128)
+  LIBC_INLINE_VAR static constexpr bool value =
+      __is_unqualified_any_of<T, float, double, long double, float128>();
+#else
   LIBC_INLINE_VAR static constexpr bool value =
       __is_unqualified_any_of<T, float, double, long double>();
+#endif // LIBC_COMPILER_HAS_FLOAT128
 };
 template <typename T>
 LIBC_INLINE_VAR constexpr bool is_floating_point_v =
diff --git a/libc/src/__support/FPUtil/FloatProperties.h b/libc/src/__support/FPUtil/FloatProperties.h
index c1d58a87101afc1..8f7f985108c85c3 100644
--- a/libc/src/__support/FPUtil/FloatProperties.h
+++ b/libc/src/__support/FPUtil/FloatProperties.h
@@ -175,6 +175,37 @@ template <> struct FloatProperties<long double> {
 };
 #endif
 
+#if defined(LIBC_COMPILER_HAS_FLOAT128)
+// Properties for numbers represented in 128 bits long double on non x86
+// platform.
+template <> struct FloatProperties<float128> {
+  typedef UInt128 BitsType;
+  static_assert(sizeof(BitsType) == sizeof(float128),
+                "Unexpected size of 'float128' type.");
+
+  static constexpr uint32_t BIT_WIDTH = sizeof(BitsType) << 3;
+
+  static constexpr uint32_t MANTISSA_WIDTH = 112;
+  static constexpr uint32_t MANTISSA_PRECISION = MANTISSA_WIDTH + 1;
+  static constexpr uint32_t EXPONENT_WIDTH = 15;
+  static constexpr BitsType MANTISSA_MASK = (BitsType(1) << MANTISSA_WIDTH) - 1;
+  static constexpr BitsType SIGN_MASK = BitsType(1)
+                                        << (EXPONENT_WIDTH + MANTISSA_WIDTH);
+  static constexpr BitsType EXPONENT_MASK = ~(SIGN_MASK | MANTISSA_MASK);
+  static constexpr uint32_t EXPONENT_BIAS = 16383;
+
+  static constexpr BitsType EXP_MANT_MASK = MANTISSA_MASK | EXPONENT_MASK;
+  static_assert(EXP_MANT_MASK == ~SIGN_MASK,
+                "Exponent and mantissa masks are not as expected.");
+
+  // If a number x is a NAN, then it is a quiet NAN if:
+  //   QuietNaNMask & bits(x) != 0
+  // Else, it is a signalling NAN.
+  static constexpr BitsType QUIET_NAN_MASK = BitsType(1)
+                                             << (MANTISSA_WIDTH - 1);
+};
+#endif // LIBC_COMPILER_HAS_FLOAT128
+
 // Define the float type corresponding to the BitsType.
 template <typename BitsType> struct FloatType;
 
diff --git a/libc/src/__support/macros/properties/compiler.h b/libc/src/__support/macros/properties/compiler.h
index a7a2822bf6a14a6..eb3c28693a50623 100644
--- a/libc/src/__support/macros/properties/compiler.h
+++ b/libc/src/__support/macros/properties/compiler.h
@@ -21,4 +21,23 @@
 #define LIBC_COMPILER_IS_MSC
 #endif
 
+// Check compiler features
+#if defined(FLT128_MANT_DIG)
+// C23 _Float128 type is available.
+#define LIBC_COMPILER_HAS_FLOAT128
+#define LIBC_FLOAT128_IS_C23
+using float128 = _Float128;
+
+#elif defined(__SIZEOF_FLOAT128__)
+// Builtin __float128 is available.
+#define LIBC_COMPILER_HAS_FLOAT128
+#define LIBC_FLOAT128_IS_BUILTIN
+using float128 = __float128;
+
+#endif
+
+#if defined(FLT16_MANT_DIG)
+#define LIBC_COMPILER_HAS_FLOAT16
+#endif
+
 #endif // LLVM_LIBC_SRC___SUPPORT_MACROS_PROPERTIES_COMPILER_H
diff --git a/libc/src/math/CMakeLists.txt b/libc/src/math/CMakeLists.txt
index f1f72714981a9e5..4aea54c7a457547 100644
--- a/libc/src/math/CMakeLists.txt
+++ b/libc/src/math/CMakeLists.txt
@@ -80,6 +80,7 @@ add_math_entrypoint_object(ceill)
 add_math_entrypoint_object(copysign)
 add_math_entrypoint_object(copysignf)
 add_math_entrypoint_object(copysignl)
+add_math_entrypoint_object(copysignf128)
 
 add_math_entrypoint_object(cos)
 add_math_entrypoint_object(cosf)
diff --git a/libc/src/math/copysignf128.h b/libc/src/math/copysignf128.h
new file mode 100644
index 000000000000000..9448d8205dd7523
--- /dev/null
+++ b/libc/src/math/copysignf128.h
@@ -0,0 +1,20 @@
+//===-- Implementation header for copysignf128 ------------------*- 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_COPYSIGNF128_H
+#define LLVM_LIBC_SRC_MATH_COPYSIGNF128_H
+
+#include "src/__support/macros/properties/compiler.h"
+
+namespace LIBC_NAMESPACE {
+
+float128 copysignf128(float128 x, float128 y);
+
+} // namespace LIBC_NAMESPACE
+
+#endif // LLVM_LIBC_SRC_MATH_COPYSIGN_H
diff --git a/libc/src/math/generic/CMakeLists.txt b/libc/src/math/generic/CMakeLists.txt
index 693887c165ce98c..7ac365f55bb6f83 100644
--- a/libc/src/math/generic/CMakeLists.txt
+++ b/libc/src/math/generic/CMakeLists.txt
@@ -806,7 +806,7 @@ add_entrypoint_object(
   DEPENDS
     libc.src.__support.FPUtil.manipulation_functions
   COMPILE_OPTIONS
-    -O2
+    -O3
 )
 
 add_entrypoint_object(
@@ -818,7 +818,7 @@ add_entrypoint_object(
   DEPENDS
     libc.src.__support.FPUtil.manipulation_functions
   COMPILE_OPTIONS
-    -O2
+    -O3
 )
 
 add_entrypoint_object(
@@ -830,7 +830,19 @@ add_entrypoint_object(
   DEPENDS
     libc.src.__support.FPUtil.manipulation_functions
   COMPILE_OPTIONS
-    -O2
+    -O3
+)
+
+add_entrypoint_object(
+  copysignf128
+  SRCS
+    copysignf128.cpp
+  HDRS
+    ../copysignf128.h
+  DEPENDS
+    libc.src.__support.FPUtil.manipulation_functions
+  COMPILE_OPTIONS
+    -O3
 )
 
 add_entrypoint_object(
diff --git a/libc/src/math/generic/copysignf128.cpp b/libc/src/math/generic/copysignf128.cpp
new file mode 100644
index 000000000000000..07e5caa223a5345
--- /dev/null
+++ b/libc/src/math/generic/copysignf128.cpp
@@ -0,0 +1,20 @@
+//===-- Implementation of copysignf128 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/copysignf128.h"
+#include "src/__support/FPUtil/ManipulationFunctions.h"
+#include "src/__support/common.h"
+#include "src/__support/macros/properties/compiler.h"
+
+namespace LIBC_NAMESPACE {
+
+LLVM_LIBC_FUNCTION(float128, copysignf128, (float128 x, float128 y)) {
+  return fputil::copysign(x, y);
+}
+
+} // namespace LIBC_NAMESPACE
diff --git a/libc/test/src/__support/FPUtil/fpbits_test.cpp b/libc/test/src/__support/FPUtil/fpbits_test.cpp
index 5c97ba3a70ca795..027db8807ab226a 100644
--- a/libc/test/src/__support/FPUtil/fpbits_test.cpp
+++ b/libc/test/src/__support/FPUtil/fpbits_test.cpp
@@ -287,3 +287,75 @@ TEST(LlvmLibcFPBitsTest, LongDoubleType) {
 #endif
 }
 #endif
+
+#if defined(LIBC_COMPILER_HAS_FLOAT128)
+TEST(LlvmLibcFPBitsTest, Float128Type) {
+  using Float128Bits = FPBits<float128>;
+
+  EXPECT_STREQ(LIBC_NAMESPACE::str(Float128Bits(Float128Bits::inf())).c_str(),
+               "(+Infinity)");
+  EXPECT_STREQ(
+      LIBC_NAMESPACE::str(Float128Bits(Float128Bits::neg_inf())).c_str(),
+      "(-Infinity)");
+  EXPECT_STREQ(
+      LIBC_NAMESPACE::str(Float128Bits(Float128Bits::build_nan(1))).c_str(),
+      "(NaN)");
+
+  Float128Bits zero(Float128Bits::zero());
+  EXPECT_EQ(zero.get_sign(), false);
+  EXPECT_EQ(zero.get_unbiased_exponent(), static_cast<uint16_t>(0x0000));
+  EXPECT_EQ(zero.get_mantissa(), static_cast<UInt128>(0x0000000000000000)
+                                     << 64);
+  EXPECT_EQ(zero.uintval(), static_cast<UInt128>(0x0000000000000000) << 64);
+  EXPECT_STREQ(LIBC_NAMESPACE::str(zero).c_str(),
+               "0x00000000000000000000000000000000 = "
+               "(S: 0, E: 0x0000, M: 0x00000000000000000000000000000000)");
+
+  Float128Bits negzero(Float128Bits::neg_zero());
+  EXPECT_EQ(negzero.get_sign(), true);
+  EXPECT_EQ(negzero.get_unbiased_exponent(), static_cast<uint16_t>(0x0000));
+  EXPECT_EQ(negzero.get_mantissa(), static_cast<UInt128>(0x0000000000000000)
+                                        << 64);
+  EXPECT_EQ(negzero.uintval(), static_cast<UInt128>(0x1) << 127);
+  EXPECT_STREQ(LIBC_NAMESPACE::str(negzero).c_str(),
+               "0x80000000000000000000000000000000 = "
+               "(S: 1, E: 0x0000, M: 0x00000000000000000000000000000000)");
+
+  Float128Bits one(float128(1.0));
+  EXPECT_EQ(one.get_sign(), false);
+  EXPECT_EQ(one.get_unbiased_exponent(), static_cast<uint16_t>(0x3FFF));
+  EXPECT_EQ(one.get_mantissa(), static_cast<UInt128>(0x0000000000000000) << 64);
+  EXPECT_EQ(one.uintval(), static_cast<UInt128>(0x3FFF) << 112);
+  EXPECT_STREQ(LIBC_NAMESPACE::str(one).c_str(),
+               "0x3FFF0000000000000000000000000000 = "
+               "(S: 0, E: 0x3FFF, M: 0x00000000000000000000000000000000)");
+
+  Float128Bits negone(float128(-1.0));
+  EXPECT_EQ(negone.get_sign(), true);
+  EXPECT_EQ(negone.get_unbiased_exponent(), static_cast<uint16_t>(0x3FFF));
+  EXPECT_EQ(negone.get_mantissa(), static_cast<UInt128>(0x0000000000000000)
+                                       << 64);
+  EXPECT_EQ(negone.uintval(), static_cast<UInt128>(0xBFFF) << 112);
+  EXPECT_STREQ(LIBC_NAMESPACE::str(negone).c_str(),
+               "0xBFFF0000000000000000000000000000 = "
+               "(S: 1, E: 0x3FFF, M: 0x00000000000000000000000000000000)");
+
+  Float128Bits num(float128(1.125));
+  EXPECT_EQ(num.get_sign(), false);
+  EXPECT_EQ(num.get_unbiased_exponent(), static_cast<uint16_t>(0x3FFF));
+  EXPECT_EQ(num.get_mantissa(), static_cast<UInt128>(0x2) << 108);
+  EXPECT_EQ(num.uintval(), static_cast<UInt128>(0x3FFF2) << 108);
+  EXPECT_STREQ(LIBC_NAMESPACE::str(num).c_str(),
+               "0x3FFF2000000000000000000000000000 = "
+               "(S: 0, E: 0x3FFF, M: 0x00002000000000000000000000000000)");
+
+  Float128Bits negnum(float128(-1.125));
+  EXPECT_EQ(negnum.get_sign(), true);
+  EXPECT_EQ(negnum.get_unbiased_exponent(), static_cast<uint16_t>(0x3FFF));
+  EXPECT_EQ(negnum.get_mantissa(), static_cast<UInt128>(0x2) << 108);
+  EXPECT_EQ(negnum.uintval(), static_cast<UInt128>(0xBFFF2) << 108);
+  EXPECT_STREQ(LIBC_NAMESPACE::str(negnum).c_str(),
+               "0xBFFF2000000000000000000000000000 = "
+               "(S: 1, E: 0x3FFF, M: 0x00002000000000000000000000000000)");
+}
+#endif // LIBC_COMPILER_HAS_FLOAT128
diff --git a/libc/test/src/math/smoke/CMakeLists.txt b/libc/test/src/math/smoke/CMakeLists.txt
index 995dee7b0b54829..101bdac995355de 100644
--- a/libc/test/src/math/smoke/CMakeLists.txt
+++ b/libc/test/src/math/smoke/CMakeLists.txt
@@ -674,6 +674,22 @@ add_fp_unittest(
   UNIT_TEST_ONLY
 )
 
+add_fp_unittest(
+  copysignf128_test
+  SUITE
+    libc-math-smoke-tests
+  SRCS
+    copysignf128_test.cpp
+  HDRS
+    CopySignTest.h
+  DEPENDS
+    libc.include.math
+    libc.src.math.copysignf128
+    libc.src.__support.FPUtil.fp_bits
+  # FIXME: Currently fails on the GPU build.
+  UNIT_TEST_ONLY
+)
+
 add_fp_unittest(
   frexp_test
   SUITE
diff --git a/libc/test/src/math/smoke/CopySignTest.h b/libc/test/src/math/smoke/CopySignTest.h
index c33f78038a3cff9..5e748bb8fd8ed58 100644
--- a/libc/test/src/math/smoke/CopySignTest.h
+++ b/libc/test/src/math/smoke/CopySignTest.h
@@ -20,28 +20,29 @@ class CopySignTest : public LIBC_NAMESPACE::testing::Test {
   typedef T (*CopySignFunc)(T, T);
 
   void testSpecialNumbers(CopySignFunc func) {
-    EXPECT_FP_EQ(aNaN, func(aNaN, -1.0));
-    EXPECT_FP_EQ(aNaN, func(aNaN, 1.0));
+    EXPECT_FP_EQ(aNaN, func(aNaN, T(-1.0)));
+    EXPECT_FP_EQ(aNaN, func(aNaN, T(1.0)));
 
-    EXPECT_FP_EQ(neg_inf, func(inf, -1.0));
-    EXPECT_FP_EQ(inf, func(neg_inf, 1.0));
+    EXPECT_FP_EQ(neg_inf, func(inf, T(-1.0)));
+    EXPECT_FP_EQ(inf, func(neg_inf, T(1.0)));
 
-    EXPECT_FP_EQ(neg_zero, func(zero, -1.0));
-    EXPECT_FP_EQ(zero, func(neg_zero, 1.0));
+    EXPECT_FP_EQ(neg_zero, func(zero, T(-1.0)));
+    EXPECT_FP_EQ(zero, func(neg_zero, T(1.0)));
   }
 
   void testRange(CopySignFunc func) {
     constexpr UIntType COUNT = 100'000;
     constexpr UIntType STEP = UIntType(-1) / COUNT;
     for (UIntType i = 0, v = 0; i <= COUNT; ++i, v += STEP) {
-      T x = T(FPBits(v));
-      if (isnan(x) || isinf(x))
+      FPBits x_bits = FPBits(v);
+      T x = T(v);
+      if (x_bits.is_nan() || x_bits.is_inf())
         continue;
 
-      double res1 = func(x, -x);
+      T res1 = func(x, -x);
       ASSERT_FP_EQ(res1, -x);
 
-      double res2 = func(x, x);
+      T res2 = func(x, x);
       ASSERT_FP_EQ(res2, x);
     }
   }
diff --git a/libc/test/src/math/smoke/copysignf128_test.cpp b/libc/test/src/math/smoke/copysignf128_test.cpp
new file mode 100644
index 000000000000000..48b41deb71d53eb
--- /dev/null
+++ b/libc/test/src/math/smoke/copysignf128_test.cpp
@@ -0,0 +1,13 @@
+//===-- Unittests for copysignf128 ----------------------------------------===//
+//
+// 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 "CopySignTest.h"
+
+#include "src/math/copysignf128.h"
+
+LIST_COPYSIGN_TESTS(float128, LIBC_NAMESPACE::copysignf128)

Copy link
Contributor

@michaelrj-google michaelrj-google left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

overall LGTM, should we move the float16 stuff to its own PR?

@@ -245,6 +245,7 @@ option(LIBC_INCLUDE_DOCS "Build the libc documentation." ${LLVM_INCLUDE_DOCS})

include(CMakeParseArguments)
include(LLVMLibCCheckCpuFeatures)
include(check_compiler_features)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This name should match the case of the other cmake utilities

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed.

@lntue
Copy link
Contributor Author

lntue commented Nov 10, 2023

overall LGTM, should we move the float16 stuff to its own PR?

I removed float16 stuff to be added in a separate PR.

@lntue lntue merged commit 3f906f5 into llvm:main Nov 10, 2023
@lntue lntue deleted the roundf128 branch November 10, 2023 19:33
zahiraam pushed a commit to zahiraam/llvm-project that referenced this pull request Nov 20, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants