Skip to content

Commit 557e931

Browse files
authored
[libc++] Implement P2897R7 aligned_accessor: An mdspan accessor expressing pointer over-alignment (#122603)
Closes #118372
1 parent ff687af commit 557e931

27 files changed

+1017
-6
lines changed

libcxx/docs/FeatureTestMacroTable.rst

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -408,6 +408,8 @@ Status
408408
---------------------------------------------------------- -----------------
409409
**C++26**
410410
----------------------------------------------------------------------------
411+
``__cpp_lib_aligned_accessor`` ``202411L``
412+
---------------------------------------------------------- -----------------
411413
``__cpp_lib_associative_heterogeneous_insertion`` *unimplemented*
412414
---------------------------------------------------------- -----------------
413415
``__cpp_lib_atomic_min_max`` *unimplemented*
@@ -456,6 +458,8 @@ Status
456458
---------------------------------------------------------- -----------------
457459
``__cpp_lib_inplace_vector`` *unimplemented*
458460
---------------------------------------------------------- -----------------
461+
``__cpp_lib_is_sufficiently_aligned`` ``202411L``
462+
---------------------------------------------------------- -----------------
459463
``__cpp_lib_is_virtual_base_of`` ``202406L``
460464
---------------------------------------------------------- -----------------
461465
``__cpp_lib_is_within_lifetime`` *unimplemented*

libcxx/docs/ReleaseNotes/21.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ Implemented Papers
4545
- P2562R1: ``constexpr`` Stable Sorting (`Github <https://github.com/llvm/llvm-project/issues/105360>`__)
4646
- P0472R3: Put std::monostate in <utility> (`Github <https://github.com/llvm/llvm-project/issues/127874>`__)
4747
- P1222R4: A Standard ``flat_set`` (`Github <https://github.com/llvm/llvm-project/issues/105193>`__)
48+
- P2897R7: ``aligned_accessor``: An mdspan accessor expressing pointer over-alignment (`Github <https://github.com/llvm/llvm-project/issues/118372>`__)
4849
- P3247R2: Deprecate the notion of trivial types (`Github <https://github.com/llvm/llvm-project/issues/118387>`__)
4950

5051
Improvements and New Features

libcxx/docs/Status/Cxx2cPapers.csv

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,7 @@
8080
"`P3138R5 <https://wg21.link/P3138R5>`__","``views::cache_latest``","2024-11 (Wrocław)","","",""
8181
"`P3379R0 <https://wg21.link/P3379R0>`__","Constrain ``std::expected`` equality operators","2024-11 (Wrocław)","","",""
8282
"`P2862R1 <https://wg21.link/P2862R1>`__","``text_encoding::name()`` should never return null values","2024-11 (Wrocław)","","",""
83-
"`P2897R7 <https://wg21.link/P2897R7>`__","``aligned_accessor``: An ``mdspan`` accessor expressing pointer over-alignment","2024-11 (Wrocław)","","",""
83+
"`P2897R7 <https://wg21.link/P2897R7>`__","``aligned_accessor``: An ``mdspan`` accessor expressing pointer over-alignment","2024-11 (Wrocław)","|Complete|","21",""
8484
"`P3355R1 <https://wg21.link/P3355R1>`__","Fix ``submdspan`` for C++26","2024-11 (Wrocław)","","",""
8585
"`P3222R0 <https://wg21.link/P3222R0>`__","Fix C++26 by adding transposed special cases for P2642 layouts","2024-11 (Wrocław)","","",""
8686
"`P3050R2 <https://wg21.link/P3050R2>`__","Fix C++26 by optimizing ``linalg::conjugated`` for noncomplex value types","2024-11 (Wrocław)","","",""

libcxx/include/CMakeLists.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -545,6 +545,7 @@ set(files
545545
__math/traits.h
546546
__math/trigonometric_functions.h
547547
__mbstate_t.h
548+
__mdspan/aligned_accessor.h
548549
__mdspan/default_accessor.h
549550
__mdspan/extents.h
550551
__mdspan/layout_left.h
@@ -569,6 +570,7 @@ set(files
569570
__memory/destroy.h
570571
__memory/destruct_n.h
571572
__memory/inout_ptr.h
573+
__memory/is_sufficiently_aligned.h
572574
__memory/noexcept_move_assign_container.h
573575
__memory/out_ptr.h
574576
__memory/pointer_traits.h
Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
// -*- C++ -*-
2+
//===----------------------------------------------------------------------===//
3+
//
4+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
5+
// See https://llvm.org/LICENSE.txt for license information.
6+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7+
//
8+
// Kokkos v. 4.0
9+
// Copyright (2022) National Technology & Engineering
10+
// Solutions of Sandia, LLC (NTESS).
11+
//
12+
// Under the terms of Contract DE-NA0003525 with NTESS,
13+
// the U.S. Government retains certain rights in this software.
14+
//
15+
//===---------------------------------------------------------------------===//
16+
17+
#ifndef _LIBCPP___MDSPAN_ALIGNED_ACCESSOR_H
18+
#define _LIBCPP___MDSPAN_ALIGNED_ACCESSOR_H
19+
20+
#include <__config>
21+
#include <__cstddef/size_t.h>
22+
#include <__mdspan/default_accessor.h>
23+
#include <__memory/assume_aligned.h>
24+
#include <__type_traits/is_abstract.h>
25+
#include <__type_traits/is_array.h>
26+
#include <__type_traits/is_convertible.h>
27+
#include <__type_traits/remove_const.h>
28+
29+
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
30+
# pragma GCC system_header
31+
#endif
32+
33+
_LIBCPP_PUSH_MACROS
34+
#include <__undef_macros>
35+
36+
_LIBCPP_BEGIN_NAMESPACE_STD
37+
38+
#if _LIBCPP_STD_VER >= 26
39+
40+
template <class _ElementType, size_t _ByteAlignment>
41+
struct aligned_accessor {
42+
static_assert(_ByteAlignment != 0 && (_ByteAlignment & (_ByteAlignment - 1)) == 0,
43+
"aligned_accessor: byte alignment must be a power of two");
44+
static_assert(_ByteAlignment >= alignof(_ElementType), "aligned_accessor: insufficient byte alignment");
45+
static_assert(!is_array_v<_ElementType>, "aligned_accessor: template argument may not be an array type");
46+
static_assert(!is_abstract_v<_ElementType>, "aligned_accessor: template argument may not be an abstract class");
47+
48+
using offset_policy = default_accessor<_ElementType>;
49+
using element_type = _ElementType;
50+
using reference = _ElementType&;
51+
using data_handle_type = _ElementType*;
52+
53+
static constexpr size_t byte_alignment = _ByteAlignment;
54+
55+
_LIBCPP_HIDE_FROM_ABI constexpr aligned_accessor() noexcept = default;
56+
57+
template <class _OtherElementType, size_t _OtherByteAlignment>
58+
requires(is_convertible_v<_OtherElementType (*)[], element_type (*)[]> && _OtherByteAlignment >= byte_alignment)
59+
_LIBCPP_HIDE_FROM_ABI constexpr aligned_accessor(aligned_accessor<_OtherElementType, _OtherByteAlignment>) noexcept {}
60+
61+
template <class _OtherElementType>
62+
requires(is_convertible_v<_OtherElementType (*)[], element_type (*)[]>)
63+
_LIBCPP_HIDE_FROM_ABI explicit constexpr aligned_accessor(default_accessor<_OtherElementType>) noexcept {}
64+
65+
template <class _OtherElementType>
66+
requires(is_convertible_v<element_type (*)[], _OtherElementType (*)[]>)
67+
_LIBCPP_HIDE_FROM_ABI constexpr operator default_accessor<_OtherElementType>() const noexcept {
68+
return {};
69+
}
70+
71+
_LIBCPP_HIDE_FROM_ABI constexpr reference access(data_handle_type __p, size_t __i) const noexcept {
72+
return std::assume_aligned<byte_alignment>(__p)[__i];
73+
}
74+
75+
_LIBCPP_HIDE_FROM_ABI constexpr typename offset_policy::data_handle_type
76+
offset(data_handle_type __p, size_t __i) const noexcept {
77+
return std::assume_aligned<byte_alignment>(__p) + __i;
78+
}
79+
};
80+
81+
#endif // _LIBCPP_STD_VER >= 26
82+
83+
_LIBCPP_END_NAMESPACE_STD
84+
85+
_LIBCPP_POP_MACROS
86+
87+
#endif // _LIBCPP___MDSPAN_ALIGNED_ACCESSOR_H

libcxx/include/__mdspan/mdspan.h

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
#include <__assert>
2121
#include <__config>
2222
#include <__fwd/mdspan.h>
23+
#include <__mdspan/aligned_accessor.h>
2324
#include <__mdspan/default_accessor.h>
2425
#include <__mdspan/extents.h>
2526
#include <__memory/addressof.h>
@@ -267,13 +268,13 @@ class mdspan {
267268
# if _LIBCPP_STD_VER >= 26
268269
template <class _ElementType, class... _OtherIndexTypes>
269270
requires((is_convertible_v<_OtherIndexTypes, size_t> && ...) && (sizeof...(_OtherIndexTypes) > 0))
270-
explicit mdspan(_ElementType*,
271-
_OtherIndexTypes...) -> mdspan<_ElementType, extents<size_t, __maybe_static_ext<_OtherIndexTypes>...>>;
271+
explicit mdspan(_ElementType*, _OtherIndexTypes...)
272+
-> mdspan<_ElementType, extents<size_t, __maybe_static_ext<_OtherIndexTypes>...>>;
272273
# else
273274
template <class _ElementType, class... _OtherIndexTypes>
274275
requires((is_convertible_v<_OtherIndexTypes, size_t> && ...) && (sizeof...(_OtherIndexTypes) > 0))
275-
explicit mdspan(_ElementType*,
276-
_OtherIndexTypes...) -> mdspan<_ElementType, dextents<size_t, sizeof...(_OtherIndexTypes)>>;
276+
explicit mdspan(_ElementType*, _OtherIndexTypes...)
277+
-> mdspan<_ElementType, dextents<size_t, sizeof...(_OtherIndexTypes)>>;
277278
# endif
278279

279280
template <class _Pointer>
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
// -*- C++ -*-
2+
//===----------------------------------------------------------------------===//
3+
//
4+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
5+
// See https://llvm.org/LICENSE.txt for license information.
6+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7+
//
8+
//===----------------------------------------------------------------------===//
9+
10+
#ifndef _LIBCPP___MEMORY_IS_SUFFICIENTLY_ALIGNED_H
11+
#define _LIBCPP___MEMORY_IS_SUFFICIENTLY_ALIGNED_H
12+
13+
#include <__config>
14+
#include <__cstddef/size_t.h>
15+
#include <cstdint>
16+
17+
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
18+
# pragma GCC system_header
19+
#endif
20+
21+
_LIBCPP_BEGIN_NAMESPACE_STD
22+
23+
#if _LIBCPP_STD_VER >= 26
24+
25+
template <size_t _Alignment, class _Tp>
26+
_LIBCPP_HIDE_FROM_ABI bool is_sufficiently_aligned(_Tp* __ptr) {
27+
return reinterpret_cast<uintptr_t>(__ptr) % _Alignment == 0;
28+
}
29+
30+
#endif // _LIBCPP_STD_VER >= 26
31+
32+
_LIBCPP_END_NAMESPACE_STD
33+
34+
#endif // _LIBCPP___MEMORY_IS_SUFFICIENTLY_ALIGNED_H

libcxx/include/mdspan

Lines changed: 37 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,10 +33,14 @@ namespace std {
3333
template<class ElementType>
3434
class default_accessor;
3535
36+
// [mdspan.accessor.aligned], class template aligned_accessor
37+
template<class ElementType, size_t ByteAlignment>
38+
class aligned_accessor; // since C++26
39+
3640
// [mdspan.mdspan], class template mdspan
3741
template<class ElementType, class Extents, class LayoutPolicy = layout_right,
3842
class AccessorPolicy = default_accessor<ElementType>>
39-
class mdspan; // not implemented yet
43+
class mdspan;
4044
}
4145
4246
// extents synopsis
@@ -269,6 +273,38 @@ namespace std {
269273
};
270274
}
271275
276+
// aligned_accessor synopsis
277+
278+
namespace std {
279+
template<class ElementType, size_t ByteAlignment>
280+
struct aligned_accessor {
281+
using offset_policy = default_accessor<ElementType>;
282+
using element_type = ElementType;
283+
using reference = ElementType&;
284+
using data_handle_type = ElementType*;
285+
286+
static constexpr size_t byte_alignment = ByteAlignment;
287+
288+
constexpr aligned_accessor() noexcept = default;
289+
290+
template<class OtherElementType, size_t OtherByteAlignment>
291+
constexpr aligned_accessor(
292+
aligned_accessor<OtherElementType, OtherByteAlignment>) noexcept;
293+
294+
template<class OtherElementType>
295+
explicit constexpr aligned_accessor(
296+
default_accessor<OtherElementType>) noexcept;
297+
298+
template<class OtherElementType>
299+
constexpr operator default_accessor<OtherElementType>() const noexcept;
300+
301+
constexpr reference access(data_handle_type p, size_t i) const noexcept;
302+
303+
constexpr typename offset_policy::data_handle_type
304+
offset(data_handle_type p, size_t i) const noexcept;
305+
};
306+
}
307+
272308
// mdspan synopsis
273309
274310
namespace std {

libcxx/include/memory

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -912,6 +912,9 @@ void* align(size_t alignment, size_t size, void*& ptr, size_t& space);
912912
template<size_t N, class T>
913913
[[nodiscard]] constexpr T* assume_aligned(T* ptr); // since C++20
914914
915+
template<size_t Alignment, class T>
916+
bool is_sufficiently_aligned(T* ptr); // since C++26
917+
915918
// [out.ptr.t], class template out_ptr_t
916919
template<class Smart, class Pointer, class... Args>
917920
class out_ptr_t; // since c++23
@@ -945,6 +948,7 @@ template<class Pointer = void, class Smart, class... Args>
945948
# include <__memory/allocator_traits.h>
946949
# include <__memory/auto_ptr.h>
947950
# include <__memory/inout_ptr.h>
951+
# include <__memory/is_sufficiently_aligned.h>
948952
# include <__memory/out_ptr.h>
949953
# include <__memory/pointer_traits.h>
950954
# include <__memory/raw_storage_iterator.h>

libcxx/include/module.modulemap

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1593,6 +1593,7 @@ module std [system] {
15931593
}
15941594

15951595
module mdspan {
1596+
module aligned_accessor { header "__mdspan/aligned_accessor.h" }
15961597
module default_accessor { header "__mdspan/default_accessor.h" }
15971598
module extents { header "__mdspan/extents.h" }
15981599
module fwd { header "__fwd/mdspan.h" }
@@ -1631,6 +1632,7 @@ module std [system] {
16311632
module destruct_n { header "__memory/destruct_n.h" }
16321633
module fwd { header "__fwd/memory.h" }
16331634
module inout_ptr { header "__memory/inout_ptr.h" }
1635+
module is_sufficiently_aligned { header "__memory/is_sufficiently_aligned.h" }
16341636
module noexcept_move_assign_container { header "__memory/noexcept_move_assign_container.h" }
16351637
module out_ptr { header "__memory/out_ptr.h" }
16361638
module pointer_traits { header "__memory/pointer_traits.h" }

0 commit comments

Comments
 (0)