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 
37 namespace std _GLIBCXX_VISIBILITY(default)
38 {
39 _GLIBCXX_BEGIN_NAMESPACE_VERSION
40 namespace 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
requires requires
Definition: complex:1948
ISO C++ entities toplevel namespace is std.
constexpr bitset< _Nb > operator|(const bitset< _Nb > &__x, const bitset< _Nb > &__y) noexcept
Global bitwise operations on bitsets.
Definition: bitset:1628