Skip to content

Commit

Permalink
[libc][math][c23] Add {f,d}mul{l,f128} and f16mul{,f,l,f128} C23 math…
Browse files Browse the repository at this point in the history
… functions

Part of llvm#93566.

Fixes llvm#94833.
  • Loading branch information
overmighty committed Jul 18, 2024
1 parent da0c8b2 commit 780bc8e
Show file tree
Hide file tree
Showing 49 changed files with 1,242 additions and 364 deletions.
4 changes: 4 additions & 0 deletions libc/config/linux/aarch64/entrypoints.txt
Original file line number Diff line number Diff line change
Expand Up @@ -357,6 +357,7 @@ set(TARGET_LIBM_ENTRYPOINTS
libc.src.math.cosf
libc.src.math.coshf
libc.src.math.cospif
libc.src.math.dmull
libc.src.math.erff
libc.src.math.exp
libc.src.math.exp10
Expand Down Expand Up @@ -411,6 +412,7 @@ set(TARGET_LIBM_ENTRYPOINTS
libc.src.math.fmodf
libc.src.math.fmodl
libc.src.math.fmul
libc.src.math.fmull
libc.src.math.frexp
libc.src.math.frexpf
libc.src.math.frexpl
Expand Down Expand Up @@ -531,6 +533,8 @@ if(LIBC_TYPES_HAS_FLOAT16)
libc.src.math.f16div
libc.src.math.f16divf
libc.src.math.f16fmaf
libc.src.math.f16mul
libc.src.math.f16mulf
libc.src.math.f16sqrt
libc.src.math.f16sqrtf
libc.src.math.f16sub
Expand Down
8 changes: 8 additions & 0 deletions libc/config/linux/x86_64/entrypoints.txt
Original file line number Diff line number Diff line change
Expand Up @@ -382,6 +382,7 @@ set(TARGET_LIBM_ENTRYPOINTS
libc.src.math.cosf
libc.src.math.coshf
libc.src.math.cospif
libc.src.math.dmull
libc.src.math.erff
libc.src.math.exp
libc.src.math.exp10
Expand Down Expand Up @@ -437,6 +438,7 @@ set(TARGET_LIBM_ENTRYPOINTS
libc.src.math.fmodf
libc.src.math.fmodl
libc.src.math.fmul
libc.src.math.fmull
libc.src.math.frexp
libc.src.math.frexpf
libc.src.math.frexpl
Expand Down Expand Up @@ -561,6 +563,9 @@ if(LIBC_TYPES_HAS_FLOAT16)
libc.src.math.f16fma
libc.src.math.f16fmaf
libc.src.math.f16fmal
libc.src.math.f16mul
libc.src.math.f16mulf
libc.src.math.f16mull
libc.src.math.f16sqrt
libc.src.math.f16sqrtf
libc.src.math.f16sqrtl
Expand Down Expand Up @@ -622,6 +627,7 @@ if(LIBC_TYPES_HAS_FLOAT16)
libc.src.math.f16addf128
libc.src.math.f16divf128
libc.src.math.f16fmaf128
libc.src.math.f16mulf128
libc.src.math.f16sqrtf128
libc.src.math.f16subf128
)
Expand All @@ -634,6 +640,7 @@ if(LIBC_TYPES_HAS_FLOAT128)
libc.src.math.canonicalizef128
libc.src.math.ceilf128
libc.src.math.copysignf128
libc.src.math.dmulf128
libc.src.math.fabsf128
libc.src.math.fdimf128
libc.src.math.floorf128
Expand All @@ -648,6 +655,7 @@ if(LIBC_TYPES_HAS_FLOAT128)
libc.src.math.fminimum_numf128
libc.src.math.fminimumf128
libc.src.math.fmodf128
libc.src.math.fmulf128
libc.src.math.frexpf128
libc.src.math.fromfpf128
libc.src.math.fromfpxf128
Expand Down
6 changes: 4 additions & 2 deletions libc/docs/math/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,7 @@ Basic Operations
+------------------+------------------+-----------------+------------------------+----------------------+------------------------+------------------------+----------------------------+
| dfma | N/A | N/A | | N/A | | 7.12.14.5 | F.10.11 |
+------------------+------------------+-----------------+------------------------+----------------------+------------------------+------------------------+----------------------------+
| dmul | N/A | N/A | | N/A | | 7.12.14.3 | F.10.11 |
| dmul | N/A | N/A | |check| | N/A | |check|\* | 7.12.14.3 | F.10.11 |
+------------------+------------------+-----------------+------------------------+----------------------+------------------------+------------------------+----------------------------+
| dsub | N/A | N/A | | N/A | | 7.12.14.2 | F.10.11 |
+------------------+------------------+-----------------+------------------------+----------------------+------------------------+------------------------+----------------------------+
Expand All @@ -130,6 +130,8 @@ Basic Operations
+------------------+------------------+-----------------+------------------------+----------------------+------------------------+------------------------+----------------------------+
| f16fma | |check|\* | |check|\* | |check|\* | N/A | |check| | 7.12.14.5 | F.10.11 |
+------------------+------------------+-----------------+------------------------+----------------------+------------------------+------------------------+----------------------------+
| f16mul | |check|\* | |check|\* | |check|\* | N/A | |check| | 7.12.14.5 | F.10.11 |
+------------------+------------------+-----------------+------------------------+----------------------+------------------------+------------------------+----------------------------+
| f16sub | |check|\* | |check|\* | |check|\* | N/A | |check| | 7.12.14.2 | F.10.11 |
+------------------+------------------+-----------------+------------------------+----------------------+------------------------+------------------------+----------------------------+
| fabs | |check| | |check| | |check| | |check| | |check| | 7.12.7.3 | F.10.4.3 |
Expand Down Expand Up @@ -166,7 +168,7 @@ Basic Operations
+------------------+------------------+-----------------+------------------------+----------------------+------------------------+------------------------+----------------------------+
| fmod | |check| | |check| | |check| | |check| | |check| | 7.12.10.1 | F.10.7.1 |
+------------------+------------------+-----------------+------------------------+----------------------+------------------------+------------------------+----------------------------+
| fmul | N/A | |check| | | N/A | | 7.12.14.3 | F.10.11 |
| fmul | N/A | |check| | |check| | N/A | |check|\* | 7.12.14.3 | F.10.11 |
+------------------+------------------+-----------------+------------------------+----------------------+------------------------+------------------------+----------------------------+
| frexp | |check| | |check| | |check| | |check| | |check| | 7.12.6.7 | F.10.3.7 |
+------------------+------------------+-----------------+------------------------+----------------------+------------------------+------------------------+----------------------------+
Expand Down
8 changes: 8 additions & 0 deletions libc/spec/llvm_libc_ext.td
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,14 @@ def LLVMLibcExt : StandardSpec<"llvm_libc_ext"> {
GuardedFunctionSpec<"f16subf", RetValSpec<Float16Type>, [ArgSpec<FloatType>, ArgSpec<FloatType>], "LIBC_TYPES_HAS_FLOAT16">,
GuardedFunctionSpec<"f16subl", RetValSpec<Float16Type>, [ArgSpec<LongDoubleType>, ArgSpec<LongDoubleType>], "LIBC_TYPES_HAS_FLOAT16">,

GuardedFunctionSpec<"fmulf128", RetValSpec<FloatType>, [ArgSpec<Float128Type>, ArgSpec<Float128Type>], "LIBC_TYPES_HAS_FLOAT128">,

GuardedFunctionSpec<"dmulf128", RetValSpec<DoubleType>, [ArgSpec<Float128Type>, ArgSpec<Float128Type>], "LIBC_TYPES_HAS_FLOAT128">,

GuardedFunctionSpec<"f16mul", RetValSpec<Float16Type>, [ArgSpec<DoubleType>, ArgSpec<DoubleType>], "LIBC_TYPES_HAS_FLOAT16">,
GuardedFunctionSpec<"f16mulf", RetValSpec<Float16Type>, [ArgSpec<FloatType>, ArgSpec<FloatType>], "LIBC_TYPES_HAS_FLOAT16">,
GuardedFunctionSpec<"f16mull", RetValSpec<Float16Type>, [ArgSpec<LongDoubleType>, ArgSpec<LongDoubleType>], "LIBC_TYPES_HAS_FLOAT16">,

GuardedFunctionSpec<"f16div", RetValSpec<Float16Type>, [ArgSpec<DoubleType>, ArgSpec<DoubleType>], "LIBC_TYPES_HAS_FLOAT16">,
GuardedFunctionSpec<"f16divf", RetValSpec<Float16Type>, [ArgSpec<FloatType>, ArgSpec<FloatType>], "LIBC_TYPES_HAS_FLOAT16">,
GuardedFunctionSpec<"f16divl", RetValSpec<Float16Type>, [ArgSpec<LongDoubleType>, ArgSpec<LongDoubleType>], "LIBC_TYPES_HAS_FLOAT16">,
Expand Down
9 changes: 7 additions & 2 deletions libc/spec/stdc.td
Original file line number Diff line number Diff line change
Expand Up @@ -475,8 +475,6 @@ def StdC : StandardSpec<"stdc"> {
GuardedFunctionSpec<"fminimum_mag_numf16", RetValSpec<Float16Type>, [ArgSpec<Float16Type>, ArgSpec<Float16Type>], "LIBC_TYPES_HAS_FLOAT16">,
GuardedFunctionSpec<"fminimum_mag_numf128", RetValSpec<Float128Type>, [ArgSpec<Float128Type>, ArgSpec<Float128Type>], "LIBC_TYPES_HAS_FLOAT128">,

FunctionSpec<"fmul", RetValSpec<FloatType>, [ArgSpec<DoubleType>, ArgSpec<DoubleType>]>,

FunctionSpec<"fma", RetValSpec<DoubleType>, [ArgSpec<DoubleType>, ArgSpec<DoubleType>, ArgSpec<DoubleType>]>,
FunctionSpec<"fmaf", RetValSpec<FloatType>, [ArgSpec<FloatType>, ArgSpec<FloatType>, ArgSpec<FloatType>]>,

Expand Down Expand Up @@ -733,6 +731,13 @@ def StdC : StandardSpec<"stdc"> {

GuardedFunctionSpec<"f16subf128", RetValSpec<Float16Type>, [ArgSpec<Float128Type>, ArgSpec<Float128Type>], "LIBC_TYPES_HAS_FLOAT16_AND_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>]>,

GuardedFunctionSpec<"f16mulf128", RetValSpec<Float16Type>, [ArgSpec<Float128Type>, ArgSpec<Float128Type>], "LIBC_TYPES_HAS_FLOAT16_AND_FLOAT128">,

GuardedFunctionSpec<"f16divf128", RetValSpec<Float16Type>, [ArgSpec<Float128Type>, ArgSpec<Float128Type>], "LIBC_TYPES_HAS_FLOAT16_AND_FLOAT128">,

GuardedFunctionSpec<"f16sqrtf128", RetValSpec<Float16Type>, [ArgSpec<Float128Type>], "LIBC_TYPES_HAS_FLOAT16_AND_FLOAT128">,
Expand Down
17 changes: 17 additions & 0 deletions libc/src/__support/FPUtil/generic/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -84,3 +84,20 @@ add_header_library(
libc.src.__support.macros.attributes
libc.src.__support.macros.optimization
)

add_header_library(
mul
HDRS
mul.h
DEPENDS
libc.hdr.errno_macros
libc.hdr.fenv_macros
libc.src.__support.CPP.bit
libc.src.__support.CPP.type_traits
libc.src.__support.FPUtil.basic_operations
libc.src.__support.FPUtil.fenv_impl
libc.src.__support.FPUtil.fp_bits
libc.src.__support.FPUtil.dyadic_float
libc.src.__support.macros.attributes
libc.src.__support.macros.optimization
)
120 changes: 120 additions & 0 deletions libc/src/__support/FPUtil/generic/mul.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
//===-- Division of IEEE 754 floating-point numbers -------------*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//

#ifndef LLVM_LIBC_SRC___SUPPORT_FPUTIL_GENERIC_MUL_H
#define LLVM_LIBC_SRC___SUPPORT_FPUTIL_GENERIC_MUL_H

#include "hdr/errno_macros.h"
#include "hdr/fenv_macros.h"
#include "src/__support/CPP/bit.h"
#include "src/__support/CPP/type_traits.h"
#include "src/__support/FPUtil/BasicOperations.h"
#include "src/__support/FPUtil/FEnvImpl.h"
#include "src/__support/FPUtil/FPBits.h"
#include "src/__support/FPUtil/dyadic_float.h"
#include "src/__support/macros/attributes.h"
#include "src/__support/macros/config.h"
#include "src/__support/macros/optimization.h"

namespace LIBC_NAMESPACE_DECL {
namespace fputil::generic {

template <typename OutType, typename InType>
LIBC_INLINE cpp::enable_if_t<cpp::is_floating_point_v<OutType> &&
cpp::is_floating_point_v<InType> &&
sizeof(OutType) <= sizeof(InType),
OutType>
mul(InType x, InType y) {
using OutFPBits = FPBits<OutType>;
using OutStorageType = typename OutFPBits::StorageType;
using InFPBits = FPBits<InType>;
using InStorageType = typename InFPBits::StorageType;
// The product of two p-digit numbers is a 2p-digit number.
using DyadicFloat = DyadicFloat<cpp::bit_ceil(
2 * static_cast<size_t>(InFPBits::FRACTION_LEN))>;
using DyadicMantissaType = typename DyadicFloat::MantissaType;

InFPBits x_bits(x);
InFPBits y_bits(y);

Sign result_sign = x_bits.sign() == y_bits.sign() ? Sign::POS : Sign::NEG;

if (LIBC_UNLIKELY(x_bits.is_inf_or_nan() || y_bits.is_inf_or_nan() ||
x_bits.is_zero() || y_bits.is_zero())) {
if (x_bits.is_nan() || y_bits.is_nan()) {
if (x_bits.is_signaling_nan() || y_bits.is_signaling_nan())
raise_except_if_required(FE_INVALID);

if (x_bits.is_quiet_nan()) {
InStorageType x_payload = static_cast<InStorageType>(getpayload(x));
if ((x_payload & ~(OutFPBits::FRACTION_MASK >> 1)) == 0)
return OutFPBits::quiet_nan(x_bits.sign(),
static_cast<OutStorageType>(x_payload))
.get_val();
}

if (y_bits.is_quiet_nan()) {
InStorageType y_payload = static_cast<InStorageType>(getpayload(y));
if ((y_payload & ~(OutFPBits::FRACTION_MASK >> 1)) == 0)
return OutFPBits::quiet_nan(y_bits.sign(),
static_cast<OutStorageType>(y_payload))
.get_val();
}

return OutFPBits::quiet_nan().get_val();
}

if (x_bits.is_inf()) {
if (y_bits.is_zero()) {
set_errno_if_required(EDOM);
raise_except_if_required(FE_INVALID);
return OutFPBits::quiet_nan().get_val();
}

return OutFPBits::inf(result_sign).get_val();
}

if (y_bits.is_inf()) {
if (x_bits.is_zero()) {
set_errno_if_required(EDOM);
raise_except_if_required(FE_INVALID);
return OutFPBits::quiet_nan().get_val();
}

return OutFPBits::inf(result_sign).get_val();
}

// Now either x or y is zero, and the other one is finite.
return OutFPBits::zero(result_sign).get_val();
}

DyadicFloat xd(x);
DyadicFloat yd(y);

// The product is either in the [2, 4) range or the [1, 2) range. We initially
// set the exponent as if the product were in the [2, 4) range. If the product
// is in the [1, 2) range, then it has 1 leading zero bit and the DyadicFloat
// constructor will normalize it and adjust the exponent.
int result_exp = xd.get_unbiased_exponent() + yd.get_unbiased_exponent() + 1 -
DyadicMantissaType::BITS + 1;

// We use a single DyadicFloat type, which can fit the 2p-digit product, for
// both the normalized inputs and the product. So we need to right-shift the
// normalized input mantissas before multiplying them.
xd.shift_right(DyadicMantissaType::BITS / 2);
yd.shift_right(DyadicMantissaType::BITS / 2);
DyadicMantissaType product = xd.mantissa * yd.mantissa;

DyadicFloat result(result_sign, result_exp, product);
return result.template as<OutType, /*ShouldSignalExceptions=*/true>();
}

} // namespace fputil::generic
} // namespace LIBC_NAMESPACE_DECL

#endif // LLVM_LIBC_SRC___SUPPORT_FPUTIL_GENERIC_MUL_H
10 changes: 10 additions & 0 deletions libc/src/math/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,9 @@ add_math_entrypoint_object(cosh)
add_math_entrypoint_object(coshf)
add_math_entrypoint_object(cospif)

add_math_entrypoint_object(dmull)
add_math_entrypoint_object(dmulf128)

add_math_entrypoint_object(erf)
add_math_entrypoint_object(erff)

Expand Down Expand Up @@ -118,6 +121,11 @@ add_math_entrypoint_object(f16fmaf)
add_math_entrypoint_object(f16fmal)
add_math_entrypoint_object(f16fmaf128)

add_math_entrypoint_object(f16mul)
add_math_entrypoint_object(f16mulf)
add_math_entrypoint_object(f16mull)
add_math_entrypoint_object(f16mulf128)

add_math_entrypoint_object(f16sqrt)
add_math_entrypoint_object(f16sqrtf)
add_math_entrypoint_object(f16sqrtl)
Expand Down Expand Up @@ -210,6 +218,8 @@ add_math_entrypoint_object(fminimum_mag_numf16)
add_math_entrypoint_object(fminimum_mag_numf128)

add_math_entrypoint_object(fmul)
add_math_entrypoint_object(fmull)
add_math_entrypoint_object(fmulf128)

add_math_entrypoint_object(fmod)
add_math_entrypoint_object(fmodf)
Expand Down
21 changes: 21 additions & 0 deletions libc/src/math/dmulf128.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
//===-- Implementation header for dmulf128 ----------------------*- 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_DMULF128_H
#define LLVM_LIBC_SRC_MATH_DMULF128_H

#include "src/__support/macros/config.h"
#include "src/__support/macros/properties/types.h"

namespace LIBC_NAMESPACE_DECL {

double dmulf128(float128 x, float128 y);

} // namespace LIBC_NAMESPACE_DECL

#endif // LLVM_LIBC_SRC_MATH_DMULF128_H
20 changes: 20 additions & 0 deletions libc/src/math/dmull.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
//===-- 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

#include "src/__support/macros/config.h"

namespace LIBC_NAMESPACE_DECL {

double dmull(long double x, long double y);

} // namespace LIBC_NAMESPACE_DECL

#endif // LLVM_LIBC_SRC_MATH_DMULL_H
21 changes: 21 additions & 0 deletions libc/src/math/f16mul.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
//===-- Implementation header for f16mul ------------------------*- 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_F16MUL_H
#define LLVM_LIBC_SRC_MATH_F16MUL_H

#include "src/__support/macros/config.h"
#include "src/__support/macros/properties/types.h"

namespace LIBC_NAMESPACE_DECL {

float16 f16mul(double x, double y);

} // namespace LIBC_NAMESPACE_DECL

#endif // LLVM_LIBC_SRC_MATH_F16MUL_H
21 changes: 21 additions & 0 deletions libc/src/math/f16mulf.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
//===-- Implementation header for f16mulf -----------------------*- 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_F16MULF_H
#define LLVM_LIBC_SRC_MATH_F16MULF_H

#include "src/__support/macros/config.h"
#include "src/__support/macros/properties/types.h"

namespace LIBC_NAMESPACE_DECL {

float16 f16mulf(float x, float y);

} // namespace LIBC_NAMESPACE_DECL

#endif // LLVM_LIBC_SRC_MATH_F16MULF_H
Loading

0 comments on commit 780bc8e

Please sign in to comment.