Botan 3.9.0
Crypto and TLS for C&
simd_avx2.h
Go to the documentation of this file.
1/*
2* (C) 2018 Jack Lloyd
3*
4* Botan is released under the Simplified BSD License (see license.txt)
5*/
6
7#ifndef BOTAN_SIMD_AVX2_H_
8#define BOTAN_SIMD_AVX2_H_
9
10#include <botan/compiler.h>
11#include <botan/types.h>
12#include <botan/internal/isa_extn.h>
13#include <immintrin.h>
14
15namespace Botan {
16
17// NOLINTBEGIN(portability-simd-intrinsics)
18
19class SIMD_8x32 final {
20 public:
21 SIMD_8x32& operator=(const SIMD_8x32& other) = default;
22 SIMD_8x32(const SIMD_8x32& other) = default;
23
24 SIMD_8x32& operator=(SIMD_8x32&& other) = default;
25 SIMD_8x32(SIMD_8x32&& other) = default;
26
27 ~SIMD_8x32() = default;
28
29 BOTAN_FN_ISA_AVX2
30 BOTAN_FORCE_INLINE SIMD_8x32() noexcept : m_avx2(_mm256_setzero_si256()) {}
31
32 BOTAN_FN_ISA_AVX2
33 explicit SIMD_8x32(const uint32_t B[8]) noexcept {
34 // NOLINTNEXTLINE(*-prefer-member-initializer)
35 m_avx2 = _mm256_loadu_si256(reinterpret_cast<const __m256i*>(B));
36 }
37
38 BOTAN_FN_ISA_AVX2
39 explicit SIMD_8x32(uint32_t B0,
40 uint32_t B1,
41 uint32_t B2,
42 uint32_t B3,
43 uint32_t B4,
44 uint32_t B5,
45 uint32_t B6,
46 uint32_t B7) noexcept {
47 // NOLINTNEXTLINE(*-prefer-member-initializer)
48 m_avx2 = _mm256_set_epi32(B7, B6, B5, B4, B3, B2, B1, B0);
49 }
50
51 BOTAN_FN_ISA_AVX2
52 explicit SIMD_8x32(uint32_t B0, uint32_t B1, uint32_t B2, uint32_t B3) noexcept {
53 // NOLINTNEXTLINE(*-prefer-member-initializer)
54 m_avx2 = _mm256_set_epi32(B3, B2, B1, B0, B3, B2, B1, B0);
55 }
56
57 BOTAN_FN_ISA_AVX2
58 static SIMD_8x32 splat(uint32_t B) noexcept { return SIMD_8x32(_mm256_set1_epi32(B)); }
59
60 BOTAN_FN_ISA_AVX2
61 static SIMD_8x32 load_le(const uint8_t* in) noexcept {
62 return SIMD_8x32(_mm256_loadu_si256(reinterpret_cast<const __m256i*>(in)));
63 }
64
65 BOTAN_FN_ISA_AVX2
66 static SIMD_8x32 load_le(const uint32_t* in) noexcept {
67 return SIMD_8x32(_mm256_loadu_si256(reinterpret_cast<const __m256i*>(in)));
68 }
69
70 BOTAN_FN_ISA_AVX2
71 static SIMD_8x32 load_le128(const uint8_t* in) noexcept {
72 return SIMD_8x32(_mm256_broadcastsi128_si256(_mm_loadu_si128(reinterpret_cast<const __m128i*>(in))));
73 }
74
75 BOTAN_FN_ISA_AVX2
76 static SIMD_8x32 load_le128(const uint32_t* in) noexcept {
77 return SIMD_8x32(_mm256_broadcastsi128_si256(_mm_loadu_si128(reinterpret_cast<const __m128i*>(in))));
78 }
79
80 BOTAN_FN_ISA_AVX2
81 static SIMD_8x32 load_be(const uint8_t* in) noexcept { return load_le(in).bswap(); }
82
83 BOTAN_FN_ISA_AVX2
84 void store_le(uint8_t out[]) const noexcept { _mm256_storeu_si256(reinterpret_cast<__m256i*>(out), m_avx2); }
85
86 BOTAN_FN_ISA_AVX2
87 void store_le(uint32_t out[]) const noexcept { _mm256_storeu_si256(reinterpret_cast<__m256i*>(out), m_avx2); }
88
89 BOTAN_FN_ISA_AVX2
90 void store_le128(uint8_t out[]) const noexcept {
91 _mm_storeu_si128(reinterpret_cast<__m128i*>(out), _mm256_extracti128_si256(raw(), 0));
92 }
93
94 BOTAN_FN_ISA_AVX2
95 static SIMD_8x32 load_le128(const uint32_t in1[], const uint32_t in2[]) noexcept {
96 return SIMD_8x32(
97 _mm256_loadu2_m128i(reinterpret_cast<const __m128i*>(in2), reinterpret_cast<const __m128i*>(in1)));
98 }
99
100 BOTAN_FN_ISA_AVX2
101 static SIMD_8x32 load_be128(const uint8_t in1[], const uint8_t in2[]) noexcept {
102 return SIMD_8x32(
103 _mm256_loadu2_m128i(reinterpret_cast<const __m128i*>(in2), reinterpret_cast<const __m128i*>(in1)))
104 .bswap();
105 }
106
107 BOTAN_FN_ISA_AVX2
108 void store_le128(uint32_t out1[], uint32_t out2[]) const noexcept {
109 _mm256_storeu2_m128i(reinterpret_cast<__m128i*>(out2), reinterpret_cast<__m128i*>(out1), raw());
110 }
111
112 BOTAN_FN_ISA_AVX2
113 void store_be(uint8_t out[]) const noexcept { bswap().store_le(out); }
114
115 template <size_t ROT>
116 BOTAN_FN_ISA_AVX2 SIMD_8x32 rotl() const noexcept
117 requires(ROT > 0 && ROT < 32)
118 {
119#if defined(__AVX512VL__)
120 return SIMD_8x32(_mm256_rol_epi32(m_avx2, ROT));
121#else
122 if constexpr(ROT == 8) {
123 const __m256i shuf_rotl_8 =
124 _mm256_set_epi64x(0x0e0d0c0f'0a09080b, 0x06050407'02010003, 0x0e0d0c0f'0a09080b, 0x06050407'02010003);
125
126 return SIMD_8x32(_mm256_shuffle_epi8(m_avx2, shuf_rotl_8));
127 } else if constexpr(ROT == 16) {
128 const __m256i shuf_rotl_16 =
129 _mm256_set_epi64x(0x0d0c0f0e'09080b0a, 0x05040706'01000302, 0x0d0c0f0e'09080b0a, 0x05040706'01000302);
130
131 return SIMD_8x32(_mm256_shuffle_epi8(m_avx2, shuf_rotl_16));
132 } else if constexpr(ROT == 24) {
133 const __m256i shuf_rotl_24 =
134 _mm256_set_epi64x(0x0c0f0e0d'080b0a09, 0x04070605'00030201, 0x0c0f0e0d'080b0a09, 0x04070605'00030201);
135
136 return SIMD_8x32(_mm256_shuffle_epi8(m_avx2, shuf_rotl_24));
137 } else {
138 return SIMD_8x32(_mm256_or_si256(_mm256_slli_epi32(m_avx2, static_cast<int>(ROT)),
139 _mm256_srli_epi32(m_avx2, static_cast<int>(32 - ROT))));
140 }
141#endif
142 }
143
144 template <size_t ROT>
145 BOTAN_FN_ISA_AVX2 SIMD_8x32 rotr() const noexcept {
146 return this->rotl<32 - ROT>();
147 }
148
149 SIMD_8x32 BOTAN_FN_ISA_AVX2 sigma0() const noexcept {
150 const SIMD_8x32 rot1 = this->rotr<2>();
151 const SIMD_8x32 rot2 = this->rotr<13>();
152 const SIMD_8x32 rot3 = this->rotr<22>();
153 return rot1 ^ rot2 ^ rot3;
154 }
155
156 SIMD_8x32 BOTAN_FN_ISA_AVX2 sigma1() const noexcept {
157 const SIMD_8x32 rot1 = this->rotr<6>();
158 const SIMD_8x32 rot2 = this->rotr<11>();
159 const SIMD_8x32 rot3 = this->rotr<25>();
160 return rot1 ^ rot2 ^ rot3;
161 }
162
163 BOTAN_FN_ISA_AVX2
164 SIMD_8x32 operator+(const SIMD_8x32& other) const noexcept {
165 SIMD_8x32 retval(*this);
166 retval += other;
167 return retval;
168 }
169
170 BOTAN_FN_ISA_AVX2
171 SIMD_8x32 operator-(const SIMD_8x32& other) const noexcept {
172 SIMD_8x32 retval(*this);
173 retval -= other;
174 return retval;
175 }
176
177 BOTAN_FN_ISA_AVX2
178 SIMD_8x32 operator^(const SIMD_8x32& other) const noexcept {
179 SIMD_8x32 retval(*this);
180 retval ^= other;
181 return retval;
182 }
183
184 BOTAN_FN_ISA_AVX2
185 SIMD_8x32 operator|(const SIMD_8x32& other) const noexcept {
186 SIMD_8x32 retval(*this);
187 retval |= other;
188 return retval;
189 }
190
191 BOTAN_FN_ISA_AVX2
192 SIMD_8x32 operator&(const SIMD_8x32& other) const noexcept {
193 SIMD_8x32 retval(*this);
194 retval &= other;
195 return retval;
196 }
197
198 BOTAN_FN_ISA_AVX2
199 void operator+=(const SIMD_8x32& other) { m_avx2 = _mm256_add_epi32(m_avx2, other.m_avx2); }
200
201 BOTAN_FN_ISA_AVX2
202 void operator-=(const SIMD_8x32& other) { m_avx2 = _mm256_sub_epi32(m_avx2, other.m_avx2); }
203
204 BOTAN_FN_ISA_AVX2
205 void operator^=(const SIMD_8x32& other) { m_avx2 = _mm256_xor_si256(m_avx2, other.m_avx2); }
206
207 BOTAN_FN_ISA_AVX2
208 void operator^=(uint32_t other) { *this ^= SIMD_8x32::splat(other); }
209
210 BOTAN_FN_ISA_AVX2
211 void operator|=(const SIMD_8x32& other) { m_avx2 = _mm256_or_si256(m_avx2, other.m_avx2); }
212
213 BOTAN_FN_ISA_AVX2
214 void operator&=(const SIMD_8x32& other) { m_avx2 = _mm256_and_si256(m_avx2, other.m_avx2); }
215
216 template <int SHIFT>
217 BOTAN_FN_ISA_AVX2 SIMD_8x32 shl() const noexcept {
218 return SIMD_8x32(_mm256_slli_epi32(m_avx2, SHIFT));
219 }
220
221 template <int SHIFT>
222 BOTAN_FN_ISA_AVX2 SIMD_8x32 shr() const noexcept {
223 return SIMD_8x32(_mm256_srli_epi32(m_avx2, SHIFT));
224 }
225
226 BOTAN_FN_ISA_AVX2
227 SIMD_8x32 operator~() const noexcept {
228 return SIMD_8x32(_mm256_xor_si256(m_avx2, _mm256_set1_epi32(0xFFFFFFFF)));
229 }
230
231 // (~reg) & other
232 BOTAN_FN_ISA_AVX2
233 SIMD_8x32 andc(const SIMD_8x32& other) const noexcept {
234 return SIMD_8x32(_mm256_andnot_si256(m_avx2, other.m_avx2));
235 }
236
237 BOTAN_FN_ISA_AVX2
238 SIMD_8x32 bswap() const noexcept {
239 alignas(32) const uint8_t BSWAP_TBL[32] = {3, 2, 1, 0, 7, 6, 5, 4, 11, 10, 9, 8, 15, 14, 13, 12,
240 19, 18, 17, 16, 23, 22, 21, 20, 27, 26, 25, 24, 31, 30, 29, 28};
241
242 const __m256i bswap = _mm256_load_si256(reinterpret_cast<const __m256i*>(BSWAP_TBL));
243
244 const __m256i output = _mm256_shuffle_epi8(m_avx2, bswap);
245
246 return SIMD_8x32(output);
247 }
248
249 // Equivalent to rev_words().bswap()
250 BOTAN_FN_ISA_AVX2
251 SIMD_8x32 reverse() const noexcept {
252 alignas(32) const uint8_t REV_TBL[32] = {15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0,
253 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0};
254
255 const __m256i bswap = _mm256_load_si256(reinterpret_cast<const __m256i*>(REV_TBL));
256 const __m256i output = _mm256_shuffle_epi8(m_avx2, bswap);
257 return SIMD_8x32(output);
258 }
259
260 BOTAN_FN_ISA_AVX2
261 SIMD_8x32 rev_words() const noexcept { return SIMD_8x32(_mm256_shuffle_epi32(raw(), 0b00011011)); }
262
263 BOTAN_FN_ISA_AVX2
264 static void transpose(SIMD_8x32& B0, SIMD_8x32& B1, SIMD_8x32& B2, SIMD_8x32& B3) noexcept {
265 const __m256i T0 = _mm256_unpacklo_epi32(B0.m_avx2, B1.m_avx2);
266 const __m256i T1 = _mm256_unpacklo_epi32(B2.m_avx2, B3.m_avx2);
267 const __m256i T2 = _mm256_unpackhi_epi32(B0.m_avx2, B1.m_avx2);
268 const __m256i T3 = _mm256_unpackhi_epi32(B2.m_avx2, B3.m_avx2);
269
270 B0.m_avx2 = _mm256_unpacklo_epi64(T0, T1);
271 B1.m_avx2 = _mm256_unpackhi_epi64(T0, T1);
272 B2.m_avx2 = _mm256_unpacklo_epi64(T2, T3);
273 B3.m_avx2 = _mm256_unpackhi_epi64(T2, T3);
274 }
275
276 BOTAN_FN_ISA_AVX2
277 static void transpose(SIMD_8x32& B0,
278 SIMD_8x32& B1,
279 SIMD_8x32& B2,
280 SIMD_8x32& B3,
281 SIMD_8x32& B4,
282 SIMD_8x32& B5,
283 SIMD_8x32& B6,
284 SIMD_8x32& B7) noexcept {
285 transpose(B0, B1, B2, B3);
286 transpose(B4, B5, B6, B7);
287
288 swap_tops(B0, B4);
289 swap_tops(B1, B5);
290 swap_tops(B2, B6);
291 swap_tops(B3, B7);
292 }
293
294 BOTAN_FN_ISA_AVX2
295 static SIMD_8x32 choose(const SIMD_8x32& mask, const SIMD_8x32& a, const SIMD_8x32& b) noexcept {
296#if defined(__AVX512VL__)
297 return SIMD_8x32(_mm256_ternarylogic_epi32(mask.raw(), a.raw(), b.raw(), 0xca));
298#else
299 return (mask & a) ^ mask.andc(b);
300#endif
301 }
302
303 BOTAN_FN_ISA_AVX2
304 static SIMD_8x32 majority(const SIMD_8x32& x, const SIMD_8x32& y, const SIMD_8x32& z) noexcept {
305#if defined(__AVX512VL__)
306 return SIMD_8x32(_mm256_ternarylogic_epi32(x.raw(), y.raw(), z.raw(), 0xe8));
307#else
308 return SIMD_8x32::choose(x ^ y, z, y);
309#endif
310 }
311
312 static inline SIMD_8x32 BOTAN_FN_ISA_AVX2 byte_shuffle(const SIMD_8x32& tbl, const SIMD_8x32& idx) {
313 return SIMD_8x32(_mm256_shuffle_epi8(tbl.raw(), idx.raw()));
314 }
315
316 BOTAN_FN_ISA_AVX2
317 static void reset_registers() noexcept { _mm256_zeroupper(); }
318
319 BOTAN_FN_ISA_AVX2
320 static void zero_registers() noexcept { _mm256_zeroall(); }
321
322 __m256i BOTAN_FN_ISA_AVX2 raw() const noexcept { return m_avx2; }
323
324 BOTAN_FN_ISA_AVX2
325 explicit SIMD_8x32(__m256i x) noexcept : m_avx2(x) {}
326
327 private:
328 BOTAN_FN_ISA_AVX2
329 static void swap_tops(SIMD_8x32& A, SIMD_8x32& B) {
330 auto T0 = SIMD_8x32(_mm256_permute2x128_si256(A.raw(), B.raw(), 0 + (2 << 4)));
331 auto T1 = SIMD_8x32(_mm256_permute2x128_si256(A.raw(), B.raw(), 1 + (3 << 4)));
332 A = T0;
333 B = T1;
334 }
335
336 __m256i m_avx2;
337};
338
339// NOLINTEND(portability-simd-intrinsics)
340
341template <size_t R>
342inline SIMD_8x32 rotl(SIMD_8x32 input) {
343 return input.rotl<R>();
344}
345
346template <size_t R>
347inline SIMD_8x32 rotr(SIMD_8x32 input) {
348 return input.rotr<R>();
349}
350
351// For Serpent:
352template <size_t S>
353inline SIMD_8x32 shl(SIMD_8x32 input) {
354 return input.shl<S>();
355}
356
357} // namespace Botan
358
359#endif
SIMD_8x32 BOTAN_FN_ISA_AVX2 sigma0() const noexcept
Definition simd_avx2.h:149
BOTAN_FN_ISA_AVX2 SIMD_8x32 operator^(const SIMD_8x32 &other) const noexcept
Definition simd_avx2.h:178
__m256i BOTAN_FN_ISA_AVX2 raw() const noexcept
Definition simd_avx2.h:322
SIMD_8x32 & operator=(SIMD_8x32 &&other)=default
BOTAN_FN_ISA_AVX2 SIMD_8x32 shl() const noexcept
Definition simd_avx2.h:217
SIMD_8x32(const SIMD_8x32 &other)=default
BOTAN_FN_ISA_AVX2 SIMD_8x32 shr() const noexcept
Definition simd_avx2.h:222
SIMD_8x32 BOTAN_FN_ISA_AVX2 sigma1() const noexcept
Definition simd_avx2.h:156
BOTAN_FN_ISA_AVX2 SIMD_8x32(__m256i x) noexcept
Definition simd_avx2.h:325
static BOTAN_FN_ISA_AVX2 SIMD_8x32 load_le128(const uint8_t *in) noexcept
Definition simd_avx2.h:71
static BOTAN_FN_ISA_AVX2 SIMD_8x32 load_le128(const uint32_t *in) noexcept
Definition simd_avx2.h:76
static BOTAN_FN_ISA_AVX2 void reset_registers() noexcept
Definition simd_avx2.h:317
BOTAN_FN_ISA_AVX2 SIMD_8x32 rev_words() const noexcept
Definition simd_avx2.h:261
BOTAN_FN_ISA_AVX2 SIMD_8x32 rotr() const noexcept
Definition simd_avx2.h:145
BOTAN_FN_ISA_AVX2 void operator&=(const SIMD_8x32 &other)
Definition simd_avx2.h:214
BOTAN_FN_ISA_AVX2 SIMD_8x32 rotl() const noexcept
Definition simd_avx2.h:116
static BOTAN_FN_ISA_AVX2 SIMD_8x32 load_le128(const uint32_t in1[], const uint32_t in2[]) noexcept
Definition simd_avx2.h:95
~SIMD_8x32()=default
static BOTAN_FN_ISA_AVX2 SIMD_8x32 load_le(const uint32_t *in) noexcept
Definition simd_avx2.h:66
BOTAN_FN_ISA_AVX2 SIMD_8x32 reverse() const noexcept
Definition simd_avx2.h:251
static BOTAN_FN_ISA_AVX2 SIMD_8x32 load_le(const uint8_t *in) noexcept
Definition simd_avx2.h:61
BOTAN_FN_ISA_AVX2 void operator^=(uint32_t other)
Definition simd_avx2.h:208
BOTAN_FN_ISA_AVX2 void store_le128(uint32_t out1[], uint32_t out2[]) const noexcept
Definition simd_avx2.h:108
BOTAN_FN_ISA_AVX2 void operator|=(const SIMD_8x32 &other)
Definition simd_avx2.h:211
SIMD_8x32(SIMD_8x32 &&other)=default
BOTAN_FN_ISA_AVX2 SIMD_8x32 operator~() const noexcept
Definition simd_avx2.h:227
BOTAN_FN_ISA_AVX2 void operator^=(const SIMD_8x32 &other)
Definition simd_avx2.h:205
BOTAN_FN_ISA_AVX2 void operator-=(const SIMD_8x32 &other)
Definition simd_avx2.h:202
BOTAN_FN_ISA_AVX2 SIMD_8x32(const uint32_t B[8]) noexcept
Definition simd_avx2.h:33
BOTAN_FN_ISA_AVX2 void store_le128(uint8_t out[]) const noexcept
Definition simd_avx2.h:90
static BOTAN_FN_ISA_AVX2 void transpose(SIMD_8x32 &B0, SIMD_8x32 &B1, SIMD_8x32 &B2, SIMD_8x32 &B3) noexcept
Definition simd_avx2.h:264
static BOTAN_FN_ISA_AVX2 void zero_registers() noexcept
Definition simd_avx2.h:320
static BOTAN_FN_ISA_AVX2 SIMD_8x32 majority(const SIMD_8x32 &x, const SIMD_8x32 &y, const SIMD_8x32 &z) noexcept
Definition simd_avx2.h:304
BOTAN_FN_ISA_AVX2 void store_be(uint8_t out[]) const noexcept
Definition simd_avx2.h:113
static BOTAN_FN_ISA_AVX2 SIMD_8x32 splat(uint32_t B) noexcept
Definition simd_avx2.h:58
static BOTAN_FN_ISA_AVX2 void transpose(SIMD_8x32 &B0, SIMD_8x32 &B1, SIMD_8x32 &B2, SIMD_8x32 &B3, SIMD_8x32 &B4, SIMD_8x32 &B5, SIMD_8x32 &B6, SIMD_8x32 &B7) noexcept
Definition simd_avx2.h:277
BOTAN_FN_ISA_AVX2 SIMD_8x32(uint32_t B0, uint32_t B1, uint32_t B2, uint32_t B3) noexcept
Definition simd_avx2.h:52
static BOTAN_FN_ISA_AVX2 SIMD_8x32 choose(const SIMD_8x32 &mask, const SIMD_8x32 &a, const SIMD_8x32 &b) noexcept
Definition simd_avx2.h:295
BOTAN_FN_ISA_AVX2 SIMD_8x32 andc(const SIMD_8x32 &other) const noexcept
Definition simd_avx2.h:233
BOTAN_FN_ISA_AVX2 SIMD_8x32 operator-(const SIMD_8x32 &other) const noexcept
Definition simd_avx2.h:171
SIMD_8x32 & operator=(const SIMD_8x32 &other)=default
BOTAN_FN_ISA_AVX2 void operator+=(const SIMD_8x32 &other)
Definition simd_avx2.h:199
static SIMD_8x32 BOTAN_FN_ISA_AVX2 byte_shuffle(const SIMD_8x32 &tbl, const SIMD_8x32 &idx)
Definition simd_avx2.h:312
BOTAN_FN_ISA_AVX2 void store_le(uint8_t out[]) const noexcept
Definition simd_avx2.h:84
BOTAN_FN_ISA_AVX2 SIMD_8x32 operator&(const SIMD_8x32 &other) const noexcept
Definition simd_avx2.h:192
BOTAN_FN_ISA_AVX2 SIMD_8x32 operator+(const SIMD_8x32 &other) const noexcept
Definition simd_avx2.h:164
BOTAN_FN_ISA_AVX2 SIMD_8x32 bswap() const noexcept
Definition simd_avx2.h:238
BOTAN_FN_ISA_AVX2 BOTAN_FORCE_INLINE SIMD_8x32() noexcept
Definition simd_avx2.h:30
BOTAN_FN_ISA_AVX2 void store_le(uint32_t out[]) const noexcept
Definition simd_avx2.h:87
BOTAN_FN_ISA_AVX2 SIMD_8x32 operator|(const SIMD_8x32 &other) const noexcept
Definition simd_avx2.h:185
static BOTAN_FN_ISA_AVX2 SIMD_8x32 load_be128(const uint8_t in1[], const uint8_t in2[]) noexcept
Definition simd_avx2.h:101
BOTAN_FN_ISA_AVX2 SIMD_8x32(uint32_t B0, uint32_t B1, uint32_t B2, uint32_t B3, uint32_t B4, uint32_t B5, uint32_t B6, uint32_t B7) noexcept
Definition simd_avx2.h:39
static BOTAN_FN_ISA_AVX2 SIMD_8x32 load_be(const uint8_t *in) noexcept
Definition simd_avx2.h:81
#define BOTAN_FORCE_INLINE
Definition compiler.h:87
BOTAN_FORCE_INLINE constexpr T rotr(T input)
Definition rotate.h:35
BOTAN_FORCE_INLINE constexpr T rotl(T input)
Definition rotate.h:23
SIMD_4x32 shl(SIMD_4x32 input)
Definition simd_4x32.h:790