Index: include/__config =================================================================== --- include/__config +++ include/__config @@ -489,6 +489,10 @@ #define _LIBCPP_HAS_NO_CXX20_CHRONO_LITERALS #endif +#if __has_builtin(__builtin_assume_aligned) +#define _LIBCPP_HAS_BUILTIN_ASSUME_ALIGNED +#endif + #elif defined(_LIBCPP_COMPILER_GCC) #define _ALIGNAS(x) __attribute__((__aligned__(x))) @@ -571,6 +575,8 @@ #define _LIBCPP_HAS_UNIQUE_OBJECT_REPRESENTATIONS #endif +#define _LIBCPP_HAS_BUILTIN_ASSUME_ALIGNED + #define _LIBCPP_ALWAYS_INLINE __attribute__ ((__always_inline__)) #elif defined(_LIBCPP_COMPILER_MSVC) Index: include/memory =================================================================== --- include/memory +++ include/memory @@ -645,6 +645,10 @@ void* align(size_t alignment, size_t size, void*& ptr, size_t& space); +// [ptr.aligned], pointer alignment hint +template + [[nodiscard]] constexpr T* assume_aligned(T* ptr); // C++20 + } // std */ @@ -5581,6 +5585,20 @@ _LIBCPP_FUNC_VIS void* align(size_t __align, size_t __sz, void*& __ptr, size_t& __space); +#if _LIBCPP_STD_VER > 17 +template +_LIBCPP_NODISCARD_ATTRIBUTE +constexpr _Tp* assume_aligned(_Tp * __p) noexcept +{ +#ifdef _LIBCPP_HAS_BUILTIN_ASSUME_ALIGNED +// return __builtin_assume_aligned(__p, _Sz); + return reinterpret_cast<_Tp*>(__builtin_assume_aligned(__p, _Sz)); +#else + return __p; +#endif +} +#endif // _LIBCPP_STD_VER > 17 + // --- Helper for container swap -- template inline _LIBCPP_INLINE_VISIBILITY Index: test/std/utilities/memory/ptr.align/assume_aligned.fail.cpp =================================================================== --- test/std/utilities/memory/ptr.align/assume_aligned.fail.cpp +++ test/std/utilities/memory/ptr.align/assume_aligned.fail.cpp @@ -0,0 +1,25 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// UNSUPPORTED: c++98, c++03, c++11, c++14, c++17 + +// #include + +// template +// [[nodiscard]] constexpr T* assume_aligned(T* ptr); + +#include +#include + +#include "test_macros.h" + +int main () +{ + int *p = nullptr; + std::assume_aligned(p, 4); // expected-error {{ignoring return value of function declared with 'nodiscard' attribute}} +} Index: test/std/utilities/memory/ptr.align/assume_aligned.pass.cpp =================================================================== --- test/std/utilities/memory/ptr.align/assume_aligned.pass.cpp +++ test/std/utilities/memory/ptr.align/assume_aligned.pass.cpp @@ -0,0 +1,66 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// UNSUPPORTED: c++98, c++03, c++11, c++14, c++17 + +// #include + +// template +// [[nodiscard]] constexpr T* assume_aligned(T* ptr); + +#include +#include + +#include "test_macros.h" + +template +constexpr bool is_aligned(T* p, size_t n) +{ return (reinterpret_cast(p) & ((1 << n) - 1)) == 0; } + +template +void test(T *p) +{ + ASSERT_SAME_TYPE(T*, decltype(std::assume_aligned<1, T>(p))); + assert((p == std::assume_aligned<1>(p))); + if (is_aligned(p, 2)) + assert((p == std::assume_aligned< 2>(p))); + if (is_aligned(p, 4)) + assert((p == std::assume_aligned< 4>(p))); + if (is_aligned(p, 8)) + assert((p == std::assume_aligned< 8>(p))); + if (is_aligned(p, 16)) + assert((p == std::assume_aligned< 16>(p))); + if (is_aligned(p, 32)) + assert((p == std::assume_aligned< 32>(p))); + if (is_aligned(p, 64)) + assert((p == std::assume_aligned< 64>(p))); + if (is_aligned(p, 128)) + assert((p == std::assume_aligned<128>(p))); +} + +int i; +long l; +double d; +long double ld; + +struct A {}; +alignas(16) A a16; +alignas(32) A a32; +alignas(64) A a64; + +int main () +{ + + test( &i); + test( &l); + test( &d); + test(&ld); + test(&a16); + test(&a32); + test(&a64); +}