Skip to content
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

[libc][math][c23] fmul correcly rounded to all rounding modes #91537

Merged
merged 44 commits into from
Jun 8, 2024

Conversation

Jobhdez
Copy link
Contributor

@Jobhdez Jobhdez commented May 8, 2024

This is an implementation of floating point multiplication:

It will consist of

  • double x double -> float

Thanks

@llvmbot llvmbot added the libc label May 8, 2024
@llvmbot
Copy link
Collaborator

llvmbot commented May 8, 2024

@llvm/pr-subscribers-libc

Author: Job Henandez Lara (Jobhdez)

Changes

Hello, after a conversation with Tue, he suggested to setup all the config. I will start working on the correct implementation asap.

I built llvm and ran the test so the config works.

Thanks


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

20 Files Affected:

  • (modified) libc/config/linux/aarch64/entrypoints.txt (+3)
  • (modified) libc/config/linux/arm/entrypoints.txt (+3)
  • (modified) libc/config/linux/riscv/entrypoints.txt (+3)
  • (modified) libc/config/linux/x86_64/entrypoints.txt (+3)
  • (modified) libc/config/windows/entrypoints.txt (+3)
  • (modified) libc/spec/stdc.td (+5)
  • (modified) libc/src/__support/FPUtil/BasicOperations.h (+10)
  • (modified) libc/src/math/CMakeLists.txt (+4)
  • (added) libc/src/math/dmull.h (+18)
  • (added) libc/src/math/fmul.h (+18)
  • (added) libc/src/math/fmull.h (+18)
  • (modified) libc/src/math/generic/CMakeLists.txt (+36)
  • (added) libc/src/math/generic/dmull.cpp (+19)
  • (added) libc/src/math/generic/fmul.cpp (+19)
  • (added) libc/src/math/generic/fmull.cpp (+19)
  • (modified) libc/test/src/math/smoke/CMakeLists.txt (+39-1)
  • (added) libc/test/src/math/smoke/FMulTest.h (+29)
  • (added) libc/test/src/math/smoke/dmull_test.cpp (+13)
  • (added) libc/test/src/math/smoke/fmul_test.cpp (+13)
  • (added) libc/test/src/math/smoke/fmull_test.cpp (+13)
diff --git a/libc/config/linux/aarch64/entrypoints.txt b/libc/config/linux/aarch64/entrypoints.txt
index ad50b6f59cdcc..c92d238f14f7d 100644
--- a/libc/config/linux/aarch64/entrypoints.txt
+++ b/libc/config/linux/aarch64/entrypoints.txt
@@ -394,6 +394,9 @@ set(TARGET_LIBM_ENTRYPOINTS
     libc.src.math.fminimum_mag_num
     libc.src.math.fminimum_mag_numf
     libc.src.math.fminimum_mag_numl
+    libc.src.math.fmul
+    libc.src.math.fmull
+    libc.src.math.dmull
     libc.src.math.fmod
     libc.src.math.fmodf
     libc.src.math.fmodl
diff --git a/libc/config/linux/arm/entrypoints.txt b/libc/config/linux/arm/entrypoints.txt
index 335981ff7dc7c..c3bb9bf666764 100644
--- a/libc/config/linux/arm/entrypoints.txt
+++ b/libc/config/linux/arm/entrypoints.txt
@@ -261,6 +261,9 @@ set(TARGET_LIBM_ENTRYPOINTS
     libc.src.math.fminimum_mag_num
     libc.src.math.fminimum_mag_numf
     libc.src.math.fminimum_mag_numl
+    libc.src.math.fmul
+    libc.src.math.fmull
+    libc.src.math.dmull
     libc.src.math.fmod
     libc.src.math.fmodf
     libc.src.math.frexp
diff --git a/libc/config/linux/riscv/entrypoints.txt b/libc/config/linux/riscv/entrypoints.txt
index 479af40b5b26b..8b4744445ae01 100644
--- a/libc/config/linux/riscv/entrypoints.txt
+++ b/libc/config/linux/riscv/entrypoints.txt
@@ -402,6 +402,9 @@ set(TARGET_LIBM_ENTRYPOINTS
     libc.src.math.fminimum_mag_num
     libc.src.math.fminimum_mag_numf
     libc.src.math.fminimum_mag_numl
+    libc.src.math.fmul
+    libc.src.math.fmull
+    libc.src.math.dmull
     libc.src.math.fmod
     libc.src.math.fmodf
     libc.src.math.fmodl
diff --git a/libc/config/linux/x86_64/entrypoints.txt b/libc/config/linux/x86_64/entrypoints.txt
index 5e3ddd34fb4dc..9623f0b967c40 100644
--- a/libc/config/linux/x86_64/entrypoints.txt
+++ b/libc/config/linux/x86_64/entrypoints.txt
@@ -421,6 +421,9 @@ set(TARGET_LIBM_ENTRYPOINTS
     libc.src.math.fminimum_mag_num
     libc.src.math.fminimum_mag_numf
     libc.src.math.fminimum_mag_numl
+    libc.src.math.fmul
+    libc.src.math.fmull
+    libc.src.math.dmull
     libc.src.math.fmod
     libc.src.math.fmodf
     libc.src.math.fmodl
diff --git a/libc/config/windows/entrypoints.txt b/libc/config/windows/entrypoints.txt
index 71216530c4041..199ce9bc91cd9 100644
--- a/libc/config/windows/entrypoints.txt
+++ b/libc/config/windows/entrypoints.txt
@@ -180,6 +180,9 @@ set(TARGET_LIBM_ENTRYPOINTS
     libc.src.math.fminimum_mag_num
     libc.src.math.fminimum_mag_numf
     libc.src.math.fminimum_mag_numl
+    libc.src.math.fmul
+    libc.src.math.fmull
+    libc.src.math.dmull
     libc.src.math.fmod
     libc.src.math.fmodf
     libc.src.math.fmodl
diff --git a/libc/spec/stdc.td b/libc/spec/stdc.td
index eb67c9b0b009b..0130ace283a55 100644
--- a/libc/spec/stdc.td
+++ b/libc/spec/stdc.td
@@ -457,6 +457,11 @@ def StdC : StandardSpec<"stdc"> {
           FunctionSpec<"fminimum_mag_numl", RetValSpec<LongDoubleType>, [ArgSpec<LongDoubleType>, ArgSpec<LongDoubleType>]>,
           GuardedFunctionSpec<"fminimum_mag_numf128", RetValSpec<Float128Type>, [ArgSpec<Float128Type>, ArgSpec<Float128Type>], "LIBC_TYPES_HAS_FLOAT128">,
 
+          FunctionSpec<"fmul", RetValSpec<FloatType>, [ArgSpec<DoubleType>, ArgSpec<DoubleType>]>,
+	  FunctionSpec<"fmull", RetValSpec<FloatType>, [ArgSpec<LongDoubleType>, ArgSpec<LongDoubleType>]>,
+	  FunctionSpec<"dmull", RetValSpec<DoubleType>, [ArgSpec<LongDoubleType>, ArgSpec<LongDoubleType>]>,
+	    
+
           FunctionSpec<"fma", RetValSpec<DoubleType>, [ArgSpec<DoubleType>, ArgSpec<DoubleType>, ArgSpec<DoubleType>]>,
           FunctionSpec<"fmaf", RetValSpec<FloatType>, [ArgSpec<FloatType>, ArgSpec<FloatType>, ArgSpec<FloatType>]>,
 
diff --git a/libc/src/__support/FPUtil/BasicOperations.h b/libc/src/__support/FPUtil/BasicOperations.h
index e5ac101fedc0e..e3581910e9799 100644
--- a/libc/src/__support/FPUtil/BasicOperations.h
+++ b/libc/src/__support/FPUtil/BasicOperations.h
@@ -177,6 +177,16 @@ LIBC_INLINE T fdim(T x, T y) {
   return (x > y ? x - y : 0);
 }
 
+LIBC_INLINE float fmul(double x, double y) { return static_cast<float>(x * y); }
+
+LIBC_INLINE float fmull(long double x, long double y) {
+  return static_cast<float>(x * y);
+}
+
+LIBC_INLINE double dmull(long double x, long double y) {
+  return static_cast<double>(x * y);
+}
+
 template <typename T, cpp::enable_if_t<cpp::is_floating_point_v<T>, int> = 0>
 LIBC_INLINE int canonicalize(T &cx, const T &x) {
   FPBits<T> sx(x);
diff --git a/libc/src/math/CMakeLists.txt b/libc/src/math/CMakeLists.txt
index c34c58575441d..dd26109d9db4d 100644
--- a/libc/src/math/CMakeLists.txt
+++ b/libc/src/math/CMakeLists.txt
@@ -164,6 +164,10 @@ add_math_entrypoint_object(fminimum_mag_numf)
 add_math_entrypoint_object(fminimum_mag_numl)
 add_math_entrypoint_object(fminimum_mag_numf128)
 
+add_math_entrypoint_object(fmul)
+add_math_entrypoint_object(fmull)
+add_math_entrypoint_object(dmull)
+
 add_math_entrypoint_object(fmod)
 add_math_entrypoint_object(fmodf)
 add_math_entrypoint_object(fmodl)
diff --git a/libc/src/math/dmull.h b/libc/src/math/dmull.h
new file mode 100644
index 0000000000000..556eb1559d535
--- /dev/null
+++ b/libc/src/math/dmull.h
@@ -0,0 +1,18 @@
+//===-- Implementation header for dmull -------------------------*- 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_DMULL_H
+#define LLVM_LIBC_SRC_MATH_DMULL_H
+
+namespace LIBC_NAMESPACE {
+
+double dmull(long double x, long double y);
+
+} // namespace LIBC_NAMESPACE
+
+#endif // LLVM_LIBC_SRC_MATH_DMULL_H
diff --git a/libc/src/math/fmul.h b/libc/src/math/fmul.h
new file mode 100644
index 0000000000000..fbc1069db733e
--- /dev/null
+++ b/libc/src/math/fmul.h
@@ -0,0 +1,18 @@
+//===-- Implementation header for fmul --------------------------*- 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_FMUL_H
+#define LLVM_LIBC_SRC_MATH_FMUL_H
+
+namespace LIBC_NAMESPACE {
+
+float fmul(double x, double y);
+
+} // namespace LIBC_NAMESPACE
+
+#endif // LLVM_LIBC_SRC_MATH_FMUL_H
diff --git a/libc/src/math/fmull.h b/libc/src/math/fmull.h
new file mode 100644
index 0000000000000..aebf52a9b0c0a
--- /dev/null
+++ b/libc/src/math/fmull.h
@@ -0,0 +1,18 @@
+//===-- Implementation header for fmull -------------------------*- 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_FMULL_H
+#define LLVM_LIBC_SRC_MATH_FMULL_H
+
+namespace LIBC_NAMESPACE {
+
+float fmull(long double x, long double y);
+
+} // namespace LIBC_NAMESPACE
+
+#endif // LLVM_LIBC_SRC_MATH_FMULL_H
diff --git a/libc/src/math/generic/CMakeLists.txt b/libc/src/math/generic/CMakeLists.txt
index daaf505008ca1..3554ec088c49f 100644
--- a/libc/src/math/generic/CMakeLists.txt
+++ b/libc/src/math/generic/CMakeLists.txt
@@ -2042,6 +2042,42 @@ add_entrypoint_object(
     -O3
 )
 
+add_entrypoint_object(
+  fmul
+  SRCS
+    fmul.cpp
+  HDRS
+    ../fmul.h
+  DEPENDS
+    libc.src.__support.FPUtil.basic_operations
+  COMPILE_OPTIONS
+    -O2
+)
+
+add_entrypoint_object(
+  fmull
+  SRCS
+    fmull.cpp
+  HDRS
+    ../fmull.h
+  DEPENDS
+    libc.src.__support.FPUtil.basic_operations
+  COMPILE_OPTIONS
+    -O2
+)
+
+add_entrypoint_object(
+  dmull
+  SRCS
+    dmull.cpp
+  HDRS
+    ../dmull.h
+  DEPENDS
+    libc.src.__support.FPUtil.basic_operations
+  COMPILE_OPTIONS
+    -O2
+)
+
 add_entrypoint_object(
   sqrt
   SRCS
diff --git a/libc/src/math/generic/dmull.cpp b/libc/src/math/generic/dmull.cpp
new file mode 100644
index 0000000000000..2c70841dc2d28
--- /dev/null
+++ b/libc/src/math/generic/dmull.cpp
@@ -0,0 +1,19 @@
+//===-- Implementation of dmull 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/dmull.h"
+#include "src/__support/FPUtil/BasicOperations.h"
+#include "src/__support/common.h"
+
+namespace LIBC_NAMESPACE {
+
+LLVM_LIBC_FUNCTION(double, dmull, (long double x, long double y)) {
+  return fputil::dmull(x, y);
+}
+
+} // namespace LIBC_NAMESPACE
diff --git a/libc/src/math/generic/fmul.cpp b/libc/src/math/generic/fmul.cpp
new file mode 100644
index 0000000000000..77452013951d7
--- /dev/null
+++ b/libc/src/math/generic/fmul.cpp
@@ -0,0 +1,19 @@
+//===-- Implementation of fmul 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/fmul.h"
+#include "src/__support/FPUtil/BasicOperations.h"
+#include "src/__support/common.h"
+
+namespace LIBC_NAMESPACE {
+
+LLVM_LIBC_FUNCTION(float, fmul, (double x, double y)) {
+  return fputil::fmul(x, y);
+}
+
+} // namespace LIBC_NAMESPACE
diff --git a/libc/src/math/generic/fmull.cpp b/libc/src/math/generic/fmull.cpp
new file mode 100644
index 0000000000000..f0d0e0d8da22a
--- /dev/null
+++ b/libc/src/math/generic/fmull.cpp
@@ -0,0 +1,19 @@
+//===-- Implementation of fmull 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/fmull.h"
+#include "src/__support/FPUtil/BasicOperations.h"
+#include "src/__support/common.h"
+
+namespace LIBC_NAMESPACE {
+
+LLVM_LIBC_FUNCTION(float, fmull, (long double x, long double y)) {
+  return fputil::fmull(x, y);
+}
+
+} // namespace LIBC_NAMESPACE
diff --git a/libc/test/src/math/smoke/CMakeLists.txt b/libc/test/src/math/smoke/CMakeLists.txt
index 112b2985829ca..30e6a3cb98184 100644
--- a/libc/test/src/math/smoke/CMakeLists.txt
+++ b/libc/test/src/math/smoke/CMakeLists.txt
@@ -1911,7 +1911,6 @@ add_fp_unittest(
     libc.src.__support.FPUtil.fp_bits
 )
 
-
 add_fp_unittest(
   fminimum_mag_numf_test
   SUITE
@@ -1964,6 +1963,45 @@ add_fp_unittest(
     libc.src.__support.FPUtil.fp_bits
 )
 
+add_fp_unittest(
+  fmul_test
+  SUITE
+    libc-math-smoke-tests
+  SRCS
+    fmul_test.cpp
+  HDRS
+    FMulTest.h
+  DEPENDS
+    libc.src.math.fmul
+    libc.src.__support.FPUtil.fp_bits
+)
+
+add_fp_unittest(
+  fmull_test
+  SUITE
+    libc-math-smoke-tests
+  SRCS
+    fmull_test.cpp
+  HDRS
+    FMulTest.h
+  DEPENDS
+    libc.src.math.fmull
+    libc.src.__support.FPUtil.fp_bits
+)
+
+add_fp_unittest(
+  dmull_test
+  SUITE
+    libc-math-smoke-tests
+  SRCS
+    dmull_test.cpp
+  HDRS
+    FMulTest.h
+  DEPENDS
+    libc.src.math.dmull
+    libc.src.__support.FPUtil.fp_bits
+)
+
 add_fp_unittest(
   sqrtf_test
   SUITE
diff --git a/libc/test/src/math/smoke/FMulTest.h b/libc/test/src/math/smoke/FMulTest.h
new file mode 100644
index 0000000000000..412d9eedf1f7c
--- /dev/null
+++ b/libc/test/src/math/smoke/FMulTest.h
@@ -0,0 +1,29 @@
+//===-- Utility class to test fmul[f|l] ---------------------*- 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_TEST_SRC_MATH_SMOKE_FMULTEST_H
+#define LLVM_LIBC_TEST_SRC_MATH_SMOKE_FMULTEST_H
+
+#include "test/UnitTest/FEnvSafeTest.h"
+#include "test/UnitTest/FPMatcher.h"
+#include "test/UnitTest/Test.h"
+
+template <typename T, typename R>
+class FmulTest : public LIBC_NAMESPACE::testing::FEnvSafeTest {
+
+public:
+  typedef T (*FMulFunc)(R, R);
+
+  void testMul(FMulFunc func) { EXPECT_FP_EQ(T(1.0), func(1.0, 1.0)); }
+};
+
+#define LIST_FMUL_TESTS(T, R, func)                                            \
+  using LlvmLibcFmulTest = FmulTest<T, R>;                                     \
+  TEST_F(LlvmLibcFmulTest, Mul) { testMul(&func); }
+
+#endif // LLVM_LIBC_TEST_SRC_MATH_SMOKE_FMULTEST_H
diff --git a/libc/test/src/math/smoke/dmull_test.cpp b/libc/test/src/math/smoke/dmull_test.cpp
new file mode 100644
index 0000000000000..f094b2578158f
--- /dev/null
+++ b/libc/test/src/math/smoke/dmull_test.cpp
@@ -0,0 +1,13 @@
+//===-- Unittests for dmull------------------------------------------------===//
+//
+// 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 "FMulTest.h"
+
+#include "src/math/dmull.h"
+
+LIST_FMUL_TESTS(double, long double, LIBC_NAMESPACE::dmull)
diff --git a/libc/test/src/math/smoke/fmul_test.cpp b/libc/test/src/math/smoke/fmul_test.cpp
new file mode 100644
index 0000000000000..0eb664f7411ee
--- /dev/null
+++ b/libc/test/src/math/smoke/fmul_test.cpp
@@ -0,0 +1,13 @@
+//===-- Unittests for fmul-------------------------------------------------===//
+//
+// 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 "FMulTest.h"
+
+#include "src/math/fmul.h"
+
+LIST_FMUL_TESTS(float, double, LIBC_NAMESPACE::fmul)
diff --git a/libc/test/src/math/smoke/fmull_test.cpp b/libc/test/src/math/smoke/fmull_test.cpp
new file mode 100644
index 0000000000000..d1151e298c0b6
--- /dev/null
+++ b/libc/test/src/math/smoke/fmull_test.cpp
@@ -0,0 +1,13 @@
+//===-- Unittests for fmull------------------------------------------------===//
+//
+// 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 "FMulTest.h"
+
+#include "src/math/fmull.h"
+
+LIST_FMUL_TESTS(float, long double, LIBC_NAMESPACE::fmull)

@Jobhdez Jobhdez marked this pull request as draft May 8, 2024 21:44
@lntue lntue self-requested a review May 9, 2024 02:55
@nickdesaulniers
Copy link
Member

Hi @Jobhdez thanks for the patch. Any updates here?

@Jobhdez
Copy link
Contributor Author

Jobhdez commented May 20, 2024

Hi @Jobhdez thanks for the patch. Any updates here?

Yeah I’m working on it. I was able to implement the function for double -> double -> float using only c++. Tue is going to go over the overflow stuff with me and I’m currently reading about overflow so when that’s done I’ll use llvm’s fpbits and implement the rest.

@nickdesaulniers heres the implementation of fmul: double -> double -> float. I have implemented the case when both are normals.
https://godbolt.org/z/zKza3EKP8

Copy link

github-actions bot commented Jun 1, 2024

✅ With the latest revision this PR passed the C/C++ code formatter.

@Jobhdez Jobhdez marked this pull request as ready for review June 1, 2024 16:33
int h_shift = 64 - g_shift;
m = (m_shift >= 64) ? 0 : static_cast<uint32_t>(highs >> m_shift);

g = g_shift >= 64 ? 0 : (highs >> ((39 + c) - dm1)) & 1;
Copy link
Contributor

Choose a reason for hiding this comment

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

highs >> g_shift

} else {
m = static_cast<uint32_t>(highs >> (39 + c));
g = (highs >> (38 + c)) & 1;
hight = (highs << (55 - c)) != 0;
Copy link
Contributor

Choose a reason for hiding this comment

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

this should be 64 - (38 + c) = 26 - c

@lntue lntue merged commit 263be9f into llvm:main Jun 8, 2024
7 checks passed
nekoshirro pushed a commit to nekoshirro/Alchemist-LLVM that referenced this pull request Jun 9, 2024
…1537)

This is an implementation of floating point multiplication:

It will consist of
   - `double x double -> float`

Signed-off-by: Hafidz Muzakky <ais.muzakky@gmail.com>
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.

None yet

4 participants