[libc-commits] [libc] [libc] Fix LIBC_LIKELY/LIBC_UNLIKELY and add LIBC_NOINLINE. (PR #230505)

via libc-commits libc-commits at lists.llvm.org
Fri Oct 9 06:47:46 PDT 2026


https://github.com/lntue created https://github.com/llvm/llvm-project/pull/230505

`__builtin_expect(value, expected)` requires the second argument to be a constant expression.  Previously, `LIBC_LIKELY` and `LIBC_UNLIKELY` wrapped `__builtin_expect(value, expected)` inside `details::expects_bool_condition(T value, T expected)`, where `expected` was a function parameter rather than a constant expression. So the hints were silently dropped by the compilers.

Also add LIBC_NOINLINE macro to `attributes.h` to outlining slow paths.

>From 5d789a27c911aebbaffc7e1b19b45beeac417875 Mon Sep 17 00:00:00 2001
From: Tue Ly <lntue.h at gmail.com>
Date: Fri, 9 Oct 2026 13:41:59 +0000
Subject: [PATCH] [libc] Fix LIBC_LIKELY/LIBC_UNLIKELY and add LIBC_NOINLINE.

`__builtin_expect(value, expected)` requires the second argument to be a constant
expression.  Previously, `LIBC_LIKELY` and `LIBC_UNLIKELY` wrapped
`__builtin_expect(value, expected)` inside `details::expects_bool_condition(T value, T expected)`,
where `expected` was a function parameter rather than a constant expression.
So the hints were silently dropped by the compilers.

Also add LIBC_NOINLINE macro to `attributes.h` to outlining slow paths.
---
 libc/src/__support/macros/attributes.h   |  8 ++++++++
 libc/src/__support/macros/optimization.h | 15 +++++++++++----
 2 files changed, 19 insertions(+), 4 deletions(-)

diff --git a/libc/src/__support/macros/attributes.h b/libc/src/__support/macros/attributes.h
index 1e8ebc13fea9a4..e251f917d9850b 100644
--- a/libc/src/__support/macros/attributes.h
+++ b/libc/src/__support/macros/attributes.h
@@ -37,6 +37,14 @@
 #define LIBC_ALWAYS_INLINE LIBC_INLINE
 #endif // __has_attribute(always_inline)
 
+#if __has_attribute(noinline)
+#define LIBC_NOINLINE __attribute__((noinline))
+#elif defined(LIBC_COMPILER_IS_MSVC) || defined(_MSC_VER)
+#define LIBC_NOINLINE __declspec(noinline)
+#else
+#define LIBC_NOINLINE
+#endif // __has_attribute(noinline)
+
 #ifndef LIBC_HAS_BUILTIN_IS_CONSTANT_EVALUATED
 #if (defined(LIBC_COMPILER_IS_GCC) && (LIBC_COMPILER_GCC_VER >= 900)) ||       \
     (defined(LIBC_COMPILER_IS_CLANG) && LIBC_COMPILER_CLANG_VER >= 900)
diff --git a/libc/src/__support/macros/optimization.h b/libc/src/__support/macros/optimization.h
index 51091b6d464043..fa62887a250c50 100644
--- a/libc/src/__support/macros/optimization.h
+++ b/libc/src/__support/macros/optimization.h
@@ -16,17 +16,24 @@
 
 // We use a template to implement likely/unlikely to make sure that we don't
 // accidentally pass an integer.
+// Note that `__builtin_expect` requires the second argument to be a constant
+// expression.
 namespace LIBC_NAMESPACE_DECL {
 namespace details {
 template <typename T>
-LIBC_INLINE constexpr bool expects_bool_condition(T value, T expected) {
-  return __builtin_expect(value, expected);
+LIBC_ALWAYS_INLINE constexpr bool expects_bool_condition(T value) = delete;
+
+template <>
+LIBC_ALWAYS_INLINE constexpr bool expects_bool_condition<bool>(bool value) {
+  return value;
 }
 } // namespace details
 } // namespace LIBC_NAMESPACE_DECL
-#define LIBC_LIKELY(x) LIBC_NAMESPACE::details::expects_bool_condition(x, true)
+#define LIBC_LIKELY(x)                                                         \
+  (__builtin_expect(LIBC_NAMESPACE::details::expects_bool_condition((x)), true))
 #define LIBC_UNLIKELY(x)                                                       \
-  LIBC_NAMESPACE::details::expects_bool_condition(x, false)
+  (__builtin_expect(LIBC_NAMESPACE::details::expects_bool_condition((x)),      \
+                    false))
 
 #if defined(LIBC_COMPILER_IS_CLANG)
 #define LIBC_LOOP_NOUNROLL _Pragma("nounroll")



More information about the libc-commits mailing list