diff options
Diffstat (limited to 'libc/src')
24 files changed, 368 insertions, 42 deletions
diff --git a/libc/src/__support/FPUtil/CMakeLists.txt b/libc/src/__support/FPUtil/CMakeLists.txt index ea1e0e8b39d1..522b4afefd48 100644 --- a/libc/src/__support/FPUtil/CMakeLists.txt +++ b/libc/src/__support/FPUtil/CMakeLists.txt @@ -92,11 +92,14 @@ add_header_library( HDRS except_value_utils.h DEPENDS + .cast .fp_bits .fenv_impl .rounding_mode libc.src.__support.CPP.optional libc.src.__support.macros.optimization + libc.src.__support.macros.properties.cpu_features + libc.src.__support.macros.properties.types ) @@ -175,9 +178,13 @@ add_header_library( .fenv_impl .fp_bits .multiply_add + .rounding_mode + libc.hdr.errno_macros + libc.hdr.fenv_macros libc.src.__support.CPP.type_traits libc.src.__support.big_int libc.src.__support.macros.optimization + libc.src.__support.macros.properties.types ) add_header_library( @@ -217,18 +224,32 @@ add_header_library( HDRS ManipulationFunctions.h DEPENDS + .cast + .dyadic_float .fenv_impl .fp_bits - .dyadic_float .nearest_integer_operations .normal_float libc.hdr.math_macros + libc.src.errno.errno + libc.src.__support.common libc.src.__support.CPP.bit libc.src.__support.CPP.limits libc.src.__support.CPP.type_traits - libc.src.__support.common libc.src.__support.macros.optimization - libc.src.errno.errno +) + +add_header_library( + cast + HDRS + cast.h + DEPENDS + .dyadic_float + .fp_bits + libc.hdr.fenv_macros + libc.src.__support.CPP.algorithm + libc.src.__support.CPP.type_traits + libc.src.__support.macros.properties.types ) add_subdirectory(generic) diff --git a/libc/src/__support/FPUtil/ManipulationFunctions.h b/libc/src/__support/FPUtil/ManipulationFunctions.h index a14f35578999..66bfe2aa377f 100644 --- a/libc/src/__support/FPUtil/ManipulationFunctions.h +++ b/libc/src/__support/FPUtil/ManipulationFunctions.h @@ -12,6 +12,7 @@ #include "FPBits.h" #include "NearestIntegerOperations.h" #include "NormalFloat.h" +#include "cast.h" #include "dyadic_float.h" #include "rounding_mode.h" @@ -192,7 +193,8 @@ ldexp(T x, U exp) { // For all other values, NormalFloat to T conversion handles it the right way. DyadicFloat<FPBits<T>::STORAGE_LEN> normal(bits.get_val()); normal.exponent += static_cast<int>(exp); - return static_cast<T>(normal); + // TODO: Add tests for exceptions. + return normal.template as<T, /*ShouldRaiseExceptions=*/true>(); } template <typename T, typename U, @@ -207,17 +209,17 @@ LIBC_INLINE T nextafter(T from, U to) { FPBits<U> to_bits(to); if (to_bits.is_nan()) - return static_cast<T>(to); + return cast<T>(to); // NOTE: This would work only if `U` has a greater or equal precision than // `T`. Otherwise `from` could loose its precision and the following statement // could incorrectly evaluate to `true`. - if (static_cast<U>(from) == to) - return static_cast<T>(to); + if (cast<U>(from) == to) + return cast<T>(to); using StorageType = typename FPBits<T>::StorageType; if (from != T(0)) { - if ((static_cast<U>(from) < to) == (from > T(0))) { + if ((cast<U>(from) < to) == (from > T(0))) { from_bits = FPBits<T>(StorageType(from_bits.uintval() + 1)); } else { from_bits = FPBits<T>(StorageType(from_bits.uintval() - 1)); diff --git a/libc/src/__support/FPUtil/cast.h b/libc/src/__support/FPUtil/cast.h new file mode 100644 index 000000000000..126f3852137b --- /dev/null +++ b/libc/src/__support/FPUtil/cast.h @@ -0,0 +1,65 @@ +//===-- Conversion between floating-point types -----------------*- 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_CAST_H +#define LLVM_LIBC_SRC___SUPPORT_FPUTIL_CAST_H + +#include "FPBits.h" +#include "dyadic_float.h" +#include "hdr/fenv_macros.h" +#include "src/__support/CPP/algorithm.h" +#include "src/__support/CPP/type_traits.h" +#include "src/__support/macros/properties/types.h" + +namespace LIBC_NAMESPACE::fputil { + +template <typename OutType, typename InType> +LIBC_INLINE constexpr cpp::enable_if_t<cpp::is_floating_point_v<OutType> && + cpp::is_floating_point_v<InType>, + OutType> +cast(InType x) { +#if defined(LIBC_TYPES_HAS_FLOAT16) && !defined(__LIBC_USE_FLOAT16_CONVERSION) + if constexpr (cpp::is_same_v<OutType, float16> || + cpp::is_same_v<InType, float16>) { + using InFPBits = FPBits<InType>; + using InStorageType = typename InFPBits::StorageType; + using OutFPBits = FPBits<OutType>; + using OutStorageType = typename OutFPBits::StorageType; + + InFPBits x_bits(x); + + if (x_bits.is_nan()) { + if (x_bits.is_signaling_nan()) { + raise_except_if_required(FE_INVALID); + return OutFPBits::quiet_nan().get_val(); + } + + InStorageType x_mant = x_bits.get_mantissa(); + if (InFPBits::FRACTION_LEN > OutFPBits::FRACTION_LEN) + x_mant >>= InFPBits::FRACTION_LEN - OutFPBits::FRACTION_LEN; + return OutFPBits::quiet_nan(x_bits.sign(), + static_cast<OutStorageType>(x_mant)) + .get_val(); + } + + if (x_bits.is_inf()) + return OutFPBits::inf(x_bits.sign()).get_val(); + + constexpr size_t MAX_FRACTION_LEN = + cpp::max(OutFPBits::FRACTION_LEN, InFPBits::FRACTION_LEN); + DyadicFloat<cpp::bit_ceil(MAX_FRACTION_LEN)> xd(x); + return xd.template as<OutType, /*ShouldSignalExceptions=*/true>(); + } +#endif + + return static_cast<OutType>(x); +} + +} // namespace LIBC_NAMESPACE::fputil + +#endif // LLVM_LIBC_SRC___SUPPORT_FPUTIL_CAST_H diff --git a/libc/src/__support/FPUtil/dyadic_float.h b/libc/src/__support/FPUtil/dyadic_float.h index 86346a47b35a..165ffc7c9220 100644 --- a/libc/src/__support/FPUtil/dyadic_float.h +++ b/libc/src/__support/FPUtil/dyadic_float.h @@ -11,11 +11,15 @@ #include "FEnvImpl.h" #include "FPBits.h" +#include "hdr/errno_macros.h" +#include "hdr/fenv_macros.h" #include "multiply_add.h" +#include "rounding_mode.h" #include "src/__support/CPP/type_traits.h" #include "src/__support/big_int.h" #include "src/__support/macros/config.h" #include "src/__support/macros/optimization.h" // LIBC_UNLIKELY +#include "src/__support/macros/properties/types.h" #include <stddef.h> @@ -97,13 +101,120 @@ template <size_t Bits> struct DyadicFloat { return exponent + (Bits - 1); } - // Assume that it is already normalized. - // Output is rounded correctly with respect to the current rounding mode. +#ifdef LIBC_TYPES_HAS_FLOAT16 + template <typename T, bool ShouldSignalExceptions> + LIBC_INLINE constexpr cpp::enable_if_t< + cpp::is_floating_point_v<T> && (FPBits<T>::FRACTION_LEN < Bits), T> + generic_as() const { + using FPBits = FPBits<float16>; + using StorageType = typename FPBits::StorageType; + + constexpr int EXTRA_FRACTION_LEN = Bits - 1 - FPBits::FRACTION_LEN; + + if (mantissa == 0) + return FPBits::zero(sign).get_val(); + + int unbiased_exp = get_unbiased_exponent(); + + if (unbiased_exp + FPBits::EXP_BIAS >= FPBits::MAX_BIASED_EXPONENT) { + if constexpr (ShouldSignalExceptions) { + set_errno_if_required(ERANGE); + raise_except_if_required(FE_OVERFLOW | FE_INEXACT); + } + + switch (quick_get_round()) { + case FE_TONEAREST: + return FPBits::inf(sign).get_val(); + case FE_TOWARDZERO: + return FPBits::max_normal(sign).get_val(); + case FE_DOWNWARD: + if (sign.is_pos()) + return FPBits::max_normal(Sign::POS).get_val(); + return FPBits::inf(Sign::NEG).get_val(); + case FE_UPWARD: + if (sign.is_neg()) + return FPBits::max_normal(Sign::NEG).get_val(); + return FPBits::inf(Sign::POS).get_val(); + default: + __builtin_unreachable(); + } + } + + StorageType out_biased_exp = 0; + StorageType out_mantissa = 0; + bool round = false; + bool sticky = false; + bool underflow = false; + + if (unbiased_exp < -FPBits::EXP_BIAS - FPBits::FRACTION_LEN) { + sticky = true; + underflow = true; + } else if (unbiased_exp == -FPBits::EXP_BIAS - FPBits::FRACTION_LEN) { + round = true; + MantissaType sticky_mask = (MantissaType(1) << (Bits - 1)) - 1; + sticky = (mantissa & sticky_mask) != 0; + } else { + int extra_fraction_len = EXTRA_FRACTION_LEN; + + if (unbiased_exp < 1 - FPBits::EXP_BIAS) { + underflow = true; + extra_fraction_len += 1 - FPBits::EXP_BIAS - unbiased_exp; + } else { + out_biased_exp = + static_cast<StorageType>(unbiased_exp + FPBits::EXP_BIAS); + } + + MantissaType round_mask = MantissaType(1) << (extra_fraction_len - 1); + round = (mantissa & round_mask) != 0; + MantissaType sticky_mask = round_mask - 1; + sticky = (mantissa & sticky_mask) != 0; + + out_mantissa = static_cast<StorageType>(mantissa >> extra_fraction_len); + } + + bool lsb = (out_mantissa & 1) != 0; + + StorageType result = + FPBits::create_value(sign, out_biased_exp, out_mantissa).uintval(); + + switch (quick_get_round()) { + case FE_TONEAREST: + if (round && (lsb || sticky)) + ++result; + break; + case FE_DOWNWARD: + if (sign.is_neg() && (round || sticky)) + ++result; + break; + case FE_UPWARD: + if (sign.is_pos() && (round || sticky)) + ++result; + break; + default: + break; + } + + if (ShouldSignalExceptions && (round || sticky)) { + int excepts = FE_INEXACT; + if (FPBits(result).is_inf()) { + set_errno_if_required(ERANGE); + excepts |= FE_OVERFLOW; + } else if (underflow) { + set_errno_if_required(ERANGE); + excepts |= FE_UNDERFLOW; + } + raise_except_if_required(excepts); + } + + return FPBits(result).get_val(); + } +#endif // LIBC_TYPES_HAS_FLOAT16 + template <typename T, bool ShouldSignalExceptions, typename = cpp::enable_if_t<cpp::is_floating_point_v<T> && (FPBits<T>::FRACTION_LEN < Bits), void>> - LIBC_INLINE constexpr T as() const { + LIBC_INLINE constexpr T fast_as() const { if (LIBC_UNLIKELY(mantissa.is_zero())) return FPBits<T>::zero(sign).get_val(); @@ -224,6 +335,20 @@ template <size_t Bits> struct DyadicFloat { return r; } + // Assume that it is already normalized. + // Output is rounded correctly with respect to the current rounding mode. + template <typename T, bool ShouldSignalExceptions, + typename = cpp::enable_if_t<cpp::is_floating_point_v<T> && + (FPBits<T>::FRACTION_LEN < Bits), + void>> + LIBC_INLINE constexpr T as() const { +#if defined(LIBC_TYPES_HAS_FLOAT16) && !defined(__LIBC_USE_FLOAT16_CONVERSION) + if constexpr (cpp::is_same_v<T, float16>) + return generic_as<T, ShouldSignalExceptions>(); +#endif + return fast_as<T, ShouldSignalExceptions>(); + } + template <typename T, typename = cpp::enable_if_t<cpp::is_floating_point_v<T> && (FPBits<T>::FRACTION_LEN < Bits), diff --git a/libc/src/__support/FPUtil/except_value_utils.h b/libc/src/__support/FPUtil/except_value_utils.h index b9f54aa24e3a..f8e4e92d3e1f 100644 --- a/libc/src/__support/FPUtil/except_value_utils.h +++ b/libc/src/__support/FPUtil/except_value_utils.h @@ -11,10 +11,13 @@ #include "FEnvImpl.h" #include "FPBits.h" +#include "cast.h" #include "rounding_mode.h" #include "src/__support/CPP/optional.h" #include "src/__support/macros/config.h" #include "src/__support/macros/optimization.h" // LIBC_UNLIKELY +#include "src/__support/macros/properties/cpu_features.h" +#include "src/__support/macros/properties/types.h" namespace LIBC_NAMESPACE_DECL { @@ -113,6 +116,21 @@ template <typename T> LIBC_INLINE T round_result_slightly_up(T value_rn) { return tmp; } +#if defined(LIBC_TYPES_HAS_FLOAT16) && \ + !defined(LIBC_TARGET_CPU_HAS_FAST_FLOAT16_OPS) +template <> LIBC_INLINE float16 round_result_slightly_down(float16 value_rn) { + volatile float tmp = value_rn; + tmp -= FPBits<float16>::min_normal().get_val(); + return cast<float16>(tmp); +} + +template <> LIBC_INLINE float16 round_result_slightly_up(float16 value_rn) { + volatile float tmp = value_rn; + tmp += FPBits<float16>::min_normal().get_val(); + return cast<float16>(tmp); +} +#endif + } // namespace fputil } // namespace LIBC_NAMESPACE_DECL diff --git a/libc/src/__support/FPUtil/generic/CMakeLists.txt b/libc/src/__support/FPUtil/generic/CMakeLists.txt index 43096aa529fc..60434d6f6f11 100644 --- a/libc/src/__support/FPUtil/generic/CMakeLists.txt +++ b/libc/src/__support/FPUtil/generic/CMakeLists.txt @@ -8,6 +8,7 @@ add_header_library( libc.src.__support.common libc.src.__support.CPP.bit libc.src.__support.CPP.type_traits + libc.src.__support.FPUtil.cast libc.src.__support.FPUtil.dyadic_float libc.src.__support.FPUtil.fenv_impl libc.src.__support.FPUtil.fp_bits @@ -21,16 +22,17 @@ add_header_library( FMA.h DEPENDS libc.hdr.fenv_macros + libc.src.__support.big_int libc.src.__support.common libc.src.__support.CPP.bit libc.src.__support.CPP.limits libc.src.__support.CPP.type_traits libc.src.__support.FPUtil.basic_operations + libc.src.__support.FPUtil.cast libc.src.__support.FPUtil.dyadic_float libc.src.__support.FPUtil.fenv_impl libc.src.__support.FPUtil.fp_bits libc.src.__support.FPUtil.rounding_mode - libc.src.__support.big_int libc.src.__support.macros.optimization libc.src.__support.uint128 ) @@ -60,9 +62,10 @@ add_header_library( libc.src.__support.CPP.bit libc.src.__support.CPP.type_traits libc.src.__support.FPUtil.basic_operations + libc.src.__support.FPUtil.cast + libc.src.__support.FPUtil.dyadic_float libc.src.__support.FPUtil.fenv_impl libc.src.__support.FPUtil.fp_bits - libc.src.__support.FPUtil.dyadic_float libc.src.__support.FPUtil.rounding_mode libc.src.__support.macros.attributes libc.src.__support.macros.optimization diff --git a/libc/src/__support/FPUtil/generic/FMA.h b/libc/src/__support/FPUtil/generic/FMA.h index e5683c8ff61e..bec312e44b1b 100644 --- a/libc/src/__support/FPUtil/generic/FMA.h +++ b/libc/src/__support/FPUtil/generic/FMA.h @@ -14,6 +14,7 @@ #include "src/__support/CPP/type_traits.h" #include "src/__support/FPUtil/BasicOperations.h" #include "src/__support/FPUtil/FPBits.h" +#include "src/__support/FPUtil/cast.h" #include "src/__support/FPUtil/dyadic_float.h" #include "src/__support/FPUtil/rounding_mode.h" #include "src/__support/big_int.h" @@ -157,7 +158,7 @@ fma(InType x, InType y, InType z) { } if (LIBC_UNLIKELY(x == 0 || y == 0 || z == 0)) - return static_cast<OutType>(x * y + z); + return cast<OutType>(x * y + z); int x_exp = 0; int y_exp = 0; @@ -198,7 +199,7 @@ fma(InType x, InType y, InType z) { if (LIBC_UNLIKELY(x_exp == InFPBits::MAX_BIASED_EXPONENT || y_exp == InFPBits::MAX_BIASED_EXPONENT || z_exp == InFPBits::MAX_BIASED_EXPONENT)) - return static_cast<OutType>(x * y + z); + return cast<OutType>(x * y + z); // Extract mantissa and append hidden leading bits. InStorageType x_mant = x_bits.get_explicit_mantissa(); diff --git a/libc/src/__support/FPUtil/generic/add_sub.h b/libc/src/__support/FPUtil/generic/add_sub.h index 850db3f83209..6bc9dcd23baf 100644 --- a/libc/src/__support/FPUtil/generic/add_sub.h +++ b/libc/src/__support/FPUtil/generic/add_sub.h @@ -17,6 +17,7 @@ #include "src/__support/FPUtil/BasicOperations.h" #include "src/__support/FPUtil/FEnvImpl.h" #include "src/__support/FPUtil/FPBits.h" +#include "src/__support/FPUtil/cast.h" #include "src/__support/FPUtil/dyadic_float.h" #include "src/__support/FPUtil/rounding_mode.h" #include "src/__support/macros/attributes.h" @@ -106,14 +107,14 @@ add_or_sub(InType x, InType y) { volatile InType tmp = y; if constexpr (IsSub) tmp = -tmp; - return static_cast<OutType>(tmp); + return cast<OutType>(tmp); } if (y_bits.is_zero()) { volatile InType tmp = y; if constexpr (IsSub) tmp = -tmp; - return static_cast<OutType>(tmp); + return cast<OutType>(tmp); } } diff --git a/libc/src/__support/FPUtil/generic/sqrt.h b/libc/src/__support/FPUtil/generic/sqrt.h index 4502cc07d32b..01af4bb7c900 100644 --- a/libc/src/__support/FPUtil/generic/sqrt.h +++ b/libc/src/__support/FPUtil/generic/sqrt.h @@ -14,6 +14,7 @@ #include "src/__support/CPP/type_traits.h" #include "src/__support/FPUtil/FEnvImpl.h" #include "src/__support/FPUtil/FPBits.h" +#include "src/__support/FPUtil/cast.h" #include "src/__support/FPUtil/dyadic_float.h" #include "src/__support/common.h" #include "src/__support/macros/config.h" @@ -96,7 +97,7 @@ sqrt(InType x) { // sqrt(-0) = -0 // sqrt(NaN) = NaN // sqrt(-NaN) = -NaN - return static_cast<OutType>(x); + return cast<OutType>(x); } else if (bits.is_neg()) { // sqrt(-Inf) = NaN // sqrt(-x) = NaN diff --git a/libc/src/math/generic/CMakeLists.txt b/libc/src/math/generic/CMakeLists.txt index 5a1ee3b8b83c..d0676d03420c 100644 --- a/libc/src/math/generic/CMakeLists.txt +++ b/libc/src/math/generic/CMakeLists.txt @@ -109,9 +109,10 @@ add_entrypoint_object( COMPILE_OPTIONS -O3 DEPENDS - libc.src.__support.macros.properties.types + libc.src.__support.FPUtil.cast libc.src.__support.FPUtil.nearest_integer_operations libc.src.__support.macros.properties.cpu_features + libc.src.__support.macros.properties.types FLAGS ROUND_OPT ) @@ -672,9 +673,10 @@ add_entrypoint_object( COMPILE_OPTIONS -O3 DEPENDS - libc.src.__support.macros.properties.types + libc.src.__support.FPUtil.cast libc.src.__support.FPUtil.nearest_integer_operations libc.src.__support.macros.properties.cpu_features + libc.src.__support.macros.properties.types FLAGS ROUND_OPT ) @@ -741,9 +743,10 @@ add_entrypoint_object( COMPILE_OPTIONS -O3 DEPENDS - libc.src.__support.macros.properties.types + libc.src.__support.FPUtil.cast libc.src.__support.FPUtil.nearest_integer_operations libc.src.__support.macros.properties.cpu_features + libc.src.__support.macros.properties.types FLAGS ROUND_OPT ) @@ -810,9 +813,10 @@ add_entrypoint_object( COMPILE_OPTIONS -O3 DEPENDS - libc.src.__support.macros.properties.types + libc.src.__support.FPUtil.cast libc.src.__support.FPUtil.nearest_integer_operations libc.src.__support.macros.properties.cpu_features + libc.src.__support.macros.properties.types FLAGS ROUND_OPT ) @@ -881,6 +885,7 @@ add_entrypoint_object( DEPENDS libc.src.__support.macros.properties.types libc.src.__support.FPUtil.nearest_integer_operations + libc.src.__support.FPUtil.cast libc.src.__support.macros.properties.cpu_features FLAGS ROUND_OPT @@ -1072,9 +1077,10 @@ add_entrypoint_object( COMPILE_OPTIONS -O3 DEPENDS - libc.src.__support.macros.properties.types + libc.src.__support.FPUtil.cast libc.src.__support.FPUtil.nearest_integer_operations libc.src.__support.macros.properties.cpu_features + libc.src.__support.macros.properties.types FLAGS ROUND_OPT ) @@ -1362,12 +1368,15 @@ add_entrypoint_object( .expxf16 libc.hdr.errno_macros libc.hdr.fenv_macros + libc.src.__support.CPP.array + libc.src.__support.FPUtil.cast libc.src.__support.FPUtil.except_value_utils libc.src.__support.FPUtil.fenv_impl libc.src.__support.FPUtil.fp_bits + libc.src.__support.FPUtil.multiply_add + libc.src.__support.FPUtil.nearest_integer libc.src.__support.FPUtil.polyeval libc.src.__support.FPUtil.rounding_mode - libc.src.__support.macros.attributes libc.src.__support.macros.optimization COMPILE_OPTIONS -O3 @@ -1442,6 +1451,7 @@ add_entrypoint_object( libc.hdr.errno_macros libc.hdr.fenv_macros libc.src.__support.CPP.array + libc.src.__support.FPUtil.cast libc.src.__support.FPUtil.except_value_utils libc.src.__support.FPUtil.fenv_impl libc.src.__support.FPUtil.fp_bits @@ -1545,6 +1555,7 @@ add_entrypoint_object( libc.hdr.errno_macros libc.hdr.fenv_macros libc.src.__support.CPP.array + libc.src.__support.FPUtil.cast libc.src.__support.FPUtil.except_value_utils libc.src.__support.FPUtil.fenv_impl libc.src.__support.FPUtil.fp_bits @@ -1617,6 +1628,7 @@ add_entrypoint_object( .expxf16 libc.hdr.errno_macros libc.hdr.fenv_macros + libc.src.__support.FPUtil.cast libc.src.__support.FPUtil.except_value_utils libc.src.__support.FPUtil.fenv_impl libc.src.__support.FPUtil.fp_bits diff --git a/libc/src/math/generic/ceilf16.cpp b/libc/src/math/generic/ceilf16.cpp index 8af31c6623a0..9d89efc5311d 100644 --- a/libc/src/math/generic/ceilf16.cpp +++ b/libc/src/math/generic/ceilf16.cpp @@ -8,6 +8,7 @@ #include "src/math/ceilf16.h" #include "src/__support/FPUtil/NearestIntegerOperations.h" +#include "src/__support/FPUtil/cast.h" #include "src/__support/common.h" #include "src/__support/macros/config.h" #include "src/__support/macros/properties/cpu_features.h" @@ -17,7 +18,7 @@ namespace LIBC_NAMESPACE_DECL { LLVM_LIBC_FUNCTION(float16, ceilf16, (float16 x)) { #if defined(__LIBC_USE_BUILTIN_CEIL_FLOOR_RINT_TRUNC) && \ defined(LIBC_TARGET_CPU_HAS_FAST_FLOAT16_OPS) - return static_cast<float16>(__builtin_ceilf(x)); + return fputil::cast<float16>(__builtin_ceilf(x)); #else return fputil::ceil(x); #endif diff --git a/libc/src/math/generic/exp10f16.cpp b/libc/src/math/generic/exp10f16.cpp index 9959f7450b59..1c5966c1f1c1 100644 --- a/libc/src/math/generic/exp10f16.cpp +++ b/libc/src/math/generic/exp10f16.cpp @@ -14,6 +14,7 @@ #include "src/__support/FPUtil/FEnvImpl.h" #include "src/__support/FPUtil/FPBits.h" #include "src/__support/FPUtil/PolyEval.h" +#include "src/__support/FPUtil/cast.h" #include "src/__support/FPUtil/except_value_utils.h" #include "src/__support/FPUtil/multiply_add.h" #include "src/__support/FPUtil/nearest_integer.h" @@ -118,13 +119,13 @@ LLVM_LIBC_FUNCTION(float16, exp10f16, (float16 x)) { if (LIBC_UNLIKELY((x_u & ~(0x3c00U | 0x4000U | 0x4200U | 0x4400U)) == 0)) { switch (x_u) { case 0x3c00U: // x = 1.0f16 - return static_cast<float16>(10.0); + return fputil::cast<float16>(10.0); case 0x4000U: // x = 2.0f16 - return static_cast<float16>(100.0); + return fputil::cast<float16>(100.0); case 0x4200U: // x = 3.0f16 - return static_cast<float16>(1'000.0); + return fputil::cast<float16>(1'000.0); case 0x4400U: // x = 4.0f16 - return static_cast<float16>(10'000.0); + return fputil::cast<float16>(10'000.0); } } @@ -164,7 +165,7 @@ LLVM_LIBC_FUNCTION(float16, exp10f16, (float16 x)) { // > 1 + x * P; float exp10_lo = fputil::polyeval(lo, 0x1p+0f, 0x1.26bb14p+1f, 0x1.53526p+1f, 0x1.04b434p+1f, 0x1.2bcf9ep+0f); - return static_cast<float16>(exp2_hi_mid * exp10_lo); + return fputil::cast<float16>(exp2_hi_mid * exp10_lo); } } // namespace LIBC_NAMESPACE_DECL diff --git a/libc/src/math/generic/exp2f16.cpp b/libc/src/math/generic/exp2f16.cpp index 66b795670400..3c4310259b1d 100644 --- a/libc/src/math/generic/exp2f16.cpp +++ b/libc/src/math/generic/exp2f16.cpp @@ -14,6 +14,7 @@ #include "src/__support/FPUtil/FEnvImpl.h" #include "src/__support/FPUtil/FPBits.h" #include "src/__support/FPUtil/PolyEval.h" +#include "src/__support/FPUtil/cast.h" #include "src/__support/FPUtil/except_value_utils.h" #include "src/__support/FPUtil/multiply_add.h" #include "src/__support/FPUtil/nearest_integer.h" @@ -121,7 +122,7 @@ LLVM_LIBC_FUNCTION(float16, exp2f16, (float16 x)) { // > 1 + x * P; float exp2_lo = fputil::polyeval(lo, 0x1p+0f, 0x1.62e43p-1f, 0x1.ec0aa6p-3f, 0x1.c6b4a6p-5f); - return static_cast<float16>(exp2_hi_mid * exp2_lo); + return fputil::cast<float16>(exp2_hi_mid * exp2_lo); } } // namespace LIBC_NAMESPACE_DECL diff --git a/libc/src/math/generic/expf16.cpp b/libc/src/math/generic/expf16.cpp index 7ffdbd519100..0548ef3932ae 100644 --- a/libc/src/math/generic/expf16.cpp +++ b/libc/src/math/generic/expf16.cpp @@ -13,6 +13,7 @@ #include "src/__support/FPUtil/FEnvImpl.h" #include "src/__support/FPUtil/FPBits.h" #include "src/__support/FPUtil/PolyEval.h" +#include "src/__support/FPUtil/cast.h" #include "src/__support/FPUtil/except_value_utils.h" #include "src/__support/FPUtil/rounding_mode.h" #include "src/__support/common.h" @@ -103,7 +104,7 @@ LLVM_LIBC_FUNCTION(float16, expf16, (float16 x)) { // > display = hexadecimal; // > P = fpminimax(expm1(x)/x, 2, [|SG...|], [-2^-5, 2^-5]); // > 1 + x * P; - return static_cast<float16>( + return fputil::cast<float16>( fputil::polyeval(xf, 0x1p+0f, 0x1p+0f, 0x1.0004p-1f, 0x1.555778p-3f)); } } @@ -113,7 +114,7 @@ LLVM_LIBC_FUNCTION(float16, expf16, (float16 x)) { // exp(x) = exp(hi + mid) * exp(lo) auto [exp_hi_mid, exp_lo] = exp_range_reduction(x); - return static_cast<float16>(exp_hi_mid * exp_lo); + return fputil::cast<float16>(exp_hi_mid * exp_lo); } } // namespace LIBC_NAMESPACE_DECL diff --git a/libc/src/math/generic/expm1f16.cpp b/libc/src/math/generic/expm1f16.cpp index 0facdc510e42..4ce0efd1f461 100644 --- a/libc/src/math/generic/expm1f16.cpp +++ b/libc/src/math/generic/expm1f16.cpp @@ -13,6 +13,7 @@ #include "src/__support/FPUtil/FEnvImpl.h" #include "src/__support/FPUtil/FPBits.h" #include "src/__support/FPUtil/PolyEval.h" +#include "src/__support/FPUtil/cast.h" #include "src/__support/FPUtil/except_value_utils.h" #include "src/__support/FPUtil/multiply_add.h" #include "src/__support/FPUtil/rounding_mode.h" @@ -99,7 +100,7 @@ LLVM_LIBC_FUNCTION(float16, expm1f16, (float16 x)) { FPBits::one(Sign::NEG).get_val()); // When x <= -0x1.0ap+3, round(expm1(x), HP, RN) = -0x1.ffcp-1. return fputil::round_result_slightly_down( - static_cast<float16>(-0x1.ffcp-1)); + fputil::cast<float16>(-0x1.ffcp-1)); } // When 0 < |x| <= 2^(-3). @@ -114,7 +115,7 @@ LLVM_LIBC_FUNCTION(float16, expm1f16, (float16 x)) { // > display = hexadecimal; // > P = fpminimax(expm1(x)/x, 4, [|SG...|], [-2^-3, 2^-3]); // > x * P; - return static_cast<float16>( + return fputil::cast<float16>( xf * fputil::polyeval(xf, 0x1p+0f, 0x1.fffff8p-2f, 0x1.555556p-3f, 0x1.55905ep-5f, 0x1.1124c2p-7f)); } @@ -126,7 +127,7 @@ LLVM_LIBC_FUNCTION(float16, expm1f16, (float16 x)) { // exp(x) = exp(hi + mid) * exp(lo) auto [exp_hi_mid, exp_lo] = exp_range_reduction(x); // expm1(x) = exp(hi + mid) * exp(lo) - 1 - return static_cast<float16>(fputil::multiply_add(exp_hi_mid, exp_lo, -1.0f)); + return fputil::cast<float16>(fputil::multiply_add(exp_hi_mid, exp_lo, -1.0f)); } } // namespace LIBC_NAMESPACE_DECL diff --git a/libc/src/math/generic/floorf16.cpp b/libc/src/math/generic/floorf16.cpp index 3092048f5ab0..361b22729f64 100644 --- a/libc/src/math/generic/floorf16.cpp +++ b/libc/src/math/generic/floorf16.cpp @@ -8,6 +8,7 @@ #include "src/math/floorf16.h" #include "src/__support/FPUtil/NearestIntegerOperations.h" +#include "src/__support/FPUtil/cast.h" #include "src/__support/common.h" #include "src/__support/macros/config.h" #include "src/__support/macros/properties/cpu_features.h" @@ -17,7 +18,7 @@ namespace LIBC_NAMESPACE_DECL { LLVM_LIBC_FUNCTION(float16, floorf16, (float16 x)) { #if defined(__LIBC_USE_BUILTIN_CEIL_FLOOR_RINT_TRUNC) && \ defined(LIBC_TARGET_CPU_HAS_FAST_FLOAT16_OPS) - return static_cast<float16>(__builtin_floorf(x)); + return fputil::cast<float16>(__builtin_floorf(x)); #else return fputil::floor(x); #endif diff --git a/libc/src/math/generic/rintf16.cpp b/libc/src/math/generic/rintf16.cpp index 3a53dd28e3d1..aefdcbea7706 100644 --- a/libc/src/math/generic/rintf16.cpp +++ b/libc/src/math/generic/rintf16.cpp @@ -8,6 +8,7 @@ #include "src/math/rintf16.h" #include "src/__support/FPUtil/NearestIntegerOperations.h" +#include "src/__support/FPUtil/cast.h" #include "src/__support/common.h" #include "src/__support/macros/config.h" #include "src/__support/macros/properties/cpu_features.h" @@ -17,7 +18,7 @@ namespace LIBC_NAMESPACE_DECL { LLVM_LIBC_FUNCTION(float16, rintf16, (float16 x)) { #if defined(__LIBC_USE_BUILTIN_CEIL_FLOOR_RINT_TRUNC) && \ defined(LIBC_TARGET_CPU_HAS_FAST_FLOAT16_OPS) - return static_cast<float16>(__builtin_rintf(x)); + return fputil::cast<float16>(__builtin_rintf(x)); #else return fputil::round_using_current_rounding_mode(x); #endif diff --git a/libc/src/math/generic/roundevenf16.cpp b/libc/src/math/generic/roundevenf16.cpp index c3dbd779b973..fdcd968bc9b8 100644 --- a/libc/src/math/generic/roundevenf16.cpp +++ b/libc/src/math/generic/roundevenf16.cpp @@ -8,6 +8,7 @@ #include "src/math/roundevenf16.h" #include "src/__support/FPUtil/NearestIntegerOperations.h" +#include "src/__support/FPUtil/cast.h" #include "src/__support/common.h" #include "src/__support/macros/config.h" #include "src/__support/macros/properties/cpu_features.h" @@ -17,7 +18,7 @@ namespace LIBC_NAMESPACE_DECL { LLVM_LIBC_FUNCTION(float16, roundevenf16, (float16 x)) { #if defined(__LIBC_USE_BUILTIN_ROUNDEVEN) && \ defined(LIBC_TARGET_CPU_HAS_FAST_FLOAT16_OPS) - return static_cast<float16>(__builtin_roundevenf(x)); + return fputil::cast<float16>(__builtin_roundevenf(x)); #else return fputil::round_using_specific_rounding_mode(x, FP_INT_TONEAREST); #endif diff --git a/libc/src/math/generic/roundf16.cpp b/libc/src/math/generic/roundf16.cpp index a5e2b44fbd54..9adfb52ed27c 100644 --- a/libc/src/math/generic/roundf16.cpp +++ b/libc/src/math/generic/roundf16.cpp @@ -8,6 +8,7 @@ #include "src/math/roundf16.h" #include "src/__support/FPUtil/NearestIntegerOperations.h" +#include "src/__support/FPUtil/cast.h" #include "src/__support/common.h" #include "src/__support/macros/config.h" #include "src/__support/macros/properties/cpu_features.h" @@ -17,7 +18,7 @@ namespace LIBC_NAMESPACE_DECL { LLVM_LIBC_FUNCTION(float16, roundf16, (float16 x)) { #if defined(__LIBC_USE_BUILTIN_ROUND) && \ defined(LIBC_TARGET_CPU_HAS_FAST_FLOAT16_OPS) - return static_cast<float16>(__builtin_roundf(x)); + return fputil::cast<float16>(__builtin_roundf(x)); #else return fputil::round(x); #endif diff --git a/libc/src/math/generic/truncf16.cpp b/libc/src/math/generic/truncf16.cpp index 31b1214a9a0e..4d37e6560a96 100644 --- a/libc/src/math/generic/truncf16.cpp +++ b/libc/src/math/generic/truncf16.cpp @@ -8,6 +8,7 @@ #include "src/math/truncf16.h" #include "src/__support/FPUtil/NearestIntegerOperations.h" +#include "src/__support/FPUtil/cast.h" #include "src/__support/common.h" #include "src/__support/macros/config.h" #include "src/__support/macros/properties/cpu_features.h" @@ -17,7 +18,7 @@ namespace LIBC_NAMESPACE_DECL { LLVM_LIBC_FUNCTION(float16, truncf16, (float16 x)) { #if defined(__LIBC_USE_BUILTIN_CEIL_FLOOR_RINT_TRUNC) && \ defined(LIBC_TARGET_CPU_HAS_FAST_FLOAT16_OPS) - return static_cast<float16>(__builtin_truncf(x)); + return fputil::cast<float16>(__builtin_truncf(x)); #else return fputil::trunc(x); #endif diff --git a/libc/src/stdlib/CMakeLists.txt b/libc/src/stdlib/CMakeLists.txt index 7fc68cb35e84..1b5b2cb15526 100644 --- a/libc/src/stdlib/CMakeLists.txt +++ b/libc/src/stdlib/CMakeLists.txt @@ -621,3 +621,10 @@ add_entrypoint_object( DEPENDS .${LIBC_TARGET_OS}.abort ) + +add_entrypoint_object( + system + ALIAS + DEPENDS + .${LIBC_TARGET_OS}.system +) diff --git a/libc/src/stdlib/gpu/CMakeLists.txt b/libc/src/stdlib/gpu/CMakeLists.txt index 073f81515870..3c0588a27e7e 100644 --- a/libc/src/stdlib/gpu/CMakeLists.txt +++ b/libc/src/stdlib/gpu/CMakeLists.txt @@ -61,5 +61,16 @@ add_entrypoint_object( ../abort.h DEPENDS libc.include.stdlib - libc.src.__support.GPU.allocator + libc.src.__support.RPC.rpc_client +) + +add_entrypoint_object( + system + SRCS + system.cpp + HDRS + ../system.h + DEPENDS + libc.include.stdlib + libc.src.__support.RPC.rpc_client ) diff --git a/libc/src/stdlib/gpu/system.cpp b/libc/src/stdlib/gpu/system.cpp new file mode 100644 index 000000000000..acf3a8c941ff --- /dev/null +++ b/libc/src/stdlib/gpu/system.cpp @@ -0,0 +1,29 @@ +//===-- GPU implementation of system --------------------------------------===// +// +// 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/RPC/rpc_client.h" +#include "src/__support/common.h" +#include "src/__support/macros/config.h" +#include "src/string/string_utils.h" + +#include "src/stdlib/system.h" + +namespace LIBC_NAMESPACE_DECL { + +LLVM_LIBC_FUNCTION(int, system, (const char *command)) { + int ret; + rpc::Client::Port port = rpc::client.open<RPC_SYSTEM>(); + port.send_n(command, internal::string_length(command) + 1); + port.recv( + [&](rpc::Buffer *buffer) { ret = static_cast<int>(buffer->data[0]); }); + port.close(); + + return ret; +} + +} // namespace LIBC_NAMESPACE_DECL diff --git a/libc/src/stdlib/system.h b/libc/src/stdlib/system.h new file mode 100644 index 000000000000..3358ca7bb7a6 --- /dev/null +++ b/libc/src/stdlib/system.h @@ -0,0 +1,20 @@ +//===-- Implementation header for system ------------------------*- 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_STDLIB_SYSTEM_H +#define LLVM_LIBC_SRC_STDLIB_SYSTEM_H + +#include "src/__support/macros/config.h" + +namespace LIBC_NAMESPACE_DECL { + +int system(const char *command); + +} // namespace LIBC_NAMESPACE_DECL + +#endif // LLVM_LIBC_SRC_STDLIB_SYSTEM_H |
