-
Notifications
You must be signed in to change notification settings - Fork 14.3k
[SimplifyLibCalls] Simplify cabs libcall if real or imaginary part of input is zero #97976
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
Conversation
@llvm/pr-subscribers-llvm-transforms @llvm/pr-subscribers-libc Author: Hendrik Hübner (HendrikHuebner) Changescabs(a + i0) -> absf(a) Issue: #97336 Patch is 25.48 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/97976.diff 20 Files Affected:
diff --git a/libc/config/darwin/arm/entrypoints.txt b/libc/config/darwin/arm/entrypoints.txt
index cb4603c79c79c..d32745c9c9467 100644
--- a/libc/config/darwin/arm/entrypoints.txt
+++ b/libc/config/darwin/arm/entrypoints.txt
@@ -132,6 +132,7 @@ set(TARGET_LIBM_ENTRYPOINTS
libc.src.math.coshf
libc.src.math.cos
libc.src.math.cosf
+ libc.src.math.cospif
libc.src.math.erff
libc.src.math.exp
libc.src.math.expf
diff --git a/libc/config/linux/aarch64/entrypoints.txt b/libc/config/linux/aarch64/entrypoints.txt
index ff35e8fffec19..79e880b1bec8e 100644
--- a/libc/config/linux/aarch64/entrypoints.txt
+++ b/libc/config/linux/aarch64/entrypoints.txt
@@ -346,6 +346,7 @@ set(TARGET_LIBM_ENTRYPOINTS
libc.src.math.cos
libc.src.math.cosf
libc.src.math.coshf
+ libc.src.math.cospif
libc.src.math.erff
libc.src.math.exp
libc.src.math.exp10
diff --git a/libc/config/linux/riscv/entrypoints.txt b/libc/config/linux/riscv/entrypoints.txt
index 51d85eed9ff16..fb9e4e3763844 100644
--- a/libc/config/linux/riscv/entrypoints.txt
+++ b/libc/config/linux/riscv/entrypoints.txt
@@ -354,6 +354,7 @@ set(TARGET_LIBM_ENTRYPOINTS
libc.src.math.cos
libc.src.math.cosf
libc.src.math.coshf
+ libc.src.math.cospif
libc.src.math.erff
libc.src.math.exp
libc.src.math.exp10
diff --git a/libc/config/linux/x86_64/entrypoints.txt b/libc/config/linux/x86_64/entrypoints.txt
index 3eefa129c9758..6a61b51d60242 100644
--- a/libc/config/linux/x86_64/entrypoints.txt
+++ b/libc/config/linux/x86_64/entrypoints.txt
@@ -371,6 +371,7 @@ set(TARGET_LIBM_ENTRYPOINTS
libc.src.math.cos
libc.src.math.cosf
libc.src.math.coshf
+ libc.src.math.cospif
libc.src.math.erff
libc.src.math.exp
libc.src.math.exp10
diff --git a/libc/docs/math/index.rst b/libc/docs/math/index.rst
index e4da3d42baf7a..6c84b10122677 100644
--- a/libc/docs/math/index.rst
+++ b/libc/docs/math/index.rst
@@ -274,7 +274,7 @@ Higher Math Functions
+-----------+------------------+-----------------+------------------------+----------------------+------------------------+------------------------+----------------------------+
| cosh | |check| | | | | | 7.12.5.4 | F.10.2.4 |
+-----------+------------------+-----------------+------------------------+----------------------+------------------------+------------------------+----------------------------+
-| cospi | | | | | | 7.12.4.12 | F.10.1.12 |
+| cospi | |check| | | | | | 7.12.4.12 | F.10.1.12 |
+-----------+------------------+-----------------+------------------------+----------------------+------------------------+------------------------+----------------------------+
| dsqrt | N/A | N/A | | N/A | | 7.12.14.6 | F.10.11 |
+-----------+------------------+-----------------+------------------------+----------------------+------------------------+------------------------+----------------------------+
diff --git a/libc/src/math/CMakeLists.txt b/libc/src/math/CMakeLists.txt
index 5b20913134fdf..ce4f8f993526d 100644
--- a/libc/src/math/CMakeLists.txt
+++ b/libc/src/math/CMakeLists.txt
@@ -81,6 +81,7 @@ add_math_entrypoint_object(cos)
add_math_entrypoint_object(cosf)
add_math_entrypoint_object(cosh)
add_math_entrypoint_object(coshf)
+add_math_entrypoint_object(cospif)
add_math_entrypoint_object(erf)
add_math_entrypoint_object(erff)
diff --git a/libc/src/math/cospif.h b/libc/src/math/cospif.h
new file mode 100644
index 0000000000000..50935bc33e59d
--- /dev/null
+++ b/libc/src/math/cospif.h
@@ -0,0 +1,18 @@
+//===-- Implementation header for cospif ------------------------*- 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_COSPIF_H
+#define LLVM_LIBC_SRC_MATH_COSPIF_H
+
+namespace LIBC_NAMESPACE {
+
+float cospif(float x);
+
+} // namespace LIBC_NAMESPACE
+
+#endif // LLVM_LIBC_SRC_MATH_COSPIF_H
diff --git a/libc/src/math/generic/CMakeLists.txt b/libc/src/math/generic/CMakeLists.txt
index d6ea8c54174b6..6ace14063bcb1 100644
--- a/libc/src/math/generic/CMakeLists.txt
+++ b/libc/src/math/generic/CMakeLists.txt
@@ -217,6 +217,23 @@ add_entrypoint_object(
-O3
)
+add_entrypoint_object(
+ cospif
+ SRCS
+ cospif.cpp
+ HDRS
+ ../cospif.h
+ DEPENDS
+ .sincosf_utils
+ libc.src.__support.FPUtil.fenv_impl
+ libc.src.__support.FPUtil.fp_bits
+ libc.src.__support.FPUtil.fma
+ libc.src.__support.FPUtil.multiply_add
+ libc.src.__support.macros.optimization
+ COMPILE_OPTIONS
+ -O3
+)
+
add_entrypoint_object(
sin
SRCS
diff --git a/libc/src/math/generic/cospif.cpp b/libc/src/math/generic/cospif.cpp
new file mode 100644
index 0000000000000..713619430fe4b
--- /dev/null
+++ b/libc/src/math/generic/cospif.cpp
@@ -0,0 +1,96 @@
+//===-- Single-precision cospi 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/cospif.h"
+#include "sincosf_utils.h"
+#include "src/__support/FPUtil/FEnvImpl.h"
+#include "src/__support/FPUtil/FPBits.h"
+#include "src/__support/FPUtil/multiply_add.h"
+#include "src/__support/common.h"
+#include "src/__support/macros/optimization.h" // LIBC_UNLIKELY
+#include "src/__support/macros/properties/cpu_features.h" // LIBC_TARGET_CPU_HAS_FMA
+
+namespace LIBC_NAMESPACE {
+
+LLVM_LIBC_FUNCTION(float, cospif, (float x)) {
+ using FPBits = typename fputil::FPBits<float>;
+
+ FPBits xbits(x);
+ Sign xsign = xbits.sign();
+ xbits.set_sign(Sign::POS);
+
+ uint32_t x_abs = xbits.uintval();
+ double xd = static_cast<double>(xbits.get_val());
+
+ // Range reduction:
+ // For |x| > 1/32, we perform range reduction as follows:
+ // Find k and y such that:
+ // x = (k + y) * 1/32
+ // k is an integer
+ // |y| < 0.5
+ //
+ // This is done by performing:
+ // k = round(x * 32)
+ // y = x * 32 - k
+ //
+ // Once k and y are computed, we then deduce the answer by the cosine of sum
+ // formula:
+ // cospi(x) = cos((k + y)*pi/32)
+ // = cos(y*pi/32) * cos(k*pi/32) - sin(y*pi/32) * sin(k*pi/32)
+ // The values of sin(k*pi/32) and cos(k*pi/32) for k = 0..63 are precomputed
+ // and stored using a vector of 32 doubles. Sin(y*pi/32) and cos(y*pi/32) are
+ // computed using degree-7 and degree-6 minimax polynomials generated by
+ // Sollya respectively.
+
+ // The exhautive test passes for smaller values
+ if (LIBC_UNLIKELY(x_abs < 0x38A2'F984U)) {
+
+#if defined(LIBC_TARGET_CPU_HAS_FMA)
+ return fputil::multiply_add(xbits.get_val(), -0x1.0p-25f, 1.0f);
+#else
+ return static_cast<float>(fputil::multiply_add(xd, -0x1.0p-25, 1.0));
+#endif // LIBC_TARGET_CPU_HAS_FMA
+ }
+
+ // Numbers greater or equal to 2^23 are always integers or NaN
+ if (LIBC_UNLIKELY(x_abs >= 0x4B00'0000)) {
+
+ if (LIBC_UNLIKELY(x_abs < 0x4B80'0000)) {
+ return (x_abs & 0x1) ? -1.0f : 1.0f;
+ }
+
+ // x is inf or nan.
+ if (LIBC_UNLIKELY(x_abs >= 0x7f80'0000U)) {
+ if (x_abs == 0x7f80'0000U) {
+ fputil::set_errno_if_required(EDOM);
+ fputil::raise_except_if_required(FE_INVALID);
+ }
+ return x + FPBits::quiet_nan().get_val();
+ }
+
+ return 1.0f;
+ }
+
+ // Combine the results with the sine of sum formula:
+ // cos(pi * x) = cos((k + y)*pi/32)
+ // = cos(y*pi/32) * cos(k*pi/32) - sin(y*pi/32) * sin(k*pi/32)
+ // = (cosm1_y + 1) * cos_k - sin_y * sin_k
+ // = (cosm1_y * cos_k + cos_k) - sin_y * sin_k
+ double sin_k, cos_k, sin_y, cosm1_y;
+
+ sincospif_eval(xd, sin_k, cos_k, sin_y, cosm1_y);
+
+ if (LIBC_UNLIKELY(sin_y == 0 && cos_k == 0)) {
+ return FPBits::zero(xsign).get_val();
+ }
+
+ return static_cast<float>(fputil::multiply_add(
+ sin_y, -sin_k, fputil::multiply_add(cosm1_y, cos_k, cos_k)));
+}
+
+} // namespace LIBC_NAMESPACE
diff --git a/libc/src/math/generic/sinpif.cpp b/libc/src/math/generic/sinpif.cpp
index 662263c9fc43e..05bdad3ab4d0e 100644
--- a/libc/src/math/generic/sinpif.cpp
+++ b/libc/src/math/generic/sinpif.cpp
@@ -26,13 +26,13 @@ LLVM_LIBC_FUNCTION(float, sinpif, (float x)) {
double xd = static_cast<double>(x);
// Range reduction:
- // For |x| > pi/32, we perform range reduction as follows:
+ // For |x| > 1/32, we perform range reduction as follows:
// Find k and y such that:
// x = (k + y) * 1/32
// k is an integer
// |y| < 0.5
- // For small range (|x| < 2^45 when FMA instructions are available, 2^22
- // otherwise), this is done by performing:
+ //
+ // This is done by performing:
// k = round(x * 32)
// y = x * 32 - k
//
diff --git a/libc/test/src/math/CMakeLists.txt b/libc/test/src/math/CMakeLists.txt
index 637e6720400ff..0ae7464e8aa40 100644
--- a/libc/test/src/math/CMakeLists.txt
+++ b/libc/test/src/math/CMakeLists.txt
@@ -28,6 +28,22 @@ add_fp_unittest(
libc.src.__support.FPUtil.fp_bits
)
+add_fp_unittest(
+ cospif_test
+ NEED_MPFR
+ SUITE
+ libc-math-unittests
+ SRCS
+ cospif_test.cpp
+ HDRS
+ sdcomp26094.h
+ DEPENDS
+ libc.src.errno.errno
+ libc.src.math.cospif
+ libc.src.__support.CPP.array
+ libc.src.__support.FPUtil.fp_bits
+)
+
add_fp_unittest(
sinf_test
NEED_MPFR
diff --git a/libc/test/src/math/cospif_test.cpp b/libc/test/src/math/cospif_test.cpp
new file mode 100644
index 0000000000000..8a39957d1a274
--- /dev/null
+++ b/libc/test/src/math/cospif_test.cpp
@@ -0,0 +1,120 @@
+//===-- Unittests for cospif ----------------------------------------------===//
+//
+// 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/errno/libc_errno.h"
+#include "src/math/cospif.h"
+#include "test/UnitTest/FPMatcher.h"
+#include "test/src/math/sdcomp26094.h"
+#include "utils/MPFRWrapper/MPFRUtils.h"
+
+using LlvmLibcCospifTest = LIBC_NAMESPACE::testing::FPTest<float>;
+
+using LIBC_NAMESPACE::testing::SDCOMP26094_VALUES;
+
+namespace mpfr = LIBC_NAMESPACE::testing::mpfr;
+
+TEST_F(LlvmLibcCospifTest, SpecialNumbers) {
+ LIBC_NAMESPACE::libc_errno = 0;
+
+ EXPECT_FP_EQ(aNaN, LIBC_NAMESPACE::cospif(aNaN));
+ EXPECT_MATH_ERRNO(0);
+
+ EXPECT_FP_EQ(1.0f, LIBC_NAMESPACE::cospif(0.0f));
+ EXPECT_MATH_ERRNO(0);
+
+ EXPECT_FP_EQ(1.0f, LIBC_NAMESPACE::cospif(-0.0f));
+ EXPECT_MATH_ERRNO(0);
+
+ EXPECT_FP_EQ(aNaN, LIBC_NAMESPACE::cospif(inf));
+ EXPECT_MATH_ERRNO(EDOM);
+
+ EXPECT_FP_EQ(aNaN, LIBC_NAMESPACE::cospif(neg_inf));
+ EXPECT_MATH_ERRNO(EDOM);
+}
+
+TEST_F(LlvmLibcCospifTest, SpecificBitPatterns) {
+ constexpr int N = 36;
+ constexpr uint32_t INPUTS[N] = {
+ 0x3f06'0a92U, // x = pi/6
+ 0x3f3a'dc51U, // x = 0x1.75b8a2p-1f
+ 0x3f49'0fdbU, // x = pi/4
+ 0x3f86'0a92U, // x = pi/3
+ 0x3fa7'832aU, // x = 0x1.4f0654p+0f
+ 0x3fc9'0fdbU, // x = pi/2
+ 0x4017'1973U, // x = 0x1.2e32e6p+1f
+ 0x4049'0fdbU, // x = pi
+ 0x4096'cbe4U, // x = 0x1.2d97c8p+2f
+ 0x40c9'0fdbU, // x = 2*pi
+ 0x433b'7490U, // x = 0x1.76e92p+7f
+ 0x437c'e5f1U, // x = 0x1.f9cbe2p+7f
+ 0x4619'9998U, // x = 0x1.33333p+13f
+ 0x474d'246fU, // x = 0x1.9a48dep+15f
+ 0x4afd'ece4U, // x = 0x1.fbd9c8p+22f
+ 0x4c23'32e9U, // x = 0x1.4665d2p+25f
+ 0x50a3'e87fU, // x = 0x1.47d0fep+34f
+ 0x5239'47f6U, // x = 0x1.728fecp+37f
+ 0x53b1'46a6U, // x = 0x1.628d4cp+40f
+ 0x55ca'fb2aU, // x = 0x1.95f654p+44f
+ 0x588e'f060U, // x = 0x1.1de0cp+50f
+ 0x5c07'bcd0U, // x = 0x1.0f79ap+57f
+ 0x5ebc'fddeU, // x = 0x1.79fbbcp+62f
+ 0x5fa6'eba7U, // x = 0x1.4dd74ep+64f
+ 0x61a4'0b40U, // x = 0x1.48168p+68f
+ 0x6386'134eU, // x = 0x1.0c269cp+72f
+ 0x6589'8498U, // x = 0x1.13093p+76f
+ 0x6600'0001U, // x = 0x1.000002p+77f
+ 0x664e'46e4U, // x = 0x1.9c8dc8p+77f
+ 0x66b0'14aaU, // x = 0x1.602954p+78f
+ 0x67a9'242bU, // x = 0x1.524856p+80f
+ 0x6a19'76f1U, // x = 0x1.32ede2p+85f
+ 0x6c55'da58U, // x = 0x1.abb4bp+89f
+ 0x6f79'be45U, // x = 0x1.f37c8ap+95f
+ 0x7276'69d4U, // x = 0x1.ecd3a8p+101f
+ 0x7758'4625U, // x = 0x1.b08c4ap+111f
+ };
+
+ for (int i = 0; i < N; ++i) {
+ float x = FPBits(INPUTS[i]).get_val();
+ EXPECT_MPFR_MATCH_ALL_ROUNDING(mpfr::Operation::Cospi, x,
+ LIBC_NAMESPACE::cospif(x), 0.5);
+ EXPECT_MPFR_MATCH_ALL_ROUNDING(mpfr::Operation::Cospi, -x,
+ LIBC_NAMESPACE::cospif(-x), 0.5);
+ }
+}
+
+// For small values, sinpi(x) is pi * x.
+TEST_F(LlvmLibcCospifTest, SmallValues) {
+ float x = FPBits(0x1780'0000U).get_val();
+ EXPECT_MPFR_MATCH_ALL_ROUNDING(mpfr::Operation::Cospi, x,
+ LIBC_NAMESPACE::cospif(x), 0.5);
+
+ x = FPBits(0x0040'0000U).get_val();
+ EXPECT_MPFR_MATCH_ALL_ROUNDING(mpfr::Operation::Cospi, x,
+ LIBC_NAMESPACE::cospif(x), 0.5);
+}
+
+// SDCOMP-26094: check sinfpi in the cases for which the range reducer
+// returns values furthest beyond its nominal upper bound of pi/4.
+TEST_F(LlvmLibcCospifTest, SDCOMP_26094) {
+ for (uint32_t v : SDCOMP26094_VALUES) {
+ float x = FPBits((v)).get_val();
+ EXPECT_MPFR_MATCH_ALL_ROUNDING(mpfr::Operation::Cospi, x,
+ LIBC_NAMESPACE::cospif(x), 0.5);
+ }
+}
+
+// sinpi(-n) = -0.0
+// sinpi(+n) = +0.0
+TEST_F(LlvmLibcCospifTest, SignedZeros) {
+ EXPECT_FP_EQ(0.0, LIBC_NAMESPACE::cospif(100.5f));
+ EXPECT_FP_EQ(-0.0, LIBC_NAMESPACE::cospif(-100.5f));
+ EXPECT_FP_EQ(0.0, LIBC_NAMESPACE::cospif(45678.5f));
+ EXPECT_FP_EQ(-0.0, LIBC_NAMESPACE::cospif(-45678.5f));
+ EXPECT_FP_EQ(0.0, LIBC_NAMESPACE::cospif(8000000.5f));
+ EXPECT_FP_EQ(-0.0, LIBC_NAMESPACE::cospif(-8000000.5f));
+}
diff --git a/libc/test/src/math/exhaustive/CMakeLists.txt b/libc/test/src/math/exhaustive/CMakeLists.txt
index 412ca031d0e99..c5f75b51cbd9f 100644
--- a/libc/test/src/math/exhaustive/CMakeLists.txt
+++ b/libc/test/src/math/exhaustive/CMakeLists.txt
@@ -74,6 +74,22 @@ add_fp_unittest(
-lpthread
)
+add_fp_unittest(
+ cospif_test
+ NO_RUN_POSTBUILD
+ NEED_MPFR
+ SUITE
+ libc_math_exhaustive_tests
+ SRCS
+ cospif_test.cpp
+ DEPENDS
+ .exhaustive_test
+ libc.src.math.cospif
+ libc.src.__support.FPUtil.fp_bits
+ LINK_LIBRARIES
+ -lpthread
+)
+
add_fp_unittest(
sincosf_test
NO_RUN_POSTBUILD
diff --git a/libc/test/src/math/exhaustive/cospif_test.cpp b/libc/test/src/math/exhaustive/cospif_test.cpp
new file mode 100644
index 0000000000000..59077d5909937
--- /dev/null
+++ b/libc/test/src/math/exhaustive/cospif_test.cpp
@@ -0,0 +1,33 @@
+//===-- Exhaustive test for cospif ----------------------------------------===//
+//
+// 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 "exhaustive_test.h"
+#include "src/math/cospif.h"
+#include "utils/MPFRWrapper/MPFRUtils.h"
+
+namespace mpfr = LIBC_NAMESPACE::testing::mpfr;
+
+using LlvmLibcCospifExhaustiveTest =
+ LlvmLibcUnaryOpExhaustiveMathTest<float, mpfr::Operation::Cospi,
+ LIBC_NAMESPACE::cospif>;
+
+static constexpr uint32_t POS_START = 0x0000'0000U;
+static constexpr uint32_t POS_STOP = 0x7f80'0000U;
+
+// Range: [0, Inf]
+TEST_F(LlvmLibcCospifExhaustiveTest, PostiveRange) {
+ test_full_range_all_roundings(POS_START, POS_STOP);
+}
+
+// Range: [-Inf, 0]
+static constexpr uint32_t NEG_START = 0xb000'0000U;
+static constexpr uint32_t NEG_STOP = 0xff80'0000U;
+
+TEST_F(LlvmLibcCospifExhaustiveTest, NegativeRange) {
+ test_full_range_all_roundings(NEG_START, NEG_STOP);
+}
diff --git a/libc/test/src/math/smoke/CMakeLists.txt b/libc/test/src/math/smoke/CMakeLists.txt
index 1b269edaa2477..72d04439e2d93 100644
--- a/libc/test/src/math/smoke/CMakeLists.txt
+++ b/libc/test/src/math/smoke/CMakeLists.txt
@@ -10,6 +10,17 @@ add_fp_unittest(
DEPENDS
libc.src.errno.errno
libc.src.math.cosf
+)
+
+add_fp_unittest(
+ cospif_test
+ SUITE
+ libc-math-smoke-tests
+ SRCS
+ cospif_test.cpp
+ DEPENDS
+ libc.src.errno.errno
+ libc.src.math.cospif
libc.src.__support.CPP.array
libc.src.__support.FPUtil.fp_bits
)
diff --git a/libc/test/src/math/smoke/cospif_test.cpp b/libc/test/src/math/smoke/cospif_test.cpp
new file mode 100644
index 0000000000000..007c4c45e3b15
--- /dev/null
+++ b/libc/test/src/math/smoke/cospif_test.cpp
@@ -0,0 +1,34 @@
+//===-- Unittests for cospif ----------------------------------------------===//
+//
+// 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/errno/libc_errno.h"
+#include "src/math/cospif.h"
+#include "test/UnitTest/FPMatcher.h"
+
+#include <stdint.h>
+
+using LlvmLibcCospifTest = LIBC_NAMESPACE::testing::FPTest<float>;
+
+TEST_F(LlvmLibcCospifTest, SpecialNumbers) {
+ LIBC_NAMESPACE::libc_errno = 0;
+
+ EXPECT_FP_EQ(aNaN, LIBC_NAMESPACE::cospif(aNaN));
+ EXPECT_MATH_ERRNO(0);
+
+ EXPECT_FP_EQ(1.0f, LIBC_NAMESPACE::cospif(0.0f));
+ EXPECT_MATH_ERRNO(0);
+
+ EXPECT_FP_EQ(1.0f, LIBC_NAMESPACE::cospif(-0.0f));
+ EXPECT_MATH_ERRNO(0);
+
+ EXPECT_FP_EQ(aNaN, LIBC_NAMESPACE::cospif(inf));
+ EXPECT_MATH_ERRNO(EDOM);
+
+ EXPECT_FP_EQ(aNaN, LIBC_NAMESPACE::cospif(neg_inf));
+ EXPECT_MATH_ERRNO(EDOM);
+}
diff --git a/libc/utils/MPFRWrapper/MPFRUtils.cpp b/libc/utils/MPFRWrapper/MPFRUtils.cpp
index f0a653824bea2..6548fc36cb6b4 100644
--- a/libc/utils/MPFRWrapper/MPFRUtils.cpp
+++ b/libc/utils/MPFRWrapper/MPFRUtils.cpp
@@ -239,6 +239,39 @@ class MPFRNumber {
return result;
}
+ MPFRNumber cospi() const {
+ MPFRNumber result(*this);
+
+#if MPFR_VERSION_MAJOR > 4 || \
+ (MPFR_VERSION_MAJOR == 4 && MPFR_VERSION_MINOR >= 2)
+ mpfr_cospi(result.value, value, mpfr_rounding);
+ return result;
+#else
+ MPFRNumber value_frac(*this);
+ mpfr_frac(value_frac.value, value, MPFR_RNDN);
+
+ if (mpfr_cmp_si(value_frac.value, 0.0) == 0) {
+ mpz_t integer_part;
+ mpz_init(integer_part);
+ mpfr_get_z(integer_part, value, MPFR_RNDN);
+
+ if (mpz_tstbit(integer_part, 0)) {
+ mpfr_set_si(result.value, -1.0, MPFR_RNDN); // odd
+ } else {
+ mpfr_set_si(result.value, 1.0, MPFR_RNDN); // even
+ }
+ return result;
+ }
+
+ MPFRNumber value_pi(0.0, 1280);
+ mpfr_const_pi(value_pi.value, MPFR_RNDN);
+ mpfr_mul(value_pi.value, value_pi.value, value, MPFR_RNDN);
+ mpfr_cos(result.value, value_pi.value, mpfr_rounding);
+
+ return result;
+#endif
+ }
+
MPFRNumber erf() const {
MPFRNumber result(*this);
mpfr_erf(result.value, value, mpfr_rounding);
@@ -675,6 +708,8 @@ unary_operation(Operation op, InputType input, unsigned int precision,
return mpfrInput.cos();
case Operation::Cosh:
return mpfrInput.cosh();
+ case Operation::Cospi:
+ return mpfrInput.cospi();
case Operation::Erf:
...
[truncated]
|
Can someone remove the libc tag? I accidentally pushed some commits which didn't belong here at first. |
@dtcxzyw I just noticed another mistake I made, I did not handle array type inputs correctly. If Op has type "ArrayTy", how can I get the first and second element and check if one is zero? In the existing code, IRBuilderBase.createExtractValue is used, but I can't use this to check for zeros because it actually modifies the IR and which should not happen in case there is no zero. |
IIRC |
Hmm... I dont think the array is a constant when it is passed to the cabs function. So this probably means its not so trivial to check whether one of its elements is constant..? In that case I will skip the optimization for array inputs. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM. Thank you!
IRBuilderBase::FastMathFlagGuard Guard(B); | ||
B.setFastMathFlags(CI->getFastMathFlags()); | ||
|
||
return copyFlags( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you add a test for FMF propagation?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I will add the fast flag to the negative zero tests if thats okay. This would reduce the number of total tests
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I can't get the negative zero test to work for fp128. Do you know how I can create a 128bit negative zero literal in IR? I tried 0xL80000000000000000000000000000000
but debugging revealed that this apparently gets turned into a very small positive number when I tried to call dump() on the value.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please use 0xL00000000000000008000000000000000
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You can always write out fpext float -0.0 to fp128 and run that through instsimplify to see how it's printed
86142ca
to
f8e7763
Compare
LLVM Buildbot has detected a new failure on builder Full details are available at: https://lab.llvm.org/buildbot/#/builders/159/builds/1861 Here is the relevant piece of the build log for the reference:
|
… input is zero (llvm#97976) cabs(a + i0) -> abs(a) cabs(0 +ib) -> abs(b) Closes llvm#97336
cabs(a + i0) -> abs(a)
cabs(0 +ib) -> abs(b)
Closes #97336