summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLLVM libc <llvm-libc@google.com>2024-05-10 16:38:13 -0500
committerCopybara-Service <copybara-worker@google.com>2024-05-11 02:10:01 -0700
commitaf661192d780c55f7cf7e4e346559bddebaba9f4 (patch)
tree8215ccfc3d5f7ee558ac2e303cac36f7f19505a0
parent5c76e7b22aaa87ac1d8f0ae7e100327ff29eb427 (diff)
downloadllvm-libc-main.tar.gz
Project import generated by Copybara.main
GitOrigin-RevId: fb3f4b013c3acab0ea3cb14c4d29f4e6d9caa33c Change-Id: Id51b0538150a61ebfd370348c8ed47881798cf7d
-rw-r--r--include/llvm-libc-macros/fenv-macros.h11
-rw-r--r--libc/hdr/fenv_macros.h46
-rw-r--r--libc/hdr/time_macros.h22
-rw-r--r--libc/hdr/types/clock_t.h22
-rw-r--r--libc/hdr/types/clockid_t.h22
-rw-r--r--libc/hdr/types/struct_timeval.h21
-rw-r--r--libc/hdr/types/suseconds_t.h22
-rw-r--r--libc/hdr/types/time_t.h22
-rw-r--r--src/__support/CPP/atomic.h30
-rw-r--r--src/__support/CPP/mutex.h49
-rw-r--r--src/__support/FPUtil/FMA.h26
-rw-r--r--src/__support/FPUtil/aarch64/FEnvImpl.h20
-rw-r--r--src/__support/FPUtil/aarch64/FMA.h50
-rw-r--r--src/__support/FPUtil/aarch64/fenv_darwin_impl.h48
-rw-r--r--src/__support/FPUtil/arm/FEnvImpl.h40
-rw-r--r--src/__support/FPUtil/gpu/FMA.h36
-rw-r--r--src/__support/FPUtil/riscv/FEnvImpl.h20
-rw-r--r--src/__support/FPUtil/riscv/FMA.h54
-rw-r--r--src/__support/FPUtil/x86_64/FEnvImpl.h24
-rw-r--r--src/__support/FPUtil/x86_64/FMA.h55
-rw-r--r--src/__support/File/dir.cpp5
-rw-r--r--src/__support/GPU/amdgpu/utils.h5
-rw-r--r--src/__support/GPU/nvptx/utils.h4
-rw-r--r--src/__support/threads/fork_callbacks.cpp9
-rw-r--r--src/__support/threads/linux/callonce.cpp31
-rw-r--r--src/__support/threads/linux/futex_utils.h90
-rw-r--r--src/__support/threads/linux/futex_word.h1
-rw-r--r--src/__support/threads/linux/mutex.h22
-rw-r--r--src/__support/threads/linux/thread.cpp25
-rw-r--r--src/__support/threads/mutex.h4
-rw-r--r--src/__support/threads/thread.cpp15
-rw-r--r--src/__support/time/linux/clock_gettime.cpp (renamed from src/time/linux/clockGetTimeImpl.h)23
-rw-r--r--src/__support/time/linux/clock_gettime.h23
-rw-r--r--src/__support/time/units.h38
-rw-r--r--src/math/generic/powf.cpp23
-rw-r--r--src/stdlib/atexit.cpp3
-rw-r--r--src/threads/linux/CndVar.h14
-rw-r--r--src/time/clock.h2
-rw-r--r--src/time/clock_gettime.h5
-rw-r--r--src/time/gettimeofday.h2
-rw-r--r--src/time/gpu/clock.cpp3
-rw-r--r--src/time/gpu/time_utils.h3
-rw-r--r--src/time/linux/clock.cpp20
-rw-r--r--src/time/linux/clock_gettime.cpp9
-rw-r--r--src/time/linux/gettimeofday.cpp14
-rw-r--r--src/time/linux/time.cpp12
-rw-r--r--src/time/nanosleep.h4
-rw-r--r--src/time/time_func.h2
-rw-r--r--test/UnitTest/FPMatcher.h26
-rw-r--r--test/src/__support/CPP/mutex_test.cpp79
-rw-r--r--test/src/math/FModTest.h4
-rw-r--r--test/src/math/RoundToIntegerTest.h7
-rw-r--r--test/src/math/atanf_test.cpp14
-rw-r--r--test/src/math/atanhf_test.cpp34
-rw-r--r--test/src/math/powf_test.cpp19
-rw-r--r--test/src/math/smoke/NextAfterTest.h2
-rw-r--r--test/src/math/smoke/NextTowardTest.h2
-rw-r--r--test/src/math/smoke/RoundToIntegerTest.h18
-rw-r--r--test/src/math/smoke/atan2f_test.cpp22
-rw-r--r--test/src/math/smoke/atanf_test.cpp13
-rw-r--r--test/src/math/smoke/atanhf_test.cpp14
61 files changed, 814 insertions, 491 deletions
diff --git a/include/llvm-libc-macros/fenv-macros.h b/include/llvm-libc-macros/fenv-macros.h
index 72ac660cd98c..1826723f9349 100644
--- a/include/llvm-libc-macros/fenv-macros.h
+++ b/include/llvm-libc-macros/fenv-macros.h
@@ -9,11 +9,12 @@
#ifndef LLVM_LIBC_MACROS_FENV_MACROS_H
#define LLVM_LIBC_MACROS_FENV_MACROS_H
-#define FE_DIVBYZERO 1
-#define FE_INEXACT 2
-#define FE_INVALID 4
-#define FE_OVERFLOW 8
-#define FE_UNDERFLOW 16
+#define FE_DIVBYZERO 0x1
+#define FE_INEXACT 0x2
+#define FE_INVALID 0x4
+#define FE_OVERFLOW 0x8
+#define FE_UNDERFLOW 0x10
+#define __FE_DENORM 0x20
#define FE_ALL_EXCEPT \
(FE_DIVBYZERO | FE_INEXACT | FE_INVALID | FE_OVERFLOW | FE_UNDERFLOW)
diff --git a/libc/hdr/fenv_macros.h b/libc/hdr/fenv_macros.h
index 1ad28cc278a9..a2e4462ef02d 100644
--- a/libc/hdr/fenv_macros.h
+++ b/libc/hdr/fenv_macros.h
@@ -17,6 +17,52 @@
#include <fenv.h>
+// In some environment, FE_ALL_EXCEPT is set to 0 and the remaining exceptions
+// FE_* are missing.
+#if (FE_ALL_EXCEPT == 0)
+#ifndef FE_DIVBYZERO
+#define FE_DIVBYZERO 0
+#endif // FE_DIVBYZERO
+
+#ifndef FE_INEXACT
+#define FE_INEXACT 0
+#endif // FE_INEXACT
+
+#ifndef FE_INVALID
+#define FE_INVALID 0
+#endif // FE_INVALID
+
+#ifndef FE_OVERFLOW
+#define FE_OVERFLOW 0
+#endif // FE_OVERFLOW
+
+#ifndef FE_UNDERFLOW
+#define FE_UNDERFLOW 0
+#endif // FE_UNDERFLOW
+#else
+// If this is not provided by the system, define it for use internally.
+#ifndef __FE_DENORM
+#define __FE_DENORM (1 << 6)
+#endif
+#endif
+
+// Rounding mode macros might be missing.
+#ifndef FE_DOWNWARD
+#define FE_DOWNWARD 0x400
+#endif // FE_DOWNWARD
+
+#ifndef FE_TONEAREST
+#define FE_TONEAREST 0
+#endif // FE_TONEAREST
+
+#ifndef FE_TOWARDZERO
+#define FE_TOWARDZERO 0xC00
+#endif // FE_TOWARDZERO
+
+#ifndef FE_UPWARD
+#define FE_UPWARD 0x800
+#endif // FE_UPWARD
+
#endif // LLVM_LIBC_FULL_BUILD
#endif // LLVM_LIBC_HDR_FENV_MACROS_H
diff --git a/libc/hdr/time_macros.h b/libc/hdr/time_macros.h
new file mode 100644
index 000000000000..dc36fe66f7a8
--- /dev/null
+++ b/libc/hdr/time_macros.h
@@ -0,0 +1,22 @@
+//===-- Definition of macros from time.h ----------------------------------===//
+//
+// 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_HDR_TIME_MACROS_H
+#define LLVM_LIBC_HDR_TIME_MACROS_H
+
+#ifdef LIBC_FULL_BUILD
+
+#include "include/llvm-libc-macros/time-macros.h"
+
+#else // Overlay mode
+
+#include <time.h>
+
+#endif // LLVM_LIBC_FULL_BUILD
+
+#endif // LLVM_LIBC_HDR_TIME_MACROS_H
diff --git a/libc/hdr/types/clock_t.h b/libc/hdr/types/clock_t.h
new file mode 100644
index 000000000000..b0b658e96c3d
--- /dev/null
+++ b/libc/hdr/types/clock_t.h
@@ -0,0 +1,22 @@
+//===-- Proxy for clock_t -------------------------------------------------===//
+//
+// 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_HDR_TYPES_CLOCK_T_H
+#define LLVM_LIBC_HDR_TYPES_CLOCK_T_H
+
+#ifdef LIBC_FULL_BUILD
+
+#include "include/llvm-libc-types/clock_t.h"
+
+#else // Overlay mode
+
+#include <sys/types.h>
+
+#endif // LLVM_LIBC_FULL_BUILD
+
+#endif // LLVM_LIBC_HDR_TYPES_CLOCK_T_H
diff --git a/libc/hdr/types/clockid_t.h b/libc/hdr/types/clockid_t.h
new file mode 100644
index 000000000000..333342072a2f
--- /dev/null
+++ b/libc/hdr/types/clockid_t.h
@@ -0,0 +1,22 @@
+//===-- Proxy for clockid_t -----------------------------------------------===//
+//
+// 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_HDR_TYPES_CLOCKID_T_H
+#define LLVM_LIBC_HDR_TYPES_CLOCKID_T_H
+
+#ifdef LIBC_FULL_BUILD
+
+#include "include/llvm-libc-types/clockid_t.h"
+
+#else // Overlay mode
+
+#include <sys/types.h>
+
+#endif // LLVM_LIBC_FULL_BUILD
+
+#endif // LLVM_LIBC_HDR_TYPES_CLOCKID_T_H
diff --git a/libc/hdr/types/struct_timeval.h b/libc/hdr/types/struct_timeval.h
new file mode 100644
index 000000000000..8fc321a52d71
--- /dev/null
+++ b/libc/hdr/types/struct_timeval.h
@@ -0,0 +1,21 @@
+//===-- Proxy for struct timeval ----------------------------------------===//
+//
+// 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_HDR_TYPES_STRUCT_TIMEVAL_H
+#define LLVM_LIBC_HDR_TYPES_STRUCT_TIMEVAL_H
+
+#ifdef LIBC_FULL_BUILD
+
+#include "include/llvm-libc-types/struct_timeval.h"
+
+#else
+
+#include <sys/time.h>
+
+#endif // LIBC_FULL_BUILD
+
+#endif // LLVM_LIBC_HDR_TYPES_STRUCT_TIMEVAL_H
diff --git a/libc/hdr/types/suseconds_t.h b/libc/hdr/types/suseconds_t.h
new file mode 100644
index 000000000000..72e54a965f75
--- /dev/null
+++ b/libc/hdr/types/suseconds_t.h
@@ -0,0 +1,22 @@
+//===-- Proxy for suseconds_t ---------------------------------------------===//
+//
+// 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_HDR_TIMES_SUSECONDS_T_H
+#define LLVM_LIBC_HDR_TIMES_SUSECONDS_T_H
+
+#ifdef LIBC_FULL_BUILD
+
+#include "include/llvm-libc-types/suseconds_t.h"
+
+#else // Overlay mode
+
+#include <sys/types.h>
+
+#endif // LLVM_LIBC_FULL_BUILD
+
+#endif // #ifndef LLVM_LIBC_HDR_TIMES_SUSECONDS_T_H
diff --git a/libc/hdr/types/time_t.h b/libc/hdr/types/time_t.h
new file mode 100644
index 000000000000..fc9a1506a2cd
--- /dev/null
+++ b/libc/hdr/types/time_t.h
@@ -0,0 +1,22 @@
+//===-- Proxy for time_t --------------------------------------------------===//
+//
+// 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_HDR_TYPES_TIME_T_H
+#define LLVM_LIBC_HDR_TYPES_TIME_T_H
+
+#ifdef LIBC_FULL_BUILD
+
+#include "include/llvm-libc-types/time_t.h"
+
+#else // Overlay mode
+
+#include <time.h>
+
+#endif // LLVM_LIBC_FULL_BUILD
+
+#endif // LLVM_LIBC_HDR_TYPES_TIME_T_H
diff --git a/src/__support/CPP/atomic.h b/src/__support/CPP/atomic.h
index 5e428940565b..e273d998c070 100644
--- a/src/__support/CPP/atomic.h
+++ b/src/__support/CPP/atomic.h
@@ -101,6 +101,36 @@ public:
int(mem_ord), int(mem_ord));
}
+ // Atomic compare exchange (separate success and failure memory orders)
+ bool compare_exchange_strong(
+ T &expected, T desired, MemoryOrder success_order,
+ MemoryOrder failure_order,
+ [[maybe_unused]] MemoryScope mem_scope = MemoryScope::DEVICE) {
+ return __atomic_compare_exchange_n(&val, &expected, desired, false,
+ static_cast<int>(success_order),
+ static_cast<int>(failure_order));
+ }
+
+ // Atomic compare exchange (weak version)
+ bool compare_exchange_weak(
+ T &expected, T desired, MemoryOrder mem_ord = MemoryOrder::SEQ_CST,
+ [[maybe_unused]] MemoryScope mem_scope = MemoryScope::DEVICE) {
+ return __atomic_compare_exchange_n(&val, &expected, desired, true,
+ static_cast<int>(mem_ord),
+ static_cast<int>(mem_ord));
+ }
+
+ // Atomic compare exchange (weak version with separate success and failure
+ // memory orders)
+ bool compare_exchange_weak(
+ T &expected, T desired, MemoryOrder success_order,
+ MemoryOrder failure_order,
+ [[maybe_unused]] MemoryScope mem_scope = MemoryScope::DEVICE) {
+ return __atomic_compare_exchange_n(&val, &expected, desired, true,
+ static_cast<int>(success_order),
+ static_cast<int>(failure_order));
+ }
+
T exchange(T desired, MemoryOrder mem_ord = MemoryOrder::SEQ_CST,
[[maybe_unused]] MemoryScope mem_scope = MemoryScope::DEVICE) {
#if __has_builtin(__scoped_atomic_exchange_n)
diff --git a/src/__support/CPP/mutex.h b/src/__support/CPP/mutex.h
new file mode 100644
index 000000000000..ff9c9f43a43c
--- /dev/null
+++ b/src/__support/CPP/mutex.h
@@ -0,0 +1,49 @@
+//===--- A self contained equivalent of std::mutex --------------*- 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_CPP_MUTEX_H
+#define LLVM_LIBC_SRC___SUPPORT_CPP_MUTEX_H
+
+namespace LIBC_NAMESPACE {
+namespace cpp {
+
+// Assume the calling thread has already obtained mutex ownership.
+struct adopt_lock_t {
+ explicit adopt_lock_t() = default;
+};
+
+// Tag used to make a scoped lock take ownership of a locked mutex.
+constexpr adopt_lock_t adopt_lock{};
+
+// An RAII class for easy locking and unlocking of mutexes.
+template <typename MutexType> class lock_guard {
+ MutexType &mutex;
+
+public:
+ // Calls `m.lock()` upon resource acquisition.
+ explicit lock_guard(MutexType &m) : mutex(m) { mutex.lock(); }
+
+ // Acquires ownership of the mutex object `m` without attempting to lock
+ // it. The behavior is undefined if the current thread does not hold the
+ // lock on `m`. Does not call `m.lock()` upon resource acquisition.
+ lock_guard(MutexType &m, adopt_lock_t /* t */) : mutex(m) {}
+
+ ~lock_guard() { mutex.unlock(); }
+
+ // non-copyable
+ lock_guard &operator=(const lock_guard &) = delete;
+ lock_guard(const lock_guard &) = delete;
+};
+
+// Deduction guide for lock_guard to suppress CTAD warnings.
+template <typename T> lock_guard(T &) -> lock_guard<T>;
+
+} // namespace cpp
+} // namespace LIBC_NAMESPACE
+
+#endif // LLVM_LIBC_SRC___SUPPORT_CPP_MUTEX_H
diff --git a/src/__support/FPUtil/FMA.h b/src/__support/FPUtil/FMA.h
index 0e1ede02d5cc..c277da49538b 100644
--- a/src/__support/FPUtil/FMA.h
+++ b/src/__support/FPUtil/FMA.h
@@ -9,25 +9,31 @@
#ifndef LLVM_LIBC_SRC___SUPPORT_FPUTIL_FMA_H
#define LLVM_LIBC_SRC___SUPPORT_FPUTIL_FMA_H
+#include "src/__support/CPP/type_traits.h"
#include "src/__support/macros/properties/architectures.h"
#include "src/__support/macros/properties/cpu_features.h" // LIBC_TARGET_CPU_HAS_FMA
#if defined(LIBC_TARGET_CPU_HAS_FMA)
-#if defined(LIBC_TARGET_ARCH_IS_X86_64)
-#include "x86_64/FMA.h"
-#elif defined(LIBC_TARGET_ARCH_IS_AARCH64)
-#include "aarch64/FMA.h"
-#elif defined(LIBC_TARGET_ARCH_IS_ANY_RISCV)
-#include "riscv/FMA.h"
-#elif defined(LIBC_TARGET_ARCH_IS_GPU)
-#include "gpu/FMA.h"
-#endif
+namespace LIBC_NAMESPACE {
+namespace fputil {
+
+template <typename T>
+LIBC_INLINE cpp::enable_if_t<cpp::is_same_v<T, float>, T> fma(T x, T y, T z) {
+ return __builtin_fmaf(x, y, z);
+}
+
+template <typename T>
+LIBC_INLINE cpp::enable_if_t<cpp::is_same_v<T, double>, T> fma(T x, T y, T z) {
+ return __builtin_fma(x, y, z);
+}
+
+} // namespace fputil
+} // namespace LIBC_NAMESPACE
#else
// FMA instructions are not available
#include "generic/FMA.h"
-#include "src/__support/CPP/type_traits.h"
namespace LIBC_NAMESPACE {
namespace fputil {
diff --git a/src/__support/FPUtil/aarch64/FEnvImpl.h b/src/__support/FPUtil/aarch64/FEnvImpl.h
index d1d92169475d..cd8a5970edd6 100644
--- a/src/__support/FPUtil/aarch64/FEnvImpl.h
+++ b/src/__support/FPUtil/aarch64/FEnvImpl.h
@@ -53,19 +53,19 @@ struct FEnv {
static constexpr uint32_t ExceptionControlFlagsBitPosition = 8;
LIBC_INLINE static uint32_t getStatusValueForExcept(int excepts) {
- return (excepts & FE_INVALID ? INVALID : 0) |
- (excepts & FE_DIVBYZERO ? DIVBYZERO : 0) |
- (excepts & FE_OVERFLOW ? OVERFLOW : 0) |
- (excepts & FE_UNDERFLOW ? UNDERFLOW : 0) |
- (excepts & FE_INEXACT ? INEXACT : 0);
+ return ((excepts & FE_INVALID) ? INVALID : 0) |
+ ((excepts & FE_DIVBYZERO) ? DIVBYZERO : 0) |
+ ((excepts & FE_OVERFLOW) ? OVERFLOW : 0) |
+ ((excepts & FE_UNDERFLOW) ? UNDERFLOW : 0) |
+ ((excepts & FE_INEXACT) ? INEXACT : 0);
}
LIBC_INLINE static int exceptionStatusToMacro(uint32_t status) {
- return (status & INVALID ? FE_INVALID : 0) |
- (status & DIVBYZERO ? FE_DIVBYZERO : 0) |
- (status & OVERFLOW ? FE_OVERFLOW : 0) |
- (status & UNDERFLOW ? FE_UNDERFLOW : 0) |
- (status & INEXACT ? FE_INEXACT : 0);
+ return ((status & INVALID) ? FE_INVALID : 0) |
+ ((status & DIVBYZERO) ? FE_DIVBYZERO : 0) |
+ ((status & OVERFLOW) ? FE_OVERFLOW : 0) |
+ ((status & UNDERFLOW) ? FE_UNDERFLOW : 0) |
+ ((status & INEXACT) ? FE_INEXACT : 0);
}
static uint32_t getControlWord() {
diff --git a/src/__support/FPUtil/aarch64/FMA.h b/src/__support/FPUtil/aarch64/FMA.h
deleted file mode 100644
index 6254a0673ff4..000000000000
--- a/src/__support/FPUtil/aarch64/FMA.h
+++ /dev/null
@@ -1,50 +0,0 @@
-//===-- Aarch64 implementations of the fma function -------------*- 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_AARCH64_FMA_H
-#define LLVM_LIBC_SRC___SUPPORT_FPUTIL_AARCH64_FMA_H
-
-#include "src/__support/macros/attributes.h" // LIBC_INLINE
-#include "src/__support/macros/properties/architectures.h"
-#include "src/__support/macros/properties/cpu_features.h" // LIBC_TARGET_CPU_HAS_FMA
-
-#if !defined(LIBC_TARGET_ARCH_IS_AARCH64)
-#error "Invalid include"
-#endif
-
-#if !defined(LIBC_TARGET_CPU_HAS_FMA)
-#error "FMA instructions are not supported"
-#endif
-
-#include "src/__support/CPP/type_traits.h"
-
-namespace LIBC_NAMESPACE {
-namespace fputil {
-
-template <typename T>
-LIBC_INLINE cpp::enable_if_t<cpp::is_same_v<T, float>, T> fma(T x, T y, T z) {
- float result;
- LIBC_INLINE_ASM("fmadd %s0, %s1, %s2, %s3\n\t"
- : "=w"(result)
- : "w"(x), "w"(y), "w"(z));
- return result;
-}
-
-template <typename T>
-LIBC_INLINE cpp::enable_if_t<cpp::is_same_v<T, double>, T> fma(T x, T y, T z) {
- double result;
- LIBC_INLINE_ASM("fmadd %d0, %d1, %d2, %d3\n\t"
- : "=w"(result)
- : "w"(x), "w"(y), "w"(z));
- return result;
-}
-
-} // namespace fputil
-} // namespace LIBC_NAMESPACE
-
-#endif // LLVM_LIBC_SRC___SUPPORT_FPUTIL_AARCH64_FMA_H
diff --git a/src/__support/FPUtil/aarch64/fenv_darwin_impl.h b/src/__support/FPUtil/aarch64/fenv_darwin_impl.h
index 5b59ba38d67b..feb48e3719bf 100644
--- a/src/__support/FPUtil/aarch64/fenv_darwin_impl.h
+++ b/src/__support/FPUtil/aarch64/fenv_darwin_impl.h
@@ -63,39 +63,39 @@ struct FEnv {
// located in a different place from FE_FLUSHTOZERO status bit relative to
// the other exceptions.
LIBC_INLINE static uint32_t exception_value_from_status(int status) {
- return (status & FE_INVALID ? EX_INVALID : 0) |
- (status & FE_DIVBYZERO ? EX_DIVBYZERO : 0) |
- (status & FE_OVERFLOW ? EX_OVERFLOW : 0) |
- (status & FE_UNDERFLOW ? EX_UNDERFLOW : 0) |
- (status & FE_INEXACT ? EX_INEXACT : 0) |
- (status & FE_FLUSHTOZERO ? EX_FLUSHTOZERO : 0);
+ return ((status & FE_INVALID) ? EX_INVALID : 0) |
+ ((status & FE_DIVBYZERO) ? EX_DIVBYZERO : 0) |
+ ((status & FE_OVERFLOW) ? EX_OVERFLOW : 0) |
+ ((status & FE_UNDERFLOW) ? EX_UNDERFLOW : 0) |
+ ((status & FE_INEXACT) ? EX_INEXACT : 0) |
+ ((status & FE_FLUSHTOZERO) ? EX_FLUSHTOZERO : 0);
}
LIBC_INLINE static uint32_t exception_value_from_control(int control) {
- return (control & __fpcr_trap_invalid ? EX_INVALID : 0) |
- (control & __fpcr_trap_divbyzero ? EX_DIVBYZERO : 0) |
- (control & __fpcr_trap_overflow ? EX_OVERFLOW : 0) |
- (control & __fpcr_trap_underflow ? EX_UNDERFLOW : 0) |
- (control & __fpcr_trap_inexact ? EX_INEXACT : 0) |
- (control & __fpcr_flush_to_zero ? EX_FLUSHTOZERO : 0);
+ return ((control & __fpcr_trap_invalid) ? EX_INVALID : 0) |
+ ((control & __fpcr_trap_divbyzero) ? EX_DIVBYZERO : 0) |
+ ((control & __fpcr_trap_overflow) ? EX_OVERFLOW : 0) |
+ ((control & __fpcr_trap_underflow) ? EX_UNDERFLOW : 0) |
+ ((control & __fpcr_trap_inexact) ? EX_INEXACT : 0) |
+ ((control & __fpcr_flush_to_zero) ? EX_FLUSHTOZERO : 0);
}
LIBC_INLINE static int exception_value_to_status(uint32_t excepts) {
- return (excepts & EX_INVALID ? FE_INVALID : 0) |
- (excepts & EX_DIVBYZERO ? FE_DIVBYZERO : 0) |
- (excepts & EX_OVERFLOW ? FE_OVERFLOW : 0) |
- (excepts & EX_UNDERFLOW ? FE_UNDERFLOW : 0) |
- (excepts & EX_INEXACT ? FE_INEXACT : 0) |
- (excepts & EX_FLUSHTOZERO ? FE_FLUSHTOZERO : 0);
+ return ((excepts & EX_INVALID) ? FE_INVALID : 0) |
+ ((excepts & EX_DIVBYZERO) ? FE_DIVBYZERO : 0) |
+ ((excepts & EX_OVERFLOW) ? FE_OVERFLOW : 0) |
+ ((excepts & EX_UNDERFLOW) ? FE_UNDERFLOW : 0) |
+ ((excepts & EX_INEXACT) ? FE_INEXACT : 0) |
+ ((excepts & EX_FLUSHTOZERO) ? FE_FLUSHTOZERO : 0);
}
LIBC_INLINE static int exception_value_to_control(uint32_t excepts) {
- return (excepts & EX_INVALID ? __fpcr_trap_invalid : 0) |
- (excepts & EX_DIVBYZERO ? __fpcr_trap_divbyzero : 0) |
- (excepts & EX_OVERFLOW ? __fpcr_trap_overflow : 0) |
- (excepts & EX_UNDERFLOW ? __fpcr_trap_underflow : 0) |
- (excepts & EX_INEXACT ? __fpcr_trap_inexact : 0) |
- (excepts & EX_FLUSHTOZERO ? __fpcr_flush_to_zero : 0);
+ return ((excepts & EX_INVALID) ? __fpcr_trap_invalid : 0) |
+ ((excepts & EX_DIVBYZERO) ? __fpcr_trap_divbyzero : 0) |
+ ((excepts & EX_OVERFLOW) ? __fpcr_trap_overflow : 0) |
+ ((excepts & EX_UNDERFLOW) ? __fpcr_trap_underflow : 0) |
+ ((excepts & EX_INEXACT) ? __fpcr_trap_inexact : 0) |
+ ((excepts & EX_FLUSHTOZERO) ? __fpcr_flush_to_zero : 0);
}
LIBC_INLINE static uint32_t get_control_word() { return __arm_rsr("fpcr"); }
diff --git a/src/__support/FPUtil/arm/FEnvImpl.h b/src/__support/FPUtil/arm/FEnvImpl.h
index 78fbda4f7aff..cb8d31d683af 100644
--- a/src/__support/FPUtil/arm/FEnvImpl.h
+++ b/src/__support/FPUtil/arm/FEnvImpl.h
@@ -50,35 +50,35 @@ struct FEnv {
}
LIBC_INLINE static int exception_enable_bits_to_macro(uint32_t status) {
- return (status & INVALID_ENABLE ? FE_INVALID : 0) |
- (status & DIVBYZERO_ENABLE ? FE_DIVBYZERO : 0) |
- (status & OVERFLOW_ENABLE ? FE_OVERFLOW : 0) |
- (status & UNDERFLOW_ENABLE ? FE_UNDERFLOW : 0) |
- (status & INEXACT_ENABLE ? FE_INEXACT : 0);
+ return ((status & INVALID_ENABLE) ? FE_INVALID : 0) |
+ ((status & DIVBYZERO_ENABLE) ? FE_DIVBYZERO : 0) |
+ ((status & OVERFLOW_ENABLE) ? FE_OVERFLOW : 0) |
+ ((status & UNDERFLOW_ENABLE) ? FE_UNDERFLOW : 0) |
+ ((status & INEXACT_ENABLE) ? FE_INEXACT : 0);
}
LIBC_INLINE static uint32_t exception_macro_to_enable_bits(int except) {
- return (except & FE_INVALID ? INVALID_ENABLE : 0) |
- (except & FE_DIVBYZERO ? DIVBYZERO_ENABLE : 0) |
- (except & FE_OVERFLOW ? OVERFLOW_ENABLE : 0) |
- (except & FE_UNDERFLOW ? UNDERFLOW_ENABLE : 0) |
- (except & FE_INEXACT ? INEXACT_ENABLE : 0);
+ return ((except & FE_INVALID) ? INVALID_ENABLE : 0) |
+ ((except & FE_DIVBYZERO) ? DIVBYZERO_ENABLE : 0) |
+ ((except & FE_OVERFLOW) ? OVERFLOW_ENABLE : 0) |
+ ((except & FE_UNDERFLOW) ? UNDERFLOW_ENABLE : 0) |
+ ((except & FE_INEXACT) ? INEXACT_ENABLE : 0);
}
LIBC_INLINE static uint32_t exception_macro_to_status_bits(int except) {
- return (except & FE_INVALID ? INVALID_STATUS : 0) |
- (except & FE_DIVBYZERO ? DIVBYZERO_STATUS : 0) |
- (except & FE_OVERFLOW ? OVERFLOW_STATUS : 0) |
- (except & FE_UNDERFLOW ? UNDERFLOW_STATUS : 0) |
- (except & FE_INEXACT ? INEXACT_STATUS : 0);
+ return ((except & FE_INVALID) ? INVALID_STATUS : 0) |
+ ((except & FE_DIVBYZERO) ? DIVBYZERO_STATUS : 0) |
+ ((except & FE_OVERFLOW) ? OVERFLOW_STATUS : 0) |
+ ((except & FE_UNDERFLOW) ? UNDERFLOW_STATUS : 0) |
+ ((except & FE_INEXACT) ? INEXACT_STATUS : 0);
}
LIBC_INLINE static uint32_t exception_status_bits_to_macro(int status) {
- return (status & INVALID_STATUS ? FE_INVALID : 0) |
- (status & DIVBYZERO_STATUS ? FE_DIVBYZERO : 0) |
- (status & OVERFLOW_STATUS ? FE_OVERFLOW : 0) |
- (status & UNDERFLOW_STATUS ? FE_UNDERFLOW : 0) |
- (status & INEXACT_STATUS ? FE_INEXACT : 0);
+ return ((status & INVALID_STATUS) ? FE_INVALID : 0) |
+ ((status & DIVBYZERO_STATUS) ? FE_DIVBYZERO : 0) |
+ ((status & OVERFLOW_STATUS) ? FE_OVERFLOW : 0) |
+ ((status & UNDERFLOW_STATUS) ? FE_UNDERFLOW : 0) |
+ ((status & INEXACT_STATUS) ? FE_INEXACT : 0);
}
};
diff --git a/src/__support/FPUtil/gpu/FMA.h b/src/__support/FPUtil/gpu/FMA.h
deleted file mode 100644
index ef1cd26a72dd..000000000000
--- a/src/__support/FPUtil/gpu/FMA.h
+++ /dev/null
@@ -1,36 +0,0 @@
-//===-- GPU implementations of the fma function -----------------*- 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_GPU_FMA_H
-#define LLVM_LIBC_SRC___SUPPORT_FPUTIL_GPU_FMA_H
-
-#include "src/__support/CPP/type_traits.h"
-
-// These intrinsics map to the FMA instructions in the target ISA for the GPU.
-// The default rounding mode generated from these will be to the nearest even.
-#if !__has_builtin(__builtin_fma) || !__has_builtin(__builtin_fmaf)
-#error "FMA builtins must be defined");
-#endif
-
-namespace LIBC_NAMESPACE {
-namespace fputil {
-
-template <typename T>
-LIBC_INLINE cpp::enable_if_t<cpp::is_same_v<T, float>, T> fma(T x, T y, T z) {
- return __builtin_fmaf(x, y, z);
-}
-
-template <typename T>
-LIBC_INLINE cpp::enable_if_t<cpp::is_same_v<T, double>, T> fma(T x, T y, T z) {
- return __builtin_fma(x, y, z);
-}
-
-} // namespace fputil
-} // namespace LIBC_NAMESPACE
-
-#endif // LLVM_LIBC_SRC___SUPPORT_FPUTIL_GPU_FMA_H
diff --git a/src/__support/FPUtil/riscv/FEnvImpl.h b/src/__support/FPUtil/riscv/FEnvImpl.h
index e7aee3ba4b91..1de464a89de4 100644
--- a/src/__support/FPUtil/riscv/FEnvImpl.h
+++ b/src/__support/FPUtil/riscv/FEnvImpl.h
@@ -65,19 +65,19 @@ struct FEnv {
}
LIBC_INLINE static int exception_bits_to_macro(uint32_t status) {
- return (status & INVALID ? FE_INVALID : 0) |
- (status & DIVBYZERO ? FE_DIVBYZERO : 0) |
- (status & OVERFLOW ? FE_OVERFLOW : 0) |
- (status & UNDERFLOW ? FE_UNDERFLOW : 0) |
- (status & INEXACT ? FE_INEXACT : 0);
+ return ((status & INVALID) ? FE_INVALID : 0) |
+ ((status & DIVBYZERO) ? FE_DIVBYZERO : 0) |
+ ((status & OVERFLOW) ? FE_OVERFLOW : 0) |
+ ((status & UNDERFLOW) ? FE_UNDERFLOW : 0) |
+ ((status & INEXACT) ? FE_INEXACT : 0);
}
LIBC_INLINE static uint32_t exception_macro_to_bits(int except) {
- return (except & FE_INVALID ? INVALID : 0) |
- (except & FE_DIVBYZERO ? DIVBYZERO : 0) |
- (except & FE_OVERFLOW ? OVERFLOW : 0) |
- (except & FE_UNDERFLOW ? UNDERFLOW : 0) |
- (except & FE_INEXACT ? INEXACT : 0);
+ return ((except & FE_INVALID) ? INVALID : 0) |
+ ((except & FE_DIVBYZERO) ? DIVBYZERO : 0) |
+ ((except & FE_OVERFLOW) ? OVERFLOW : 0) |
+ ((except & FE_UNDERFLOW) ? UNDERFLOW : 0) |
+ ((except & FE_INEXACT) ? INEXACT : 0);
}
};
diff --git a/src/__support/FPUtil/riscv/FMA.h b/src/__support/FPUtil/riscv/FMA.h
deleted file mode 100644
index f01962174f16..000000000000
--- a/src/__support/FPUtil/riscv/FMA.h
+++ /dev/null
@@ -1,54 +0,0 @@
-//===-- RISCV implementations of the fma function ---------------*- 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_RISCV_FMA_H
-#define LLVM_LIBC_SRC___SUPPORT_FPUTIL_RISCV_FMA_H
-
-#include "src/__support/macros/attributes.h" // LIBC_INLINE
-#include "src/__support/macros/properties/architectures.h"
-#include "src/__support/macros/properties/cpu_features.h" // LIBC_TARGET_CPU_HAS_FMA
-
-#if !defined(LIBC_TARGET_ARCH_IS_ANY_RISCV)
-#error "Invalid include"
-#endif
-
-#if !defined(LIBC_TARGET_CPU_HAS_FMA)
-#error "FMA instructions are not supported"
-#endif
-
-#include "src/__support/CPP/type_traits.h"
-
-namespace LIBC_NAMESPACE {
-namespace fputil {
-
-#ifdef __riscv_flen
-template <typename T>
-LIBC_INLINE cpp::enable_if_t<cpp::is_same_v<T, float>, T> fma(T x, T y, T z) {
- float result;
- LIBC_INLINE_ASM("fmadd.s %0, %1, %2, %3\n\t"
- : "=f"(result)
- : "f"(x), "f"(y), "f"(z));
- return result;
-}
-
-#if __riscv_flen >= 64
-template <typename T>
-LIBC_INLINE cpp::enable_if_t<cpp::is_same_v<T, double>, T> fma(T x, T y, T z) {
- double result;
- LIBC_INLINE_ASM("fmadd.d %0, %1, %2, %3\n\t"
- : "=f"(result)
- : "f"(x), "f"(y), "f"(z));
- return result;
-}
-#endif // __riscv_flen >= 64
-#endif // __riscv_flen
-
-} // namespace fputil
-} // namespace LIBC_NAMESPACE
-
-#endif // LLVM_LIBC_SRC___SUPPORT_FPUTIL_RISCV_FMA_H
diff --git a/src/__support/FPUtil/x86_64/FEnvImpl.h b/src/__support/FPUtil/x86_64/FEnvImpl.h
index 0595658d7df3..a157b81aaaf3 100644
--- a/src/__support/FPUtil/x86_64/FEnvImpl.h
+++ b/src/__support/FPUtil/x86_64/FEnvImpl.h
@@ -72,25 +72,25 @@ static constexpr uint16_t MXCSR_EXCEPTION_CONTOL_BIT_POISTION = 7;
LIBC_INLINE uint16_t get_status_value_for_except(int excepts) {
// We will make use of the fact that exception control bits are single
// bit flags in the control registers.
- return (excepts & FE_INVALID ? ExceptionFlags::INVALID_F : 0) |
+ return ((excepts & FE_INVALID) ? ExceptionFlags::INVALID_F : 0) |
#ifdef __FE_DENORM
- (excepts & __FE_DENORM ? ExceptionFlags::DENORMAL_F : 0) |
+ ((excepts & __FE_DENORM) ? ExceptionFlags::DENORMAL_F : 0) |
#endif // __FE_DENORM
- (excepts & FE_DIVBYZERO ? ExceptionFlags::DIV_BY_ZERO_F : 0) |
- (excepts & FE_OVERFLOW ? ExceptionFlags::OVERFLOW_F : 0) |
- (excepts & FE_UNDERFLOW ? ExceptionFlags::UNDERFLOW_F : 0) |
- (excepts & FE_INEXACT ? ExceptionFlags::INEXACT_F : 0);
+ ((excepts & FE_DIVBYZERO) ? ExceptionFlags::DIV_BY_ZERO_F : 0) |
+ ((excepts & FE_OVERFLOW) ? ExceptionFlags::OVERFLOW_F : 0) |
+ ((excepts & FE_UNDERFLOW) ? ExceptionFlags::UNDERFLOW_F : 0) |
+ ((excepts & FE_INEXACT) ? ExceptionFlags::INEXACT_F : 0);
}
LIBC_INLINE int exception_status_to_macro(uint16_t status) {
- return (status & ExceptionFlags::INVALID_F ? FE_INVALID : 0) |
+ return ((status & ExceptionFlags::INVALID_F) ? FE_INVALID : 0) |
#ifdef __FE_DENORM
- (status & ExceptionFlags::DENORMAL_F ? __FE_DENORM : 0) |
+ ((status & ExceptionFlags::DENORMAL_F) ? __FE_DENORM : 0) |
#endif // __FE_DENORM
- (status & ExceptionFlags::DIV_BY_ZERO_F ? FE_DIVBYZERO : 0) |
- (status & ExceptionFlags::OVERFLOW_F ? FE_OVERFLOW : 0) |
- (status & ExceptionFlags::UNDERFLOW_F ? FE_UNDERFLOW : 0) |
- (status & ExceptionFlags::INEXACT_F ? FE_INEXACT : 0);
+ ((status & ExceptionFlags::DIV_BY_ZERO_F) ? FE_DIVBYZERO : 0) |
+ ((status & ExceptionFlags::OVERFLOW_F) ? FE_OVERFLOW : 0) |
+ ((status & ExceptionFlags::UNDERFLOW_F) ? FE_UNDERFLOW : 0) |
+ ((status & ExceptionFlags::INEXACT_F) ? FE_INEXACT : 0);
}
struct X87StateDescriptor {
diff --git a/src/__support/FPUtil/x86_64/FMA.h b/src/__support/FPUtil/x86_64/FMA.h
deleted file mode 100644
index 91ef7f96ff4d..000000000000
--- a/src/__support/FPUtil/x86_64/FMA.h
+++ /dev/null
@@ -1,55 +0,0 @@
-//===-- x86_64 implementations of the fma function --------------*- 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_X86_64_FMA_H
-#define LLVM_LIBC_SRC___SUPPORT_FPUTIL_X86_64_FMA_H
-
-#include "src/__support/macros/attributes.h" // LIBC_INLINE
-#include "src/__support/macros/properties/architectures.h"
-#include "src/__support/macros/properties/cpu_features.h" // LIBC_TARGET_CPU_HAS_FMA
-
-#if !defined(LIBC_TARGET_ARCH_IS_X86_64)
-#error "Invalid include"
-#endif
-
-#if !defined(LIBC_TARGET_CPU_HAS_FMA)
-#error "FMA instructions are not supported"
-#endif
-
-#include "src/__support/CPP/type_traits.h"
-#include <immintrin.h>
-
-namespace LIBC_NAMESPACE {
-namespace fputil {
-
-template <typename T>
-LIBC_INLINE cpp::enable_if_t<cpp::is_same_v<T, float>, T> fma(T x, T y, T z) {
- float result;
- __m128 xmm = _mm_load_ss(&x); // NOLINT
- __m128 ymm = _mm_load_ss(&y); // NOLINT
- __m128 zmm = _mm_load_ss(&z); // NOLINT
- __m128 r = _mm_fmadd_ss(xmm, ymm, zmm); // NOLINT
- _mm_store_ss(&result, r); // NOLINT
- return result;
-}
-
-template <typename T>
-LIBC_INLINE cpp::enable_if_t<cpp::is_same_v<T, double>, T> fma(T x, T y, T z) {
- double result;
- __m128d xmm = _mm_load_sd(&x); // NOLINT
- __m128d ymm = _mm_load_sd(&y); // NOLINT
- __m128d zmm = _mm_load_sd(&z); // NOLINT
- __m128d r = _mm_fmadd_sd(xmm, ymm, zmm); // NOLINT
- _mm_store_sd(&result, r); // NOLINT
- return result;
-}
-
-} // namespace fputil
-} // namespace LIBC_NAMESPACE
-
-#endif // LLVM_LIBC_SRC___SUPPORT_FPUTIL_X86_64_FMA_H
diff --git a/src/__support/File/dir.cpp b/src/__support/File/dir.cpp
index 9ff639a777e2..e0f7695b3932 100644
--- a/src/__support/File/dir.cpp
+++ b/src/__support/File/dir.cpp
@@ -8,6 +8,7 @@
#include "dir.h"
+#include "src/__support/CPP/mutex.h" // lock_guard
#include "src/__support/CPP/new.h"
#include "src/__support/error_or.h"
#include "src/errno/libc_errno.h" // For error macros
@@ -27,7 +28,7 @@ ErrorOr<Dir *> Dir::open(const char *path) {
}
ErrorOr<struct ::dirent *> Dir::read() {
- MutexLock lock(&mutex);
+ cpp::lock_guard lock(mutex);
if (readptr >= fillsize) {
auto readsize = platform_fetch_dirents(fd, buffer);
if (!readsize)
@@ -51,7 +52,7 @@ ErrorOr<struct ::dirent *> Dir::read() {
int Dir::close() {
{
- MutexLock lock(&mutex);
+ cpp::lock_guard lock(mutex);
int retval = platform_closedir(fd);
if (retval != 0)
return retval;
diff --git a/src/__support/GPU/amdgpu/utils.h b/src/__support/GPU/amdgpu/utils.h
index 9b520a6bcf38..5f8ad74f6aea 100644
--- a/src/__support/GPU/amdgpu/utils.h
+++ b/src/__support/GPU/amdgpu/utils.h
@@ -140,6 +140,11 @@ LIBC_INLINE uint32_t get_lane_size() {
__builtin_amdgcn_fence(__ATOMIC_ACQUIRE, "workgroup");
}
+/// Waits for all pending memory operations to complete in program order.
+[[clang::convergent]] LIBC_INLINE void memory_fence() {
+ __builtin_amdgcn_fence(__ATOMIC_ACQ_REL, "");
+}
+
/// Wait for all threads in the wavefront to converge, this is a noop on AMDGPU.
[[clang::convergent]] LIBC_INLINE void sync_lane(uint64_t) {
__builtin_amdgcn_wave_barrier();
diff --git a/src/__support/GPU/nvptx/utils.h b/src/__support/GPU/nvptx/utils.h
index 3f19afb83648..88b8ee2e31d3 100644
--- a/src/__support/GPU/nvptx/utils.h
+++ b/src/__support/GPU/nvptx/utils.h
@@ -118,9 +118,13 @@ LIBC_INLINE uint32_t get_lane_size() { return 32; }
uint32_t mask = static_cast<uint32_t>(lane_mask);
return __nvvm_vote_ballot_sync(mask, x);
}
+
/// Waits for all the threads in the block to converge and issues a fence.
[[clang::convergent]] LIBC_INLINE void sync_threads() { __syncthreads(); }
+/// Waits for all pending memory operations to complete in program order.
+[[clang::convergent]] LIBC_INLINE void memory_fence() { __nvvm_membar_sys(); }
+
/// Waits for all threads in the warp to reconverge for independent scheduling.
[[clang::convergent]] LIBC_INLINE void sync_lane(uint64_t mask) {
__nvvm_bar_warp_sync(static_cast<uint32_t>(mask));
diff --git a/src/__support/threads/fork_callbacks.cpp b/src/__support/threads/fork_callbacks.cpp
index 54fda676f281..6efaf62f135a 100644
--- a/src/__support/threads/fork_callbacks.cpp
+++ b/src/__support/threads/fork_callbacks.cpp
@@ -8,6 +8,7 @@
#include "fork_callbacks.h"
+#include "src/__support/CPP/mutex.h" // lock_guard
#include "src/__support/threads/mutex.h"
#include <stddef.h> // For size_t
@@ -35,7 +36,7 @@ public:
constexpr AtForkCallbackManager() : mtx(false, false, false), next_index(0) {}
bool register_triple(const ForkCallbackTriple &triple) {
- MutexLock lock(&mtx);
+ cpp::lock_guard lock(mtx);
if (next_index >= CALLBACK_SIZE)
return false;
list[next_index] = triple;
@@ -44,7 +45,7 @@ public:
}
void invoke_prepare() {
- MutexLock lock(&mtx);
+ cpp::lock_guard lock(mtx);
for (size_t i = 0; i < next_index; ++i) {
auto prepare = list[i].prepare;
if (prepare)
@@ -53,7 +54,7 @@ public:
}
void invoke_parent() {
- MutexLock lock(&mtx);
+ cpp::lock_guard lock(mtx);
for (size_t i = 0; i < next_index; ++i) {
auto parent = list[i].parent;
if (parent)
@@ -62,7 +63,7 @@ public:
}
void invoke_child() {
- MutexLock lock(&mtx);
+ cpp::lock_guard lock(mtx);
for (size_t i = 0; i < next_index; ++i) {
auto child = list[i].child;
if (child)
diff --git a/src/__support/threads/linux/callonce.cpp b/src/__support/threads/linux/callonce.cpp
index b6a5ab8c0d07..b48a514a4487 100644
--- a/src/__support/threads/linux/callonce.cpp
+++ b/src/__support/threads/linux/callonce.cpp
@@ -6,15 +6,9 @@
//
//===----------------------------------------------------------------------===//
-#include "futex_word.h"
-
-#include "src/__support/CPP/atomic.h"
-#include "src/__support/CPP/limits.h" // INT_MAX
-#include "src/__support/OSUtil/syscall.h" // For syscall functions.
#include "src/__support/threads/callonce.h"
-
-#include <linux/futex.h>
-#include <sys/syscall.h> // For syscall numbers.
+#include "src/__support/macros/optimization.h"
+#include "src/__support/threads/linux/futex_utils.h"
namespace LIBC_NAMESPACE {
@@ -24,31 +18,30 @@ static constexpr FutexWordType WAITING = 0x22;
static constexpr FutexWordType FINISH = 0x33;
int callonce(CallOnceFlag *flag, CallOnceCallback *func) {
- auto *futex_word = reinterpret_cast<cpp::Atomic<FutexWordType> *>(flag);
+ auto *futex_word = reinterpret_cast<Futex *>(flag);
FutexWordType not_called = NOT_CALLED;
+ // Avoid cmpxchg operation if the function has already been called.
+ // The destination operand of cmpxchg may receive a write cycle without
+ // regard to the result of the comparison
+ if (LIBC_LIKELY(futex_word->load(cpp::MemoryOrder::RELAXED) == FINISH))
+ return 0;
+
// The call_once call can return only after the called function |func|
// returns. So, we use futexes to synchronize calls with the same flag value.
if (futex_word->compare_exchange_strong(not_called, START)) {
func();
auto status = futex_word->exchange(FINISH);
- if (status == WAITING) {
- LIBC_NAMESPACE::syscall_impl<long>(FUTEX_SYSCALL_ID, &futex_word->val,
- FUTEX_WAKE_PRIVATE,
- INT_MAX, // Wake all waiters.
- 0, 0, 0);
- }
+ if (status == WAITING)
+ futex_word->notify_all();
return 0;
}
FutexWordType status = START;
if (futex_word->compare_exchange_strong(status, WAITING) ||
status == WAITING) {
- LIBC_NAMESPACE::syscall_impl<long>(
- FUTEX_SYSCALL_ID, &futex_word->val, FUTEX_WAIT_PRIVATE,
- WAITING, // Block only if status is still |WAITING|.
- 0, 0, 0);
+ futex_word->wait(WAITING);
}
return 0;
diff --git a/src/__support/threads/linux/futex_utils.h b/src/__support/threads/linux/futex_utils.h
new file mode 100644
index 000000000000..1fbce4f7bf43
--- /dev/null
+++ b/src/__support/threads/linux/futex_utils.h
@@ -0,0 +1,90 @@
+//===--- Futex Wrapper ------------------------------------------*- 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_THREADS_LINUX_FUTEX_UTILS_H
+#define LLVM_LIBC_SRC___SUPPORT_THREADS_LINUX_FUTEX_UTILS_H
+
+#include "hdr/types/struct_timespec.h"
+#include "src/__support/CPP/atomic.h"
+#include "src/__support/CPP/limits.h"
+#include "src/__support/CPP/optional.h"
+#include "src/__support/OSUtil/syscall.h"
+#include "src/__support/macros/attributes.h"
+#include "src/__support/threads/linux/futex_word.h"
+#include <linux/errno.h>
+#include <linux/futex.h>
+
+namespace LIBC_NAMESPACE {
+class Futex : public cpp::Atomic<FutexWordType> {
+public:
+ struct Timeout {
+ timespec abs_time;
+ bool is_realtime;
+ };
+ LIBC_INLINE constexpr Futex(FutexWordType value)
+ : cpp::Atomic<FutexWordType>(value) {}
+ LIBC_INLINE Futex &operator=(FutexWordType value) {
+ cpp::Atomic<FutexWordType>::store(value);
+ return *this;
+ }
+ LIBC_INLINE long wait(FutexWordType expected,
+ cpp::optional<Timeout> timeout = cpp::nullopt,
+ bool is_shared = false) {
+ // use bitset variants to enforce abs_time
+ uint32_t op = is_shared ? FUTEX_WAIT_BITSET : FUTEX_WAIT_BITSET_PRIVATE;
+ if (timeout && timeout->is_realtime) {
+ op |= FUTEX_CLOCK_REALTIME;
+ }
+ for (;;) {
+ if (this->load(cpp::MemoryOrder::RELAXED) != expected)
+ return 0;
+
+ long ret = syscall_impl<long>(
+ /* syscall number */ FUTEX_SYSCALL_ID,
+ /* futex address */ this,
+ /* futex operation */ op,
+ /* expected value */ expected,
+ /* timeout */ timeout ? &timeout->abs_time : nullptr,
+ /* ignored */ nullptr,
+ /* bitset */ FUTEX_BITSET_MATCH_ANY);
+
+ // continue waiting if interrupted; otherwise return the result
+ // which should normally be 0 or -ETIMEOUT
+ if (ret == -EINTR)
+ continue;
+
+ return ret;
+ }
+ }
+ LIBC_INLINE long notify_one(bool is_shared = false) {
+ return syscall_impl<long>(
+ /* syscall number */ FUTEX_SYSCALL_ID,
+ /* futex address */ this,
+ /* futex operation */ is_shared ? FUTEX_WAKE : FUTEX_WAKE_PRIVATE,
+ /* wake up limit */ 1,
+ /* ignored */ nullptr,
+ /* ignored */ nullptr,
+ /* ignored */ 0);
+ }
+ LIBC_INLINE long notify_all(bool is_shared = false) {
+ return syscall_impl<long>(
+ /* syscall number */ FUTEX_SYSCALL_ID,
+ /* futex address */ this,
+ /* futex operation */ is_shared ? FUTEX_WAKE : FUTEX_WAKE_PRIVATE,
+ /* wake up limit */ cpp::numeric_limits<int>::max(),
+ /* ignored */ nullptr,
+ /* ignored */ nullptr,
+ /* ignored */ 0);
+ }
+};
+
+static_assert(__is_standard_layout(Futex),
+ "Futex must be a standard layout type.");
+} // namespace LIBC_NAMESPACE
+
+#endif // LLVM_LIBC_SRC___SUPPORT_THREADS_LINUX_FUTEX_UTILS_H
diff --git a/src/__support/threads/linux/futex_word.h b/src/__support/threads/linux/futex_word.h
index 67159b81b561..acdd33bcdaaf 100644
--- a/src/__support/threads/linux/futex_word.h
+++ b/src/__support/threads/linux/futex_word.h
@@ -11,7 +11,6 @@
#include <stdint.h>
#include <sys/syscall.h>
-
namespace LIBC_NAMESPACE {
// Futexes are 32 bits in size on all platforms, including 64-bit platforms.
diff --git a/src/__support/threads/linux/mutex.h b/src/__support/threads/linux/mutex.h
index 618698db0d25..6702de465168 100644
--- a/src/__support/threads/linux/mutex.h
+++ b/src/__support/threads/linux/mutex.h
@@ -9,17 +9,10 @@
#ifndef LLVM_LIBC_SRC___SUPPORT_THREADS_LINUX_MUTEX_H
#define LLVM_LIBC_SRC___SUPPORT_THREADS_LINUX_MUTEX_H
-#include "src/__support/CPP/atomic.h"
-#include "src/__support/OSUtil/syscall.h" // For syscall functions.
-#include "src/__support/threads/linux/futex_word.h"
+#include "src/__support/threads/linux/futex_utils.h"
#include "src/__support/threads/mutex_common.h"
-#include <linux/futex.h>
-#include <stdint.h>
-#include <sys/syscall.h> // For syscall numbers.
-
namespace LIBC_NAMESPACE {
-
struct Mutex {
unsigned char timed;
unsigned char recursive;
@@ -28,7 +21,7 @@ struct Mutex {
void *owner;
unsigned long long lock_count;
- cpp::Atomic<FutexWordType> futex_word;
+ Futex futex_word;
enum class LockState : FutexWordType {
Free,
@@ -76,9 +69,7 @@ public:
// futex syscall will block if the futex data is still
// `LockState::Waiting` (the 4th argument to the syscall function
// below.)
- LIBC_NAMESPACE::syscall_impl<long>(
- FUTEX_SYSCALL_ID, &futex_word.val, FUTEX_WAIT_PRIVATE,
- FutexWordType(LockState::Waiting), 0, 0, 0);
+ futex_word.wait(FutexWordType(LockState::Waiting));
was_waiting = true;
// Once woken up/unblocked, try everything all over.
continue;
@@ -91,9 +82,7 @@ public:
// we will wait for the futex to be woken up. Note again that the
// following syscall will block only if the futex data is still
// `LockState::Waiting`.
- LIBC_NAMESPACE::syscall_impl<long>(
- FUTEX_SYSCALL_ID, &futex_word, FUTEX_WAIT_PRIVATE,
- FutexWordType(LockState::Waiting), 0, 0, 0);
+ futex_word.wait(FutexWordType(LockState::Waiting));
was_waiting = true;
}
continue;
@@ -110,8 +99,7 @@ public:
if (futex_word.compare_exchange_strong(mutex_status,
FutexWordType(LockState::Free))) {
// If any thread is waiting to be woken up, then do it.
- LIBC_NAMESPACE::syscall_impl<long>(FUTEX_SYSCALL_ID, &futex_word,
- FUTEX_WAKE_PRIVATE, 1, 0, 0, 0);
+ futex_word.notify_one();
return MutexError::NONE;
}
diff --git a/src/__support/threads/linux/thread.cpp b/src/__support/threads/linux/thread.cpp
index fcf87cc587a5..1d986ff38cff 100644
--- a/src/__support/threads/linux/thread.cpp
+++ b/src/__support/threads/linux/thread.cpp
@@ -14,15 +14,14 @@
#include "src/__support/OSUtil/syscall.h" // For syscall functions.
#include "src/__support/common.h"
#include "src/__support/error_or.h"
-#include "src/__support/threads/linux/futex_word.h" // For FutexWordType
-#include "src/errno/libc_errno.h" // For error macros
+#include "src/__support/threads/linux/futex_utils.h" // For FutexWordType
+#include "src/errno/libc_errno.h" // For error macros
#ifdef LIBC_TARGET_ARCH_IS_AARCH64
#include <arm_acle.h>
#endif
#include <fcntl.h>
-#include <linux/futex.h>
#include <linux/param.h> // For EXEC_PAGESIZE.
#include <linux/prctl.h> // For PR_SET_NAME
#include <linux/sched.h> // For CLONE_* flags.
@@ -247,8 +246,7 @@ int Thread::run(ThreadStyle style, ThreadRunner runner, void *arg, void *stack,
// stack memory.
static constexpr size_t INTERNAL_STACK_DATA_SIZE =
- sizeof(StartArgs) + sizeof(ThreadAttributes) +
- sizeof(cpp::Atomic<FutexWordType>);
+ sizeof(StartArgs) + sizeof(ThreadAttributes) + sizeof(Futex);
// This is pretty arbitrary, but at the moment we don't adjust user provided
// stacksize (or default) to account for this data as its assumed minimal. If
@@ -288,9 +286,9 @@ int Thread::run(ThreadStyle style, ThreadRunner runner, void *arg, void *stack,
start_args->runner = runner;
start_args->arg = arg;
- auto clear_tid = reinterpret_cast<cpp::Atomic<FutexWordType> *>(
+ auto clear_tid = reinterpret_cast<Futex *>(
adjusted_stack + sizeof(StartArgs) + sizeof(ThreadAttributes));
- clear_tid->val = CLEAR_TID_VALUE;
+ clear_tid->set(CLEAR_TID_VALUE);
attrib->platform_data = clear_tid;
// The clone syscall takes arguments in an architecture specific order.
@@ -374,14 +372,11 @@ void Thread::wait() {
// The kernel should set the value at the clear tid address to zero.
// If not, it is a spurious wake and we should continue to wait on
// the futex.
- auto *clear_tid =
- reinterpret_cast<cpp::Atomic<FutexWordType> *>(attrib->platform_data);
- while (clear_tid->load() != 0) {
- // We cannot do a FUTEX_WAIT_PRIVATE here as the kernel does a
- // FUTEX_WAKE and not a FUTEX_WAKE_PRIVATE.
- LIBC_NAMESPACE::syscall_impl<long>(FUTEX_SYSCALL_ID, &clear_tid->val,
- FUTEX_WAIT, CLEAR_TID_VALUE, nullptr);
- }
+ auto *clear_tid = reinterpret_cast<Futex *>(attrib->platform_data);
+ // We cannot do a FUTEX_WAIT_PRIVATE here as the kernel does a
+ // FUTEX_WAKE and not a FUTEX_WAKE_PRIVATE.
+ while (clear_tid->load() != 0)
+ clear_tid->wait(CLEAR_TID_VALUE, cpp::nullopt, true);
}
bool Thread::operator==(const Thread &thread) const {
diff --git a/src/__support/threads/mutex.h b/src/__support/threads/mutex.h
index fa2bd64b6b51..9dded2e3f952 100644
--- a/src/__support/threads/mutex.h
+++ b/src/__support/threads/mutex.h
@@ -38,9 +38,9 @@
// want the constructors of the Mutex classes to be constexprs.
#if defined(__linux__)
-#include "linux/mutex.h"
+#include "src/__support/threads/linux/mutex.h"
#elif defined(LIBC_TARGET_ARCH_IS_GPU)
-#include "gpu/mutex.h"
+#include "src/__support/threads/gpu/mutex.h"
#endif // __linux__
namespace LIBC_NAMESPACE {
diff --git a/src/__support/threads/thread.cpp b/src/__support/threads/thread.cpp
index 62aa86b7aef7..7b02f8246e24 100644
--- a/src/__support/threads/thread.cpp
+++ b/src/__support/threads/thread.cpp
@@ -6,10 +6,11 @@
//
//===----------------------------------------------------------------------===//
-#include "thread.h"
-#include "mutex.h"
+#include "src/__support/threads/thread.h"
+#include "src/__support/threads/mutex.h"
#include "src/__support/CPP/array.h"
+#include "src/__support/CPP/mutex.h" // lock_guard
#include "src/__support/CPP/optional.h"
#include "src/__support/fixedvector.h"
#include "src/__support/macros/attributes.h"
@@ -56,7 +57,7 @@ public:
constexpr TSSKeyMgr() : mtx(false, false, false) {}
cpp::optional<unsigned int> new_key(TSSDtor *dtor) {
- MutexLock lock(&mtx);
+ cpp::lock_guard lock(mtx);
for (unsigned int i = 0; i < TSS_KEY_COUNT; ++i) {
TSSKeyUnit &u = units[i];
if (!u.active) {
@@ -70,20 +71,20 @@ public:
TSSDtor *get_dtor(unsigned int key) {
if (key >= TSS_KEY_COUNT)
return nullptr;
- MutexLock lock(&mtx);
+ cpp::lock_guard lock(mtx);
return units[key].dtor;
}
bool remove_key(unsigned int key) {
if (key >= TSS_KEY_COUNT)
return false;
- MutexLock lock(&mtx);
+ cpp::lock_guard lock(mtx);
units[key].reset();
return true;
}
bool is_valid_key(unsigned int key) {
- MutexLock lock(&mtx);
+ cpp::lock_guard lock(mtx);
return units[key].active;
}
};
@@ -113,7 +114,7 @@ public:
constexpr ThreadAtExitCallbackMgr() : mtx(false, false, false) {}
int add_callback(AtExitCallback *callback, void *obj) {
- MutexLock lock(&mtx);
+ cpp::lock_guard lock(mtx);
return callback_list.push_back({callback, obj});
}
diff --git a/src/time/linux/clockGetTimeImpl.h b/src/__support/time/linux/clock_gettime.cpp
index 8c8c9fcf845c..7f266b282a39 100644
--- a/src/time/linux/clockGetTimeImpl.h
+++ b/src/__support/time/linux/clock_gettime.cpp
@@ -1,4 +1,4 @@
-//===- Linux implementation of the POSIX clock_gettime function -*- C++ -*-===//
+//===--- clock_gettime linux implementation ---------------------*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
@@ -6,23 +6,12 @@
//
//===----------------------------------------------------------------------===//
-#ifndef LLVM_LIBC_SRC_TIME_LINUX_CLOCKGETTIMEIMPL_H
-#define LLVM_LIBC_SRC_TIME_LINUX_CLOCKGETTIMEIMPL_H
-
-#include "src/__support/OSUtil/syscall.h" // For internal syscall function.
-#include "src/__support/common.h"
-#include "src/__support/error_or.h"
-#include "src/errno/libc_errno.h"
-
-#include <stdint.h> // For int64_t.
-#include <sys/syscall.h> // For syscall numbers.
-#include <time.h>
-
+#include "src/__support/time/linux/clock_gettime.h"
+#include "src/__support/OSUtil/syscall.h"
+#include <sys/syscall.h>
namespace LIBC_NAMESPACE {
namespace internal {
-
-LIBC_INLINE ErrorOr<int> clock_gettimeimpl(clockid_t clockid,
- struct timespec *ts) {
+ErrorOr<int> clock_gettime(clockid_t clockid, timespec *ts) {
#if SYS_clock_gettime
int ret = LIBC_NAMESPACE::syscall_impl<int>(SYS_clock_gettime,
static_cast<long>(clockid),
@@ -44,5 +33,3 @@ LIBC_INLINE ErrorOr<int> clock_gettimeimpl(clockid_t clockid,
} // namespace internal
} // namespace LIBC_NAMESPACE
-
-#endif // LLVM_LIBC_SRC_TIME_LINUX_CLOCKGETTIMEIMPL_H
diff --git a/src/__support/time/linux/clock_gettime.h b/src/__support/time/linux/clock_gettime.h
new file mode 100644
index 000000000000..b1572726f630
--- /dev/null
+++ b/src/__support/time/linux/clock_gettime.h
@@ -0,0 +1,23 @@
+//===--- clock_gettime linux implementation ---------------------*- 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_TIME_LINUX_CLOCK_GETTIME_H
+#define LLVM_LIBC_SRC___SUPPORT_TIME_LINUX_CLOCK_GETTIME_H
+#include "hdr/types/clockid_t.h"
+#include "hdr/types/struct_timespec.h"
+#include "src/__support/common.h"
+
+#include "src/__support/error_or.h"
+
+namespace LIBC_NAMESPACE {
+namespace internal {
+ErrorOr<int> clock_gettime(clockid_t clockid, timespec *ts);
+}
+} // namespace LIBC_NAMESPACE
+
+#endif // LLVM_LIBC_SRC___SUPPORT_TIME_LINUX_CLOCK_GETTIME_H
diff --git a/src/__support/time/units.h b/src/__support/time/units.h
new file mode 100644
index 000000000000..f6bd19f9b139
--- /dev/null
+++ b/src/__support/time/units.h
@@ -0,0 +1,38 @@
+//===--- Time units conversion ----------------------------------*- 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_TIME_UNITS_H
+#define LLVM_LIBC_SRC___SUPPORT_TIME_UNITS_H
+
+#include "hdr/types/time_t.h"
+#include "src/__support/common.h"
+
+namespace LIBC_NAMESPACE {
+namespace time_units {
+LIBC_INLINE constexpr time_t operator""_s_ns(unsigned long long s) {
+ return s * 1'000'000'000;
+}
+LIBC_INLINE constexpr time_t operator""_s_us(unsigned long long s) {
+ return s * 1'000'000;
+}
+LIBC_INLINE constexpr time_t operator""_s_ms(unsigned long long s) {
+ return s * 1'000;
+}
+LIBC_INLINE constexpr time_t operator""_ms_ns(unsigned long long ms) {
+ return ms * 1'000'000;
+}
+LIBC_INLINE constexpr time_t operator""_ms_us(unsigned long long ms) {
+ return ms * 1'000;
+}
+LIBC_INLINE constexpr time_t operator""_us_ns(unsigned long long us) {
+ return us * 1'000;
+}
+} // namespace time_units
+} // namespace LIBC_NAMESPACE
+
+#endif // LLVM_LIBC_SRC___SUPPORT_TIME_UNITS_H
diff --git a/src/math/generic/powf.cpp b/src/math/generic/powf.cpp
index 0450ffd711ff..59efc3f424c7 100644
--- a/src/math/generic/powf.cpp
+++ b/src/math/generic/powf.cpp
@@ -528,7 +528,7 @@ LLVM_LIBC_FUNCTION(float, powf, (float x, float y)) {
// So if |y| > 151 * 2^24, and x is finite:
// |y * log2(x)| = 0 or > 151.
// Hence x^y will either overflow or underflow if x is not zero.
- if (LIBC_UNLIKELY((y_abs & 0x007f'ffff) == 0) || (y_abs > 0x4f170000)) {
+ if (LIBC_UNLIKELY((y_abs & 0x0007'ffff) == 0) || (y_abs > 0x4f170000)) {
// Exceptional exponents.
switch (y_abs) {
case 0x0000'0000: { // y = +-0.0f
@@ -572,6 +572,26 @@ LLVM_LIBC_FUNCTION(float, powf, (float x, float y)) {
// case 0xbf00'0000: // pow(x, -1/2) = rsqrt(x)
// return rsqrt(x);
}
+ if (is_integer(y) && (y_u > 0x4000'0000) && (y_u <= 0x41c0'0000)) {
+ // Check for exact cases when 2 < y < 25 and y is an integer.
+ int msb =
+ (x_abs == 0) ? (FloatBits::TOTAL_LEN - 2) : cpp::countl_zero(x_abs);
+ msb = (msb > FloatBits::EXP_LEN) ? msb : FloatBits::EXP_LEN;
+ int lsb = (x_abs == 0) ? 0 : cpp::countr_zero(x_abs);
+ lsb = (lsb > FloatBits::FRACTION_LEN) ? FloatBits::FRACTION_LEN : lsb;
+ int extra_bits = FloatBits::TOTAL_LEN - 2 - lsb - msb;
+ int iter = static_cast<int>(y);
+
+ if (extra_bits * iter <= FloatBits::FRACTION_LEN + 2) {
+ // The result is either exact or exactly half-way.
+ // But it is exactly representable in double precision.
+ double x_d = static_cast<double>(x);
+ double result = x_d;
+ for (int i = 1; i < iter; ++i)
+ result *= x_d;
+ return static_cast<float>(result);
+ }
+ }
if (y_abs > 0x4f17'0000) {
if (y_abs > 0x7f80'0000) {
// y is NaN
@@ -834,7 +854,6 @@ LLVM_LIBC_FUNCTION(float, powf, (float x, float y)) {
return static_cast<float>(
powf_double_double(idx_x, dx, y6, lo6_hi, exp2_hi_mid_dd)) +
0.0f;
- // return static_cast<float>(r);
}
} // namespace LIBC_NAMESPACE
diff --git a/src/stdlib/atexit.cpp b/src/stdlib/atexit.cpp
index fa072b2fdf8d..4f0497444773 100644
--- a/src/stdlib/atexit.cpp
+++ b/src/stdlib/atexit.cpp
@@ -7,6 +7,7 @@
//===----------------------------------------------------------------------===//
#include "src/stdlib/atexit.h"
+#include "src/__support/CPP/mutex.h" // lock_guard
#include "src/__support/blockstore.h"
#include "src/__support/common.h"
#include "src/__support/fixedvector.h"
@@ -68,7 +69,7 @@ void call_exit_callbacks() {
}
int add_atexit_unit(const AtExitUnit &unit) {
- MutexLock lock(&handler_list_mtx);
+ cpp::lock_guard lock(handler_list_mtx);
if (exit_callbacks.push_back(unit))
return 0;
return -1;
diff --git a/src/threads/linux/CndVar.h b/src/threads/linux/CndVar.h
index b4afdef9f9eb..c08ffa393856 100644
--- a/src/threads/linux/CndVar.h
+++ b/src/threads/linux/CndVar.h
@@ -10,8 +10,10 @@
#define LLVM_LIBC_SRC_THREADS_LINUX_CNDVAR_H
#include "src/__support/CPP/atomic.h"
+#include "src/__support/CPP/mutex.h" // lock_guard
+#include "src/__support/CPP/optional.h"
#include "src/__support/OSUtil/syscall.h" // For syscall functions.
-#include "src/__support/threads/linux/futex_word.h"
+#include "src/__support/threads/linux/futex_utils.h"
#include "src/__support/threads/mutex.h"
#include <linux/futex.h> // For futex operations.
@@ -28,7 +30,7 @@ struct CndVar {
};
struct CndWaiter {
- cpp::Atomic<uint32_t> futex_word = WS_Waiting;
+ Futex futex_word = WS_Waiting;
CndWaiter *next = nullptr;
};
@@ -58,7 +60,7 @@ struct CndVar {
CndWaiter waiter;
{
- MutexLock ml(&qmtx);
+ cpp::lock_guard ml(qmtx);
CndWaiter *old_back = nullptr;
if (waitq_front == nullptr) {
waitq_front = waitq_back = &waiter;
@@ -84,8 +86,7 @@ struct CndVar {
}
}
- LIBC_NAMESPACE::syscall_impl<long>(FUTEX_SYSCALL_ID, &waiter.futex_word.val,
- FUTEX_WAIT, WS_Waiting, 0, 0, 0);
+ waiter.futex_word.wait(WS_Waiting, cpp::nullopt, true);
// At this point, if locking |m| fails, we can simply return as the
// queued up waiter would have been removed from the queue.
@@ -109,6 +110,7 @@ struct CndVar {
qmtx.futex_word = FutexWordType(Mutex::LockState::Free);
+ // this is a special WAKE_OP, so we use syscall directly
LIBC_NAMESPACE::syscall_impl<long>(
FUTEX_SYSCALL_ID, &qmtx.futex_word.val, FUTEX_WAKE_OP, 1, 1,
&first->futex_word.val,
@@ -117,7 +119,7 @@ struct CndVar {
}
int broadcast() {
- MutexLock ml(&qmtx);
+ cpp::lock_guard ml(qmtx);
uint32_t dummy_futex_word;
CndWaiter *waiter = waitq_front;
waitq_front = waitq_back = nullptr;
diff --git a/src/time/clock.h b/src/time/clock.h
index d4af7656644a..f5d14d036e13 100644
--- a/src/time/clock.h
+++ b/src/time/clock.h
@@ -9,7 +9,7 @@
#ifndef LLVM_LIBC_SRC_TIME_CLOCK_H
#define LLVM_LIBC_SRC_TIME_CLOCK_H
-#include <time.h>
+#include "hdr/types/clock_t.h"
namespace LIBC_NAMESPACE {
diff --git a/src/time/clock_gettime.h b/src/time/clock_gettime.h
index 72e2e1949feb..48e81a355429 100644
--- a/src/time/clock_gettime.h
+++ b/src/time/clock_gettime.h
@@ -9,11 +9,12 @@
#ifndef LLVM_LIBC_SRC_TIME_CLOCK_GETTIME_H
#define LLVM_LIBC_SRC_TIME_CLOCK_GETTIME_H
-#include <time.h>
+#include "hdr/types/clockid_t.h"
+#include "hdr/types/struct_timespec.h"
namespace LIBC_NAMESPACE {
-int clock_gettime(clockid_t clockid, struct timespec *tp);
+int clock_gettime(clockid_t clockid, timespec *tp);
} // namespace LIBC_NAMESPACE
diff --git a/src/time/gettimeofday.h b/src/time/gettimeofday.h
index 880b94cee731..62ee31edcad6 100644
--- a/src/time/gettimeofday.h
+++ b/src/time/gettimeofday.h
@@ -9,7 +9,7 @@
#ifndef LLVM_LIBC_SRC_TIME_GETTIMEOFDAY_H
#define LLVM_LIBC_SRC_TIME_GETTIMEOFDAY_H
-#include <time.h>
+#include "hdr/types/struct_timeval.h"
namespace LIBC_NAMESPACE {
diff --git a/src/time/gpu/clock.cpp b/src/time/gpu/clock.cpp
index 86cc97e2a3bf..8ddfc27975bb 100644
--- a/src/time/gpu/clock.cpp
+++ b/src/time/gpu/clock.cpp
@@ -6,9 +6,8 @@
//
//===----------------------------------------------------------------------===//
-#include "time_utils.h"
-
#include "src/time/clock.h"
+#include "src/time/gpu/time_utils.h"
namespace LIBC_NAMESPACE {
diff --git a/src/time/gpu/time_utils.h b/src/time/gpu/time_utils.h
index 8a9a5f0f65b8..3f1fd11c1791 100644
--- a/src/time/gpu/time_utils.h
+++ b/src/time/gpu/time_utils.h
@@ -9,8 +9,9 @@
#ifndef LLVM_LIBC_SRC_TIME_GPU_TIME_UTILS_H
#define LLVM_LIBC_SRC_TIME_GPU_TIME_UTILS_H
+#include "hdr/time_macros.h"
+#include "hdr/types/clock_t.h"
#include "src/__support/GPU/utils.h"
-
namespace LIBC_NAMESPACE {
#if defined(LIBC_TARGET_ARCH_IS_AMDGPU)
diff --git a/src/time/linux/clock.cpp b/src/time/linux/clock.cpp
index 1e95f0526bc9..2c1eee8e5d60 100644
--- a/src/time/linux/clock.cpp
+++ b/src/time/linux/clock.cpp
@@ -7,21 +7,19 @@
//===----------------------------------------------------------------------===//
#include "src/time/clock.h"
-
+#include "hdr/time_macros.h"
#include "src/__support/CPP/limits.h"
-#include "src/__support/OSUtil/syscall.h" // For internal syscall function.
#include "src/__support/common.h"
+#include "src/__support/time/linux/clock_gettime.h"
+#include "src/__support/time/units.h"
#include "src/errno/libc_errno.h"
-#include "src/time/linux/clockGetTimeImpl.h"
-
-#include <sys/syscall.h> // For syscall numbers.
-#include <time.h>
namespace LIBC_NAMESPACE {
LLVM_LIBC_FUNCTION(clock_t, clock, ()) {
+ using namespace time_units;
struct timespec ts;
- auto result = internal::clock_gettimeimpl(CLOCK_PROCESS_CPUTIME_ID, &ts);
+ auto result = internal::clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &ts);
if (!result.has_value()) {
libc_errno = result.error();
return -1;
@@ -34,15 +32,15 @@ LLVM_LIBC_FUNCTION(clock_t, clock, ()) {
cpp::numeric_limits<clock_t>::max() / CLOCKS_PER_SEC;
if (ts.tv_sec > CLOCK_SECS_MAX)
return clock_t(-1);
- if (ts.tv_nsec / 1000000000 > CLOCK_SECS_MAX - ts.tv_sec)
+ if (ts.tv_nsec / 1_s_ns > CLOCK_SECS_MAX - ts.tv_sec)
return clock_t(-1);
// For the integer computation converting tv_nsec to clocks to work
// correctly, we want CLOCKS_PER_SEC to be less than 1000000000.
- static_assert(1000000000 > CLOCKS_PER_SEC,
- "Expected CLOCKS_PER_SEC to be less than 1000000000.");
+ static_assert(1_s_ns > CLOCKS_PER_SEC,
+ "Expected CLOCKS_PER_SEC to be less than 1'000'000'000.");
return clock_t(ts.tv_sec * CLOCKS_PER_SEC +
- ts.tv_nsec / (1000000000 / CLOCKS_PER_SEC));
+ ts.tv_nsec / (1_s_ns / CLOCKS_PER_SEC));
}
} // namespace LIBC_NAMESPACE
diff --git a/src/time/linux/clock_gettime.cpp b/src/time/linux/clock_gettime.cpp
index 47e974a866c8..d7b8cfd245bc 100644
--- a/src/time/linux/clock_gettime.cpp
+++ b/src/time/linux/clock_gettime.cpp
@@ -7,21 +7,16 @@
//===----------------------------------------------------------------------===//
#include "src/time/clock_gettime.h"
-
-#include "src/__support/OSUtil/syscall.h" // For internal syscall function.
#include "src/__support/common.h"
+#include "src/__support/time/linux/clock_gettime.h"
#include "src/errno/libc_errno.h"
-#include "src/time/linux/clockGetTimeImpl.h"
-
-#include <sys/syscall.h> // For syscall numbers.
-#include <time.h>
namespace LIBC_NAMESPACE {
// TODO(michaelrj): Move this into time/linux with the other syscalls.
LLVM_LIBC_FUNCTION(int, clock_gettime,
(clockid_t clockid, struct timespec *ts)) {
- auto result = internal::clock_gettimeimpl(clockid, ts);
+ auto result = internal::clock_gettime(clockid, ts);
// A negative return value indicates an error with the magnitude of the
// value being the error code.
diff --git a/src/time/linux/gettimeofday.cpp b/src/time/linux/gettimeofday.cpp
index 07ab4d579176..f868f5ff4d4b 100644
--- a/src/time/linux/gettimeofday.cpp
+++ b/src/time/linux/gettimeofday.cpp
@@ -7,24 +7,24 @@
//===----------------------------------------------------------------------===//
#include "src/time/gettimeofday.h"
-
-#include "src/__support/OSUtil/syscall.h" // For internal syscall function.
+#include "hdr/time_macros.h"
+#include "hdr/types/suseconds_t.h"
#include "src/__support/common.h"
+#include "src/__support/time/linux/clock_gettime.h"
+#include "src/__support/time/units.h"
#include "src/errno/libc_errno.h"
-#include "src/time/linux/clockGetTimeImpl.h"
-
-#include <sys/syscall.h> // For syscall numbers.
namespace LIBC_NAMESPACE {
// TODO(michaelrj): Move this into time/linux with the other syscalls.
LLVM_LIBC_FUNCTION(int, gettimeofday,
(struct timeval * tv, [[maybe_unused]] void *unused)) {
+ using namespace time_units;
if (tv == nullptr)
return 0;
struct timespec ts;
- auto result = internal::clock_gettimeimpl(CLOCK_REALTIME, &ts);
+ auto result = internal::clock_gettime(CLOCK_REALTIME, &ts);
// A negative return value indicates an error with the magnitude of the
// value being the error code.
@@ -34,7 +34,7 @@ LLVM_LIBC_FUNCTION(int, gettimeofday,
}
tv->tv_sec = ts.tv_sec;
- tv->tv_usec = static_cast<suseconds_t>(ts.tv_nsec / 1000);
+ tv->tv_usec = static_cast<suseconds_t>(ts.tv_nsec / 1_us_ns);
return 0;
}
diff --git a/src/time/linux/time.cpp b/src/time/linux/time.cpp
index e286fae095b2..32f531efb6d1 100644
--- a/src/time/linux/time.cpp
+++ b/src/time/linux/time.cpp
@@ -6,22 +6,18 @@
//
//===----------------------------------------------------------------------===//
-#include "src/time/time_func.h"
-
-#include "src/__support/OSUtil/syscall.h" // For internal syscall function.
+#include "hdr/time_macros.h"
#include "src/__support/common.h"
+#include "src/__support/time/linux/clock_gettime.h"
#include "src/errno/libc_errno.h"
-#include "src/time/linux/clockGetTimeImpl.h"
-
-#include <sys/syscall.h> // For syscall numbers.
-#include <time.h>
+#include "src/time/time_func.h"
namespace LIBC_NAMESPACE {
LLVM_LIBC_FUNCTION(time_t, time, (time_t * tp)) {
// TODO: Use the Linux VDSO to fetch the time and avoid the syscall.
struct timespec ts;
- auto result = internal::clock_gettimeimpl(CLOCK_REALTIME, &ts);
+ auto result = internal::clock_gettime(CLOCK_REALTIME, &ts);
if (!result.has_value()) {
libc_errno = result.error();
return -1;
diff --git a/src/time/nanosleep.h b/src/time/nanosleep.h
index 757394232c07..2309666b2304 100644
--- a/src/time/nanosleep.h
+++ b/src/time/nanosleep.h
@@ -9,11 +9,11 @@
#ifndef LLVM_LIBC_SRC_TIME_NANOSLEEP_H
#define LLVM_LIBC_SRC_TIME_NANOSLEEP_H
-#include <time.h>
+#include "hdr/types/struct_timespec.h"
namespace LIBC_NAMESPACE {
-int nanosleep(const struct timespec *req, struct timespec *rem);
+int nanosleep(const timespec *req, timespec *rem);
} // namespace LIBC_NAMESPACE
diff --git a/src/time/time_func.h b/src/time/time_func.h
index beb02020b575..2a5239220942 100644
--- a/src/time/time_func.h
+++ b/src/time/time_func.h
@@ -9,7 +9,7 @@
#ifndef LLVM_LIBC_SRC_TIME_TIME_FUNC_H
#define LLVM_LIBC_SRC_TIME_TIME_FUNC_H
-#include <time.h>
+#include "hdr/types/time_t.h"
// Note this header file is named time_func.h to avoid conflicts with the
// public header file time.h.
diff --git a/test/UnitTest/FPMatcher.h b/test/UnitTest/FPMatcher.h
index c58c322c981e..26af5cec02b5 100644
--- a/test/UnitTest/FPMatcher.h
+++ b/test/UnitTest/FPMatcher.h
@@ -159,18 +159,18 @@ template <typename T> struct FPTest : public Test {
#define EXPECT_FP_EXCEPTION(expected) \
do { \
if (math_errhandling & MATH_ERREXCEPT) { \
- EXPECT_GE(LIBC_NAMESPACE::fputil::test_except(FE_ALL_EXCEPT) & \
- (expected), \
- expected); \
+ EXPECT_EQ(LIBC_NAMESPACE::fputil::test_except(FE_ALL_EXCEPT) & \
+ ((expected) ? (expected) : FE_ALL_EXCEPT), \
+ (expected)); \
} \
} while (0)
#define ASSERT_FP_EXCEPTION(expected) \
do { \
if (math_errhandling & MATH_ERREXCEPT) { \
- ASSERT_GE(LIBC_NAMESPACE::fputil::test_except(FE_ALL_EXCEPT) & \
- (expected), \
- expected); \
+ ASSERT_EQ(LIBC_NAMESPACE::fputil::test_except(FE_ALL_EXCEPT) & \
+ ((expected) ? (expected) : FE_ALL_EXCEPT), \
+ (expected)); \
} \
} while (0)
@@ -178,24 +178,14 @@ template <typename T> struct FPTest : public Test {
do { \
LIBC_NAMESPACE::fputil::clear_except(FE_ALL_EXCEPT); \
EXPECT_FP_EQ(expected_val, actual_val); \
- if (math_errhandling & MATH_ERREXCEPT) { \
- EXPECT_GE(LIBC_NAMESPACE::fputil::test_except(FE_ALL_EXCEPT) & \
- (expected_except), \
- expected_except); \
- LIBC_NAMESPACE::fputil::clear_except(FE_ALL_EXCEPT); \
- } \
+ EXPECT_FP_EXCEPTION(expected_except); \
} while (0)
#define EXPECT_FP_IS_NAN_WITH_EXCEPTION(actual_val, expected_except) \
do { \
LIBC_NAMESPACE::fputil::clear_except(FE_ALL_EXCEPT); \
EXPECT_FP_IS_NAN(actual_val); \
- if (math_errhandling & MATH_ERREXCEPT) { \
- EXPECT_GE(LIBC_NAMESPACE::fputil::test_except(FE_ALL_EXCEPT) & \
- (expected_except), \
- expected_except); \
- LIBC_NAMESPACE::fputil::clear_except(FE_ALL_EXCEPT); \
- } \
+ EXPECT_FP_EXCEPTION(expected_except); \
} while (0)
#define EXPECT_FP_EQ_ALL_ROUNDING(expected, actual) \
diff --git a/test/src/__support/CPP/mutex_test.cpp b/test/src/__support/CPP/mutex_test.cpp
new file mode 100644
index 000000000000..a68c84cfc78a
--- /dev/null
+++ b/test/src/__support/CPP/mutex_test.cpp
@@ -0,0 +1,79 @@
+//===-- Unittests for mutex -----------------------------------------------===//
+//
+// 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/CPP/mutex.h"
+#include "test/UnitTest/Test.h"
+
+using LIBC_NAMESPACE::cpp::adopt_lock;
+using LIBC_NAMESPACE::cpp::lock_guard;
+
+// Simple struct for testing cpp::lock_guard. It defines methods 'lock' and
+// 'unlock' which are required for the cpp::lock_guard class template.
+struct Mutex {
+ // Flag to show whether this mutex is locked.
+ bool locked = false;
+
+ // Flag to show if this mutex has been double locked.
+ bool double_locked = false;
+
+ // Flag to show if this mutex has been double unlocked.
+ bool double_unlocked = false;
+
+ Mutex() {}
+
+ void lock() {
+ if (locked)
+ double_locked = true;
+
+ locked = true;
+ }
+
+ void unlock() {
+ if (!locked)
+ double_unlocked = true;
+
+ locked = false;
+ }
+};
+
+TEST(LlvmLibcMutexTest, Basic) {
+ Mutex m;
+ ASSERT_FALSE(m.locked);
+ ASSERT_FALSE(m.double_locked);
+ ASSERT_FALSE(m.double_unlocked);
+
+ {
+ lock_guard lg(m);
+ ASSERT_TRUE(m.locked);
+ ASSERT_FALSE(m.double_locked);
+ }
+
+ ASSERT_FALSE(m.locked);
+ ASSERT_FALSE(m.double_unlocked);
+}
+
+TEST(LlvmLibcMutexTest, AcquireLocked) {
+ Mutex m;
+ ASSERT_FALSE(m.locked);
+ ASSERT_FALSE(m.double_locked);
+ ASSERT_FALSE(m.double_unlocked);
+
+ // Lock the mutex before placing a lock guard on it.
+ m.lock();
+ ASSERT_TRUE(m.locked);
+ ASSERT_FALSE(m.double_locked);
+
+ {
+ lock_guard lg(m, adopt_lock);
+ ASSERT_TRUE(m.locked);
+ ASSERT_FALSE(m.double_locked);
+ }
+
+ ASSERT_FALSE(m.locked);
+ ASSERT_FALSE(m.double_unlocked);
+}
diff --git a/test/src/math/FModTest.h b/test/src/math/FModTest.h
index f1015d6497fc..32c009ab8828 100644
--- a/test/src/math/FModTest.h
+++ b/test/src/math/FModTest.h
@@ -18,10 +18,10 @@
#include "hdr/math_macros.h"
#define TEST_SPECIAL(x, y, expected, dom_err, expected_exception) \
+ LIBC_NAMESPACE::fputil::clear_except(FE_ALL_EXCEPT); \
EXPECT_FP_EQ(expected, f(x, y)); \
EXPECT_MATH_ERRNO((dom_err) ? EDOM : 0); \
- EXPECT_FP_EXCEPTION(expected_exception); \
- LIBC_NAMESPACE::fputil::clear_except(FE_ALL_EXCEPT)
+ EXPECT_FP_EXCEPTION(expected_exception)
#define TEST_REGULAR(x, y, expected) TEST_SPECIAL(x, y, expected, false, 0)
diff --git a/test/src/math/RoundToIntegerTest.h b/test/src/math/RoundToIntegerTest.h
index 0f052ba42a46..d40e15080087 100644
--- a/test/src/math/RoundToIntegerTest.h
+++ b/test/src/math/RoundToIntegerTest.h
@@ -57,12 +57,13 @@ private:
ASSERT_EQ(func(input), expected);
+ // TODO: Handle the !expectError case. It used to expect
+ // 0 for errno and exceptions, but this doesn't hold for
+ // all math functions using RoundToInteger test:
+ // https://github.com/llvm/llvm-project/pull/88816
if (expectError) {
ASSERT_FP_EXCEPTION(FE_INVALID);
ASSERT_MATH_ERRNO(EDOM);
- } else {
- ASSERT_FP_EXCEPTION(0);
- ASSERT_MATH_ERRNO(0);
}
}
diff --git a/test/src/math/atanf_test.cpp b/test/src/math/atanf_test.cpp
index 4fa7badaf736..376b4724b5a3 100644
--- a/test/src/math/atanf_test.cpp
+++ b/test/src/math/atanf_test.cpp
@@ -21,21 +21,29 @@ using LlvmLibcAtanfTest = LIBC_NAMESPACE::testing::FPTest<float>;
namespace mpfr = LIBC_NAMESPACE::testing::mpfr;
+// TODO: This test needs to have its checks for exceptions, errno
+// tightened
TEST_F(LlvmLibcAtanfTest, SpecialNumbers) {
LIBC_NAMESPACE::libc_errno = 0;
LIBC_NAMESPACE::fputil::clear_except(FE_ALL_EXCEPT);
EXPECT_FP_EQ_ALL_ROUNDING(aNaN, LIBC_NAMESPACE::atanf(aNaN));
- EXPECT_FP_EXCEPTION(0);
+ // TODO: Uncomment these checks later, RoundingMode affects running
+ // tests in this way https://github.com/llvm/llvm-project/issues/90653.
+ // EXPECT_FP_EXCEPTION(0);
EXPECT_MATH_ERRNO(0);
LIBC_NAMESPACE::fputil::clear_except(FE_ALL_EXCEPT);
EXPECT_FP_EQ_ALL_ROUNDING(0.0f, LIBC_NAMESPACE::atanf(0.0f));
- EXPECT_FP_EXCEPTION(0);
+ // TODO: Uncomment these checks later, RoundingMode affects running
+ // tests in this way https://github.com/llvm/llvm-project/issues/90653.
+ // EXPECT_FP_EXCEPTION(0);
EXPECT_MATH_ERRNO(0);
LIBC_NAMESPACE::fputil::clear_except(FE_ALL_EXCEPT);
EXPECT_FP_EQ_ALL_ROUNDING(-0.0f, LIBC_NAMESPACE::atanf(-0.0f));
- EXPECT_FP_EXCEPTION(0);
+ // TODO: Uncomment these checks later, RoundingMode affects running
+ // tests in this way https://github.com/llvm/llvm-project/issues/90653.
+ // EXPECT_FP_EXCEPTION(0);
EXPECT_MATH_ERRNO(0);
}
diff --git a/test/src/math/atanhf_test.cpp b/test/src/math/atanhf_test.cpp
index 7fc8c70d1386..b0505e4c1182 100644
--- a/test/src/math/atanhf_test.cpp
+++ b/test/src/math/atanhf_test.cpp
@@ -21,32 +21,40 @@ using LlvmLibcAtanhfTest = LIBC_NAMESPACE::testing::FPTest<float>;
namespace mpfr = LIBC_NAMESPACE::testing::mpfr;
+// TODO: This test needs to have its checks for exceptions, errno
+// tightened https://github.com/llvm/llvm-project/issues/88819.
TEST_F(LlvmLibcAtanhfTest, SpecialNumbers) {
LIBC_NAMESPACE::libc_errno = 0;
LIBC_NAMESPACE::fputil::clear_except(FE_ALL_EXCEPT);
EXPECT_FP_EQ_ALL_ROUNDING(aNaN, LIBC_NAMESPACE::atanhf(aNaN));
- EXPECT_FP_EXCEPTION(0);
+ // TODO: Uncomment these checks later, RoundingMode affects running
+ // tests in this way https://github.com/llvm/llvm-project/issues/90653.
+ // EXPECT_FP_EXCEPTION(0);
EXPECT_MATH_ERRNO(0);
LIBC_NAMESPACE::fputil::clear_except(FE_ALL_EXCEPT);
EXPECT_FP_EQ_ALL_ROUNDING(0.0f, LIBC_NAMESPACE::atanhf(0.0f));
- EXPECT_FP_EXCEPTION(0);
+ // See above TODO
+ // EXPECT_FP_EXCEPTION(0);
EXPECT_MATH_ERRNO(0);
LIBC_NAMESPACE::fputil::clear_except(FE_ALL_EXCEPT);
EXPECT_FP_EQ_ALL_ROUNDING(-0.0f, LIBC_NAMESPACE::atanhf(-0.0f));
- EXPECT_FP_EXCEPTION(0);
+ // See above TODO
+ // EXPECT_FP_EXCEPTION(0);
EXPECT_MATH_ERRNO(0);
LIBC_NAMESPACE::fputil::clear_except(FE_ALL_EXCEPT);
EXPECT_FP_EQ_ALL_ROUNDING(inf, LIBC_NAMESPACE::atanhf(1.0f));
- EXPECT_FP_EXCEPTION(FE_DIVBYZERO);
+ // See above TODO
+ // EXPECT_FP_EXCEPTION(FE_DIVBYZERO);
EXPECT_MATH_ERRNO(ERANGE);
LIBC_NAMESPACE::fputil::clear_except(FE_ALL_EXCEPT);
EXPECT_FP_EQ_ALL_ROUNDING(neg_inf, LIBC_NAMESPACE::atanhf(-1.0f));
- EXPECT_FP_EXCEPTION(FE_DIVBYZERO);
+ // See above TODO
+ // EXPECT_FP_EXCEPTION(FE_DIVBYZERO);
EXPECT_MATH_ERRNO(ERANGE);
auto bt = FPBits(1.0f);
@@ -54,33 +62,37 @@ TEST_F(LlvmLibcAtanhfTest, SpecialNumbers) {
LIBC_NAMESPACE::fputil::clear_except(FE_ALL_EXCEPT);
EXPECT_FP_EQ_ALL_ROUNDING(aNaN, LIBC_NAMESPACE::atanhf(bt.get_val()));
- EXPECT_FP_EXCEPTION(FE_INVALID);
+ // EXPECT_FP_EXCEPTION(FE_INVALID);
EXPECT_MATH_ERRNO(EDOM);
LIBC_NAMESPACE::fputil::clear_except(FE_ALL_EXCEPT);
bt.set_sign(Sign::NEG);
EXPECT_FP_EQ_ALL_ROUNDING(aNaN, LIBC_NAMESPACE::atanhf(bt.get_val()));
- EXPECT_FP_EXCEPTION(FE_INVALID);
+ // See above TODO
+ // EXPECT_FP_EXCEPTION(FE_INVALID);
EXPECT_MATH_ERRNO(EDOM);
LIBC_NAMESPACE::fputil::clear_except(FE_ALL_EXCEPT);
EXPECT_FP_EQ_ALL_ROUNDING(aNaN, LIBC_NAMESPACE::atanhf(2.0f));
- EXPECT_FP_EXCEPTION(FE_INVALID);
+ // See above TODO
+ // EXPECT_FP_EXCEPTION(FE_INVALID);
EXPECT_MATH_ERRNO(EDOM);
LIBC_NAMESPACE::fputil::clear_except(FE_ALL_EXCEPT);
EXPECT_FP_EQ_ALL_ROUNDING(aNaN, LIBC_NAMESPACE::atanhf(-2.0f));
- EXPECT_FP_EXCEPTION(FE_INVALID);
+ // EXPECT_FP_EXCEPTION(FE_INVALID);
EXPECT_MATH_ERRNO(EDOM);
LIBC_NAMESPACE::fputil::clear_except(FE_ALL_EXCEPT);
EXPECT_FP_EQ_ALL_ROUNDING(aNaN, LIBC_NAMESPACE::atanhf(inf));
- EXPECT_FP_EXCEPTION(FE_INVALID);
+ // See above TODO
+ // EXPECT_FP_EXCEPTION(FE_INVALID);
EXPECT_MATH_ERRNO(EDOM);
bt.set_sign(Sign::NEG);
EXPECT_FP_EQ_ALL_ROUNDING(aNaN, LIBC_NAMESPACE::atanhf(neg_inf));
- EXPECT_FP_EXCEPTION(FE_INVALID);
+ // See above TODO
+ // EXPECT_FP_EXCEPTION(FE_INVALID);
EXPECT_MATH_ERRNO(EDOM);
}
diff --git a/test/src/math/powf_test.cpp b/test/src/math/powf_test.cpp
index 69135593cd32..797913e5b7ee 100644
--- a/test/src/math/powf_test.cpp
+++ b/test/src/math/powf_test.cpp
@@ -22,14 +22,21 @@ using LIBC_NAMESPACE::testing::tlog;
namespace mpfr = LIBC_NAMESPACE::testing::mpfr;
TEST_F(LlvmLibcPowfTest, TrickyInputs) {
- constexpr int N = 11;
+ constexpr int N = 13;
constexpr mpfr::BinaryInput<float> INPUTS[N] = {
- {0x1.290bbp-124f, 0x1.1e6d92p-25f}, {0x1.2e9fb6p+5f, -0x1.1b82b6p-18f},
- {0x1.6877f6p+60f, -0x1.75f1c6p-4f}, {0x1.0936acp-63f, -0x1.55200ep-15f},
- {0x1.d6d72ap+43f, -0x1.749ccap-5f}, {0x1.4afb2ap-40f, 0x1.063198p+0f},
- {0x1.0124dep+0f, -0x1.fdb016p+9f}, {0x1.1058p+0f, 0x1.ap+64f},
- {0x1.1058p+0f, -0x1.ap+64f}, {0x1.1058p+0f, 0x1.ap+64f},
+ {0x1.290bbp-124f, 0x1.1e6d92p-25f},
+ {0x1.2e9fb6p+5f, -0x1.1b82b6p-18f},
+ {0x1.6877f6p+60f, -0x1.75f1c6p-4f},
+ {0x1.0936acp-63f, -0x1.55200ep-15f},
+ {0x1.d6d72ap+43f, -0x1.749ccap-5f},
+ {0x1.4afb2ap-40f, 0x1.063198p+0f},
+ {0x1.0124dep+0f, -0x1.fdb016p+9f},
+ {0x1.1058p+0f, 0x1.ap+64f},
+ {0x1.1058p+0f, -0x1.ap+64f},
+ {0x1.1058p+0f, 0x1.ap+64f},
{0x1.fa32d4p-1f, 0x1.67a62ep+12f},
+ {-0x1.8p-49, 0x1.8p+1},
+ {0x1.8p-48, 0x1.8p+1},
};
for (int i = 0; i < N; ++i) {
diff --git a/test/src/math/smoke/NextAfterTest.h b/test/src/math/smoke/NextAfterTest.h
index 65dba9338285..d65ccdf8e70c 100644
--- a/test/src/math/smoke/NextAfterTest.h
+++ b/test/src/math/smoke/NextAfterTest.h
@@ -18,6 +18,8 @@
#include "test/UnitTest/FPMatcher.h"
#include "test/UnitTest/Test.h"
+// TODO: Strengthen errno,exception checks and remove these assert macros
+// after new matchers/test fixtures are added
#define ASSERT_FP_EQ_WITH_EXCEPTION(result, expected, expected_exception) \
ASSERT_FP_EQ(result, expected); \
ASSERT_FP_EXCEPTION(expected_exception); \
diff --git a/test/src/math/smoke/NextTowardTest.h b/test/src/math/smoke/NextTowardTest.h
index 1894d324b085..a24ec9ff6bd8 100644
--- a/test/src/math/smoke/NextTowardTest.h
+++ b/test/src/math/smoke/NextTowardTest.h
@@ -19,6 +19,8 @@
#include "test/UnitTest/FPMatcher.h"
#include "test/UnitTest/Test.h"
+// TODO: Strengthen errno,exception checks and remove these assert macros
+// after new matchers/test fixtures are added
#define ASSERT_FP_EQ_WITH_EXCEPTION(result, expected, expected_exception) \
ASSERT_FP_EQ(result, expected); \
ASSERT_FP_EXCEPTION(expected_exception); \
diff --git a/test/src/math/smoke/RoundToIntegerTest.h b/test/src/math/smoke/RoundToIntegerTest.h
index 50bcd4a6a76c..3ff311f46b05 100644
--- a/test/src/math/smoke/RoundToIntegerTest.h
+++ b/test/src/math/smoke/RoundToIntegerTest.h
@@ -28,14 +28,7 @@ public:
typedef I (*RoundToIntegerFunc)(F);
private:
- using FPBits = LIBC_NAMESPACE::fputil::FPBits<F>;
- using StorageType = typename FPBits::StorageType;
-
- const F zero = FPBits::zero(Sign::POS).get_val();
- const F neg_zero = FPBits::zero(Sign::NEG).get_val();
- const F inf = FPBits::inf(Sign::POS).get_val();
- const F neg_inf = FPBits::inf(Sign::NEG).get_val();
- const F nan = FPBits::quiet_nan().get_val();
+ DECLARE_SPECIAL_CONSTANTS(F)
static constexpr StorageType MAX_SUBNORMAL =
FPBits::max_subnormal().uintval();
@@ -52,12 +45,13 @@ private:
ASSERT_EQ(func(input), expected);
+ // TODO: Handle the !expectError case. It used to expect
+ // 0 for errno and exceptions, but this doesn't hold for
+ // all math functions using RoundToInteger test:
+ // https://github.com/llvm/llvm-project/pull/88816
if (expectError) {
ASSERT_FP_EXCEPTION(FE_INVALID);
ASSERT_MATH_ERRNO(EDOM);
- } else {
- ASSERT_FP_EXCEPTION(0);
- ASSERT_MATH_ERRNO(0);
}
}
@@ -81,7 +75,7 @@ public:
// libc/CMakeLists.txt is not forwarded to C++.
#if LIBC_COPT_IMPLEMENTATION_DEFINED_TEST_BEHAVIOR
// Result is not well-defined, we always returns INTEGER_MAX
- test_one_input(func, nan, INTEGER_MAX, true);
+ test_one_input(func, aNaN, INTEGER_MAX, true);
#endif // LIBC_COPT_IMPLEMENTATION_DEFINED_TEST_BEHAVIOR
}
diff --git a/test/src/math/smoke/atan2f_test.cpp b/test/src/math/smoke/atan2f_test.cpp
index f81d140fefc5..32a28cfdfeaa 100644
--- a/test/src/math/smoke/atan2f_test.cpp
+++ b/test/src/math/smoke/atan2f_test.cpp
@@ -18,33 +18,43 @@ using LlvmLibcAtan2fTest = LIBC_NAMESPACE::testing::FPTest<float>;
TEST_F(LlvmLibcAtan2fTest, SpecialNumbers) {
LIBC_NAMESPACE::libc_errno = 0;
+ // TODO: Strengthen errno,exception checks and remove these assert macros
+ // after new matchers/test fixtures are added see:
+ // https://github.com/llvm/llvm-project/issues/90653.
LIBC_NAMESPACE::fputil::clear_except(FE_ALL_EXCEPT);
EXPECT_FP_EQ_ALL_ROUNDING(aNaN, LIBC_NAMESPACE::atan2f(aNaN, zero));
- EXPECT_FP_EXCEPTION(0);
+ // TODO: Uncomment these checks later, RoundingMode affects running
+ // tests in this way https://github.com/llvm/llvm-project/issues/90653.
+ // EXPECT_FP_EXCEPTION(0);
EXPECT_MATH_ERRNO(0);
LIBC_NAMESPACE::fputil::clear_except(FE_ALL_EXCEPT);
EXPECT_FP_EQ_ALL_ROUNDING(aNaN, LIBC_NAMESPACE::atan2f(1.0f, aNaN));
- EXPECT_FP_EXCEPTION(0);
+ // See above TODO
+ // EXPECT_FP_EXCEPTION(0);
EXPECT_MATH_ERRNO(0);
LIBC_NAMESPACE::fputil::clear_except(FE_ALL_EXCEPT);
EXPECT_FP_EQ_ALL_ROUNDING(0.0f, LIBC_NAMESPACE::atan2f(zero, zero));
- EXPECT_FP_EXCEPTION(0);
+ // See above TODO
+ // EXPECT_FP_EXCEPTION(0);
EXPECT_MATH_ERRNO(0);
LIBC_NAMESPACE::fputil::clear_except(FE_ALL_EXCEPT);
EXPECT_FP_EQ_ALL_ROUNDING(-0.0f, LIBC_NAMESPACE::atan2f(-0.0f, zero));
- EXPECT_FP_EXCEPTION(0);
+ // See above TODO
+ // EXPECT_FP_EXCEPTION(0);
EXPECT_MATH_ERRNO(0);
LIBC_NAMESPACE::fputil::clear_except(FE_ALL_EXCEPT);
EXPECT_FP_EQ_ALL_ROUNDING(0.0f, LIBC_NAMESPACE::atan2f(1.0f, inf));
- EXPECT_FP_EXCEPTION(0);
+ // See above TODO
+ // EXPECT_FP_EXCEPTION(0);
EXPECT_MATH_ERRNO(0);
LIBC_NAMESPACE::fputil::clear_except(FE_ALL_EXCEPT);
EXPECT_FP_EQ_ALL_ROUNDING(-0.0f, LIBC_NAMESPACE::atan2f(-1.0f, inf));
- EXPECT_FP_EXCEPTION(0);
+ // See above TODO
+ // EXPECT_FP_EXCEPTION(0);
EXPECT_MATH_ERRNO(0);
}
diff --git a/test/src/math/smoke/atanf_test.cpp b/test/src/math/smoke/atanf_test.cpp
index 3800c2334b92..56bf2f951b33 100644
--- a/test/src/math/smoke/atanf_test.cpp
+++ b/test/src/math/smoke/atanf_test.cpp
@@ -21,18 +21,25 @@ using LlvmLibcAtanfTest = LIBC_NAMESPACE::testing::FPTest<float>;
TEST_F(LlvmLibcAtanfTest, SpecialNumbers) {
LIBC_NAMESPACE::libc_errno = 0;
+ // TODO: Strengthen errno,exception checks and remove these assert macros
+ // after new matchers/test fixtures are added
+ // https://github.com/llvm/llvm-project/issues/90653
LIBC_NAMESPACE::fputil::clear_except(FE_ALL_EXCEPT);
EXPECT_FP_EQ_ALL_ROUNDING(aNaN, LIBC_NAMESPACE::atanf(aNaN));
- EXPECT_FP_EXCEPTION(0);
+ // TODO: Uncomment these checks later, RoundingMode affects running
+ // tests in this way https://github.com/llvm/llvm-project/issues/90653.
+ // EXPECT_FP_EXCEPTION(0);
EXPECT_MATH_ERRNO(0);
LIBC_NAMESPACE::fputil::clear_except(FE_ALL_EXCEPT);
EXPECT_FP_EQ_ALL_ROUNDING(0.0f, LIBC_NAMESPACE::atanf(0.0f));
- EXPECT_FP_EXCEPTION(0);
+ // See above TODO
+ // EXPECT_FP_EXCEPTION(0);
EXPECT_MATH_ERRNO(0);
LIBC_NAMESPACE::fputil::clear_except(FE_ALL_EXCEPT);
EXPECT_FP_EQ_ALL_ROUNDING(-0.0f, LIBC_NAMESPACE::atanf(-0.0f));
- EXPECT_FP_EXCEPTION(0);
+ // See above TODO
+ // EXPECT_FP_EXCEPTION(0);
EXPECT_MATH_ERRNO(0);
}
diff --git a/test/src/math/smoke/atanhf_test.cpp b/test/src/math/smoke/atanhf_test.cpp
index fc3e2dd9bc54..2d2acfeeab4e 100644
--- a/test/src/math/smoke/atanhf_test.cpp
+++ b/test/src/math/smoke/atanhf_test.cpp
@@ -19,22 +19,28 @@
using LlvmLibcAtanhfTest = LIBC_NAMESPACE::testing::FPTest<float>;
TEST_F(LlvmLibcAtanhfTest, SpecialNumbers) {
-
LIBC_NAMESPACE::libc_errno = 0;
+ // TODO: Strengthen errno,exception checks and remove these assert macros
+ // after new matchers/test fixtures are added, see:
+ // https://github.com/llvm/llvm-project/issues/90653
LIBC_NAMESPACE::fputil::clear_except(FE_ALL_EXCEPT);
EXPECT_FP_EQ_ALL_ROUNDING(aNaN, LIBC_NAMESPACE::atanhf(aNaN));
- EXPECT_FP_EXCEPTION(0);
+ // TODO: Uncomment these checks later, RoundingMode affects running
+ // tests in this way https://github.com/llvm/llvm-project/issues/90653.
+ // EXPECT_FP_EXCEPTION(0);
EXPECT_MATH_ERRNO(0);
LIBC_NAMESPACE::fputil::clear_except(FE_ALL_EXCEPT);
EXPECT_FP_EQ_ALL_ROUNDING(0.0f, LIBC_NAMESPACE::atanhf(0.0f));
- EXPECT_FP_EXCEPTION(0);
+ // See above TODO
+ // EXPECT_FP_EXCEPTION(0);
EXPECT_MATH_ERRNO(0);
LIBC_NAMESPACE::fputil::clear_except(FE_ALL_EXCEPT);
EXPECT_FP_EQ_ALL_ROUNDING(-0.0f, LIBC_NAMESPACE::atanhf(-0.0f));
- EXPECT_FP_EXCEPTION(0);
+ // See above TODO
+ // EXPECT_FP_EXCEPTION(0);
EXPECT_MATH_ERRNO(0);
EXPECT_FP_EQ_WITH_EXCEPTION(inf, LIBC_NAMESPACE::atanhf(1.0f), FE_DIVBYZERO);