Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[libc++] Implement P2897R7 aligned_accessor: An mdspan accessor expressing pointer over-alignment #122603

Open
wants to merge 5 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions libcxx/docs/FeatureTestMacroTable.rst
Original file line number Diff line number Diff line change
Expand Up @@ -404,6 +404,8 @@ Status
---------------------------------------------------------- -----------------
**C++26**
----------------------------------------------------------------------------
``__cpp_lib_aligned_accessor`` ``202411L``
---------------------------------------------------------- -----------------
``__cpp_lib_associative_heterogeneous_insertion`` *unimplemented*
---------------------------------------------------------- -----------------
``__cpp_lib_atomic_min_max`` *unimplemented*
Expand Down Expand Up @@ -450,6 +452,8 @@ Status
---------------------------------------------------------- -----------------
``__cpp_lib_inplace_vector`` *unimplemented*
---------------------------------------------------------- -----------------
``__cpp_lib_is_sufficiently_aligned`` ``202411L``
---------------------------------------------------------- -----------------
``__cpp_lib_is_virtual_base_of`` ``202406L``
---------------------------------------------------------- -----------------
``__cpp_lib_is_within_lifetime`` *unimplemented*
Expand Down
2 changes: 1 addition & 1 deletion libcxx/docs/Status/Cxx2cPapers.csv
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@
"`P3379R0 <https://wg21.link/P3379R0>`__","Constrain ``std::expected`` equality operators","2024-11 (Wrocław)","","",""
"`P0472R2 <https://wg21.link/P0472R2>`__","Put ``std::monostate`` in ``<utility>``","2024-11 (Wrocław)","","",""
"`P2862R1 <https://wg21.link/P2862R1>`__","``text_encoding::name()`` should never return null values","2024-11 (Wrocław)","","",""
"`P2897R7 <https://wg21.link/P2897R7>`__","``aligned_accessor``: An ``mdspan`` accessor expressing pointer over-alignment","2024-11 (Wrocław)","","",""
"`P2897R7 <https://wg21.link/P2897R7>`__","``aligned_accessor``: An ``mdspan`` accessor expressing pointer over-alignment","2024-11 (Wrocław)","|Complete|","20",""
"`P3355R1 <https://wg21.link/P3355R1>`__","Fix ``submdspan`` for C++26","2024-11 (Wrocław)","","",""
"`P3222R0 <https://wg21.link/P3222R0>`__","Fix C++26 by adding transposed special cases for P2642 layouts","2024-11 (Wrocław)","","",""
"`P3050R2 <https://wg21.link/P3050R2>`__","Fix C++26 by optimizing ``linalg::conjugated`` for noncomplex value types","2024-11 (Wrocław)","","",""
Expand Down
2 changes: 2 additions & 0 deletions libcxx/include/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -529,6 +529,7 @@ set(files
__math/traits.h
__math/trigonometric_functions.h
__mbstate_t.h
__mdspan/aligned_accessor.h
__mdspan/default_accessor.h
__mdspan/extents.h
__mdspan/layout_left.h
Expand All @@ -553,6 +554,7 @@ set(files
__memory/construct_at.h
__memory/destruct_n.h
__memory/inout_ptr.h
__memory/is_sufficiently_aligned.h
__memory/noexcept_move_assign_container.h
__memory/out_ptr.h
__memory/pointer_traits.h
Expand Down
87 changes: 87 additions & 0 deletions libcxx/include/__mdspan/aligned_accessor.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
// -*- 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
//
// Kokkos v. 4.0
// Copyright (2022) National Technology & Engineering
// Solutions of Sandia, LLC (NTESS).
//
// Under the terms of Contract DE-NA0003525 with NTESS,
// the U.S. Government retains certain rights in this software.
//
//===---------------------------------------------------------------------===//

#ifndef _LIBCPP___MDSPAN_ALIGNED_ACCESSOR_H
#define _LIBCPP___MDSPAN_ALIGNED_ACCESSOR_H

#include <__config>
#include <__cstddef/size_t.h>
dalg24 marked this conversation as resolved.
Show resolved Hide resolved
#include <__mdspan/default_accessor.h>
#include <__memory/assume_aligned.h>
#include <__type_traits/is_abstract.h>
#include <__type_traits/is_array.h>
#include <__type_traits/is_convertible.h>
#include <__type_traits/remove_const.h>

#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
# pragma GCC system_header
#endif

_LIBCPP_PUSH_MACROS
#include <__undef_macros>

_LIBCPP_BEGIN_NAMESPACE_STD

#if _LIBCPP_STD_VER >= 26

template <class _ElementType, size_t _ByteAlignment>
struct aligned_accessor {
static_assert(_ByteAlignment != 0 && (_ByteAlignment & (_ByteAlignment - 1)) == 0,
"aligned_accessor: byte alignment must be a power of two");
static_assert(_ByteAlignment >= alignof(_ElementType), "aligned_accessor: insufficient byte alignment");
static_assert(!is_array_v<_ElementType>, "aligned_accessor: template argument may not be an array type");
static_assert(!is_abstract_v<_ElementType>, "aligned_accessor: template argument may not be an abstract class");

using offset_policy = default_accessor<_ElementType>;
using element_type = _ElementType;
using reference = _ElementType&;
using data_handle_type = _ElementType*;

static constexpr size_t byte_alignment = _ByteAlignment;

_LIBCPP_HIDE_FROM_ABI constexpr aligned_accessor() noexcept = default;

template <class _OtherElementType, size_t _OtherByteAlignment>
requires(is_convertible_v<_OtherElementType (*)[], element_type (*)[]> && _OtherByteAlignment >= byte_alignment)
_LIBCPP_HIDE_FROM_ABI constexpr aligned_accessor(aligned_accessor<_OtherElementType, _OtherByteAlignment>) noexcept {}

template <class _OtherElementType>
requires(is_convertible_v<_OtherElementType (*)[], element_type (*)[]>)
_LIBCPP_HIDE_FROM_ABI explicit constexpr aligned_accessor(default_accessor<_OtherElementType>) noexcept {}

template <class _OtherElementType>
requires(is_convertible_v<element_type (*)[], _OtherElementType (*)[]>)
_LIBCPP_HIDE_FROM_ABI constexpr operator default_accessor<_OtherElementType>() const noexcept {
return {};
}

_LIBCPP_HIDE_FROM_ABI constexpr reference access(data_handle_type __p, size_t __i) const noexcept {
return std::assume_aligned<byte_alignment>(__p)[__i];
}

_LIBCPP_HIDE_FROM_ABI constexpr typename offset_policy::data_handle_type
offset(data_handle_type __p, size_t __i) const noexcept {
return std::assume_aligned<byte_alignment>(__p) + __i;
}
};

#endif // _LIBCPP_STD_VER >= 26

_LIBCPP_END_NAMESPACE_STD

_LIBCPP_POP_MACROS

#endif // _LIBCPP___MDSPAN_ALIGNED_ACCESSOR_H
9 changes: 5 additions & 4 deletions libcxx/include/__mdspan/mdspan.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
#include <__assert>
#include <__config>
#include <__fwd/mdspan.h>
#include <__mdspan/aligned_accessor.h>
#include <__mdspan/default_accessor.h>
#include <__mdspan/extents.h>
#include <__type_traits/extent.h>
Expand Down Expand Up @@ -266,13 +267,13 @@ class mdspan {
# if _LIBCPP_STD_VER >= 26
template <class _ElementType, class... _OtherIndexTypes>
requires((is_convertible_v<_OtherIndexTypes, size_t> && ...) && (sizeof...(_OtherIndexTypes) > 0))
explicit mdspan(_ElementType*,
_OtherIndexTypes...) -> mdspan<_ElementType, extents<size_t, __maybe_static_ext<_OtherIndexTypes>...>>;
explicit mdspan(_ElementType*, _OtherIndexTypes...)
-> mdspan<_ElementType, extents<size_t, __maybe_static_ext<_OtherIndexTypes>...>>;
# else
template <class _ElementType, class... _OtherIndexTypes>
requires((is_convertible_v<_OtherIndexTypes, size_t> && ...) && (sizeof...(_OtherIndexTypes) > 0))
explicit mdspan(_ElementType*,
_OtherIndexTypes...) -> mdspan<_ElementType, dextents<size_t, sizeof...(_OtherIndexTypes)>>;
explicit mdspan(_ElementType*, _OtherIndexTypes...)
-> mdspan<_ElementType, dextents<size_t, sizeof...(_OtherIndexTypes)>>;
# endif

template <class _Pointer>
Expand Down
34 changes: 34 additions & 0 deletions libcxx/include/__memory/is_sufficiently_aligned.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
// -*- 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 _LIBCPP___MEMORY_IS_SUFFICIENTLY_ALIGNED_H
#define _LIBCPP___MEMORY_IS_SUFFICIENTLY_ALIGNED_H

#include <__config>
#include <__cstddef/size_t.h>
#include <cstdint>

#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
# pragma GCC system_header
#endif

_LIBCPP_BEGIN_NAMESPACE_STD

#if _LIBCPP_STD_VER >= 26

template <size_t _Alignment, class _Tp>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we can just add this to assume_aligned.h. These two seem to be quite closely related.

_LIBCPP_HIDE_FROM_ABI bool is_sufficiently_aligned(_Tp* __ptr) {
return reinterpret_cast<uintptr_t>(__ptr) % _Alignment == 0;
}

#endif // _LIBCPP_STD_VER >= 26

_LIBCPP_END_NAMESPACE_STD

#endif // _LIBCPP___MEMORY_IS_SUFFICIENTLY_ALIGNED_H
38 changes: 37 additions & 1 deletion libcxx/include/mdspan
Original file line number Diff line number Diff line change
Expand Up @@ -33,10 +33,14 @@ namespace std {
template<class ElementType>
class default_accessor;

// [mdspan.accessor.aligned], class template aligned_accessor
template<class ElementType, size_t ByteAlignment>
class aligned_accessor; // since C++26

// [mdspan.mdspan], class template mdspan
template<class ElementType, class Extents, class LayoutPolicy = layout_right,
class AccessorPolicy = default_accessor<ElementType>>
class mdspan; // not implemented yet
class mdspan;
}

// extents synopsis
Expand Down Expand Up @@ -269,6 +273,38 @@ namespace std {
};
}

// aligned_accessor synopsis

namespace std {
template<class ElementType, size_t ByteAlignment>
struct aligned_accessor {
using offset_policy = default_accessor<ElementType>;
using element_type = ElementType;
using reference = ElementType&;
using data_handle_type = ElementType*;

static constexpr size_t byte_alignment = ByteAlignment;

constexpr aligned_accessor() noexcept = default;

template<class OtherElementType, size_t OtherByteAlignment>
constexpr aligned_accessor(
aligned_accessor<OtherElementType, OtherByteAlignment>) noexcept;

template<class OtherElementType>
explicit constexpr aligned_accessor(
default_accessor<OtherElementType>) noexcept;

template<class OtherElementType>
constexpr operator default_accessor<OtherElementType>() const noexcept;

constexpr reference access(data_handle_type p, size_t i) const noexcept;

constexpr typename offset_policy::data_handle_type
offset(data_handle_type p, size_t i) const noexcept;
};
}

// mdspan synopsis

namespace std {
Expand Down
4 changes: 4 additions & 0 deletions libcxx/include/memory
Original file line number Diff line number Diff line change
Expand Up @@ -912,6 +912,9 @@ void* align(size_t alignment, size_t size, void*& ptr, size_t& space);
template<size_t N, class T>
[[nodiscard]] constexpr T* assume_aligned(T* ptr); // since C++20

template<size_t Alignment, class T>
bool is_sufficiently_aligned(T* ptr); // since C++26

// [out.ptr.t], class template out_ptr_t
template<class Smart, class Pointer, class... Args>
class out_ptr_t; // since c++23
Expand Down Expand Up @@ -945,6 +948,7 @@ template<class Pointer = void, class Smart, class... Args>
# include <__memory/allocator_traits.h>
# include <__memory/auto_ptr.h>
# include <__memory/inout_ptr.h>
# include <__memory/is_sufficiently_aligned.h>
# include <__memory/out_ptr.h>
# include <__memory/pointer_traits.h>
# include <__memory/raw_storage_iterator.h>
Expand Down
2 changes: 2 additions & 0 deletions libcxx/include/module.modulemap
Original file line number Diff line number Diff line change
Expand Up @@ -1504,6 +1504,7 @@ module std [system] {
}

module mdspan {
module aligned_accessor { header "__mdspan/aligned_accessor.h" }
module default_accessor { header "__mdspan/default_accessor.h" }
module extents { header "__mdspan/extents.h" }
module fwd { header "__fwd/mdspan.h" }
Expand Down Expand Up @@ -1539,6 +1540,7 @@ module std [system] {
module destruct_n { header "__memory/destruct_n.h" }
module fwd { header "__fwd/memory.h" }
module inout_ptr { header "__memory/inout_ptr.h" }
module is_sufficiently_aligned { header "__memory/is_sufficiently_aligned.h" }
module noexcept_move_assign_container { header "__memory/noexcept_move_assign_container.h" }
module out_ptr { header "__memory/out_ptr.h" }
module pointer_traits { header "__memory/pointer_traits.h" }
Expand Down
4 changes: 4 additions & 0 deletions libcxx/include/version
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
Macro name Value Headers
__cpp_lib_adaptor_iterator_pair_constructor 202106L <queue> <stack>
__cpp_lib_addressof_constexpr 201603L <memory>
__cpp_lib_aligned_accessor 202411L <mdspan>
__cpp_lib_allocate_at_least 202302L <memory>
__cpp_lib_allocator_traits_is_always_equal 201411L <deque> <forward_list> <list>
<map> <memory> <scoped_allocator>
Expand Down Expand Up @@ -145,6 +146,7 @@ __cpp_lib_is_nothrow_convertible 201806L <type_traits>
__cpp_lib_is_null_pointer 201309L <type_traits>
__cpp_lib_is_pointer_interconvertible 201907L <type_traits>
__cpp_lib_is_scoped_enum 202011L <type_traits>
__cpp_lib_is_sufficiently_aligned 202411L <memory>
__cpp_lib_is_swappable 201603L <type_traits>
__cpp_lib_is_virtual_base_of 202406L <type_traits>
__cpp_lib_is_within_lifetime 202306L <type_traits>
Expand Down Expand Up @@ -523,6 +525,7 @@ __cpp_lib_void_t 201411L <type_traits>
#endif

#if _LIBCPP_STD_VER >= 26
# define __cpp_lib_aligned_accessor 202411L
// # define __cpp_lib_associative_heterogeneous_insertion 202306L
// # define __cpp_lib_atomic_min_max 202403L
# undef __cpp_lib_bind_front
Expand Down Expand Up @@ -551,6 +554,7 @@ __cpp_lib_void_t 201411L <type_traits>
// # define __cpp_lib_generate_random 202403L
// # define __cpp_lib_hazard_pointer 202306L
// # define __cpp_lib_inplace_vector 202406L
# define __cpp_lib_is_sufficiently_aligned 202411L
# if __has_builtin(__builtin_is_virtual_base_of)
# define __cpp_lib_is_virtual_base_of 202406L
# endif
Expand Down
5 changes: 5 additions & 0 deletions libcxx/modules/std/mdspan.inc
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,11 @@ export namespace std {
// [mdspan.accessor.default], class template default_accessor
using std::default_accessor;

# if _LIBCPP_STD_VER >= 26
// [mdspan.accessor.aligned], class template aligned_accessor
using std::aligned_accessor;
# endif // _LIBCPP_STD_VER >= 26

// [mdspan.mdspan], class template mdspan
using std::mdspan;
#endif // _LIBCPP_STD_VER >= 23
Expand Down
3 changes: 3 additions & 0 deletions libcxx/modules/std/memory.inc
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,9 @@ export namespace std {
// [ptr.align], pointer alignment
using std::align;
using std::assume_aligned;
#if _LIBCPP_STD_VER >= 26
using std::is_sufficiently_aligned;
#endif

// [obj.lifetime], explicit lifetime management
// using std::start_lifetime_as;
Expand Down
Loading
Loading