9 #define HAS_BUILTIN __has_builtin
11 #define HAS_BUILTIN(x) (0)
15 #define force_inline [[gnu::always_inline]]
16 #elif defined(_MSC_VER)
17 #define force_inline __forceinline
19 #define force_inline inline
22 #if defined(__GNUC__) || HAS_BUILTIN(__builtin_expect)
23 /* likely() optimizes for the case where the condition is true. The condition
24 * is not required to be true, but it can result in more optimal code for the
25 * true path at the expense of a less optimal false path.
28 force_inline
constexpr bool likely(T
&& expr
) noexcept
29 { return __builtin_expect(static_cast<bool>(std::forward
<T
>(expr
)), true); }
30 /* The opposite of likely(), optimizing for the case where the condition is
34 force_inline
constexpr bool unlikely(T
&& expr
) noexcept
35 { return __builtin_expect(static_cast<bool>(std::forward
<T
>(expr
)), false); }
40 force_inline
constexpr bool likely(T
&& expr
) noexcept
41 { return static_cast<bool>(std::forward
<T
>(expr
)); }
43 force_inline
constexpr bool unlikely(T
&& expr
) noexcept
44 { return static_cast<bool>(std::forward
<T
>(expr
)); }
46 #define LIKELY(x) (likely(x))
47 #define UNLIKELY(x) (unlikely(x))
49 #if HAS_BUILTIN(__builtin_assume)
50 /* Unlike LIKELY, ASSUME requires the condition to be true or else it invokes
51 * undefined behavior. It's essentially an assert without actually checking the
52 * condition at run-time, allowing for stronger optimizations than LIKELY.
54 #define ASSUME __builtin_assume
55 #elif defined(_MSC_VER)
56 #define ASSUME __assume
57 #elif defined(__GNUC__)
58 #define ASSUME(x) do { if(x) break; __builtin_unreachable(); } while(0)
60 #define ASSUME(x) ((void)0)
65 template<std::size_t alignment
, typename T
>
66 force_inline
constexpr auto assume_aligned(T
*ptr
) noexcept
68 #ifdef __cpp_lib_assume_aligned
69 return std::assume_aligned
<alignment
,T
>(ptr
);
70 #elif defined(__clang__) || (defined(__GNUC__) && !defined(__ICC))
71 return static_cast<T
*>(__builtin_assume_aligned(ptr
, alignment
));
72 #elif defined(_MSC_VER)
73 constexpr std::size_t alignment_mask
{(1<<alignment
) - 1};
74 if((reinterpret_cast<std::uintptr_t>(ptr
)&alignment_mask
) == 0)
78 __assume_aligned(ptr
, alignment
);
87 #endif /* OPTHELPERS_H */