libstdc++: simd_flags.h Source File

libstdc++

simd_flags.h
1// Implementation of <simd> -*- C++ -*-
2
3// Copyright The GNU Toolchain Authors.
4//
5// This file is part of the GNU ISO C++ Library. This library is free
6// software; you can redistribute it and/or modify it under the
7// terms of the GNU General Public License as published by the
8// Free Software Foundation; either version 3, or (at your option)
9// any later version.
10
11// This library is distributed in the hope that it will be useful,
12// but WITHOUT ANY WARRANTY; without even the implied warranty of
13// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14// GNU General Public License for more details.
15
16// Under Section 7 of GPL version 3, you are granted additional
17// permissions described in the GCC Runtime Library Exception, version
18// 3.1, as published by the Free Software Foundation.
19
20// You should have received a copy of the GNU General Public License and
21// a copy of the GCC Runtime Library Exception along with this program;
22// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
23// <http://www.gnu.org/licenses/>.
24
25#ifndef _GLIBCXX_SIMD_FLAGS_H
26#define _GLIBCXX_SIMD_FLAGS_H 1
27
28#ifdef _GLIBCXX_SYSHDR
29#pragma GCC system_header
30#endif
31
32#if __cplusplus >= 202400L
33
34#include "simd_details.h"
35#include <bits/align.h> // assume_aligned
36
37namespace std _GLIBCXX_VISIBILITY(default)
38{
39_GLIBCXX_BEGIN_NAMESPACE_VERSION
40namespace simd
41{
42 // [simd.traits]
43 // --- alignment ---
44 template <typename _Tp, typename _Up = typename _Tp::value_type>
45 struct alignment
46 {};
47
48 template <typename _Tp, typename _Ap, __vectorizable _Up>
49 struct alignment<basic_vec<_Tp, _Ap>, _Up>
50 : integral_constant<size_t, alignof(basic_vec<_Tp, _Ap>)>
51 {};
52
53 template <typename _Tp, typename _Up = typename _Tp::value_type>
54 constexpr size_t alignment_v = alignment<_Tp, _Up>::value;
55
56 // [simd.flags] -------------------------------------------------------------
57 struct _LoadStoreTag
58 {};
59
60 /** @internal
61 * `struct convert-flag`
62 *
63 * C++26 [simd.expos] / [simd.flags]
64 */
65 struct __convert_flag
66 : _LoadStoreTag
67 {};
68
69 /** @internal
70 * `struct aligned-flag`
71 *
72 * C++26 [simd.expos] / [simd.flags]
73 */
74 struct __aligned_flag
75 : _LoadStoreTag
76 {
77 template <typename _Tp, typename _Up>
78 [[__gnu__::__always_inline__]]
79 static constexpr _Up*
80 _S_adjust_pointer(_Up* __ptr)
81 { return assume_aligned<simd::alignment_v<_Tp, remove_cv_t<_Up>>>(__ptr); }
82 };
83
84 /** @internal
85 * `template<size_t N> struct overaligned-flag`
86 *
87 * @tparam _Np alignment in bytes
88 *
89 * C++26 [simd.expos] / [simd.flags]
90 */
91 template <size_t _Np>
92 struct __overaligned_flag
93 : _LoadStoreTag
94 {
95 static_assert(__has_single_bit(_Np));
96
97 template <typename, typename _Up>
98 [[__gnu__::__always_inline__]]
99 static constexpr _Up*
100 _S_adjust_pointer(_Up* __ptr)
101 { return assume_aligned<_Np>(__ptr); }
102 };
103
104 struct __partial_loadstore_flag
105 : _LoadStoreTag
106 {};
107
108
109 template <typename _Tp>
110 concept __loadstore_tag = is_base_of_v<_LoadStoreTag, _Tp>;
111
112 template <typename...>
113 struct flags;
114
115 template <typename... _Flags>
116 requires (__loadstore_tag<_Flags> && ...)
117 struct flags<_Flags...>
118 {
119 /** @internal
120 * Returns @c true if the given argument is part of this specialization, otherwise returns @c
121 * false.
122 */
123 template <typename _F0>
124 static consteval bool
125 _S_test(flags<_F0>)
126 { return (is_same_v<_Flags, _F0> || ...); }
127
128 friend consteval flags
129 operator|(flags, flags<>)
130 { return flags{}; }
131
132 template <typename _T0, typename... _More>
133 friend consteval auto
134 operator|(flags, flags<_T0, _More...>)
135 {
136 if constexpr ((same_as<_Flags, _T0> || ...))
137 return flags<_Flags...>{} | flags<_More...>{};
138 else
139 return flags<_Flags..., _T0>{} | flags<_More...>{};
140 }
141
142 /** @internal
143 * Adjusts a pointer according to the alignment requirements of the flags.
144 *
145 * This function iterates over all flags in the pack and applies each flag's
146 * `_S_adjust_pointer` method to the input pointer. Flags that don't provide
147 * this method are ignored.
148 *
149 * @tparam _Tp A basic_vec type for which a load/store pointer is adjusted
150 * @tparam _Up The value-type of the input/output range
151 * @param __ptr The pointer to the range
152 * @return The adjusted pointer
153 */
154 template <typename _Tp, typename _Up>
155 static constexpr _Up*
156 _S_adjust_pointer(_Up* __ptr)
157 {
158 template for ([[maybe_unused]] constexpr auto __f : {_Flags()...})
159 {
160 if constexpr (requires {__f.template _S_adjust_pointer<_Tp>(__ptr); })
161 __ptr = __f.template _S_adjust_pointer<_Tp>(__ptr);
162 }
163 return __ptr;
164 }
165 };
166
167 inline constexpr flags<> flag_default {};
168
169 inline constexpr flags<__convert_flag> flag_convert {};
170
171 inline constexpr flags<__aligned_flag> flag_aligned {};
172
173 template <size_t _Np>
174 requires(__has_single_bit(_Np))
175 inline constexpr flags<__overaligned_flag<_Np>> flag_overaligned {};
176
177 /** @internal
178 * Pass to unchecked_load or unchecked_store to make it behave like partial_load / partial_store.
179 */
180 inline constexpr flags<__partial_loadstore_flag> __allow_partial_loadstore {};
181
182} // namespace simd
183_GLIBCXX_END_NAMESPACE_VERSION
184} // namespace std
185
186#endif // C++26
187#endif // _GLIBCXX_SIMD_FLAGS_H
align.h
std::assume_aligned
constexpr _Tp * assume_aligned(_Tp *__ptr) noexcept
Inform the compiler that a pointer is aligned.
Definition align.h:90
std
ISO C++ entities toplevel namespace is std.
std::operator|
constexpr bitset< _Nb > operator|(const bitset< _Nb > &__x, const bitset< _Nb > &__y) noexcept
Global bitwise operations on bitsets.
Definition bitset:1672