core/intrinsics/simd.rs
1//! SIMD compiler intrinsics.
2//!
3//! In this module, a "vector" is any `repr(simd)` type.
4
5#[cfg(not(feature = "ferrocene_subset"))]
6use crate::marker::ConstParamTy;
7
8/// Inserts an element into a vector, returning the updated vector.
9///
10/// `T` must be a vector with element type `U`, and `idx` must be `const`.
11///
12/// # Safety
13///
14/// `idx` must be in-bounds of the vector.
15#[rustc_intrinsic]
16#[rustc_nounwind]
17pub const unsafe fn simd_insert<T, U>(x: T, idx: u32, val: U) -> T;
18
19/// Extracts an element from a vector.
20///
21/// `T` must be a vector with element type `U`, and `idx` must be `const`.
22///
23/// # Safety
24///
25/// `idx` must be const and in-bounds of the vector.
26#[rustc_intrinsic]
27#[rustc_nounwind]
28pub const unsafe fn simd_extract<T, U>(x: T, idx: u32) -> U;
29
30/// Inserts an element into a vector, returning the updated vector.
31///
32/// `T` must be a vector with element type `U`.
33///
34/// If the index is `const`, [`simd_insert`] may emit better assembly.
35///
36/// # Safety
37///
38/// `idx` must be in-bounds of the vector.
39#[rustc_nounwind]
40#[rustc_intrinsic]
41#[cfg(not(feature = "ferrocene_subset"))]
42pub const unsafe fn simd_insert_dyn<T, U>(x: T, idx: u32, val: U) -> T;
43
44/// Extracts an element from a vector.
45///
46/// `T` must be a vector with element type `U`.
47///
48/// If the index is `const`, [`simd_extract`] may emit better assembly.
49///
50/// # Safety
51///
52/// `idx` must be in-bounds of the vector.
53#[rustc_nounwind]
54#[rustc_intrinsic]
55pub const unsafe fn simd_extract_dyn<T, U>(x: T, idx: u32) -> U;
56
57/// Creates a vector where every lane has the provided value.
58///
59/// `T` must be a vector with element type `U`.
60#[rustc_nounwind]
61#[rustc_intrinsic]
62pub const unsafe fn simd_splat<T, U>(value: U) -> T;
63
64/// Adds two simd vectors elementwise.
65///
66/// `T` must be a vector of integers or floats.
67#[rustc_intrinsic]
68#[rustc_nounwind]
69pub const unsafe fn simd_add<T>(x: T, y: T) -> T;
70
71/// Subtracts `rhs` from `lhs` elementwise.
72///
73/// `T` must be a vector of integers or floats.
74#[rustc_intrinsic]
75#[rustc_nounwind]
76pub const unsafe fn simd_sub<T>(lhs: T, rhs: T) -> T;
77
78/// Multiplies two simd vectors elementwise.
79///
80/// `T` must be a vector of integers or floats.
81#[rustc_intrinsic]
82#[rustc_nounwind]
83pub const unsafe fn simd_mul<T>(x: T, y: T) -> T;
84
85/// Divides `lhs` by `rhs` elementwise.
86///
87/// `T` must be a vector of integers or floats.
88///
89/// # Safety
90/// For integers, `rhs` must not contain any zero elements.
91/// Additionally for signed integers, `<int>::MIN / -1` is undefined behavior.
92#[rustc_intrinsic]
93#[rustc_nounwind]
94#[cfg(not(feature = "ferrocene_subset"))]
95pub const unsafe fn simd_div<T>(lhs: T, rhs: T) -> T;
96
97/// Returns remainder of two vectors elementwise.
98///
99/// `T` must be a vector of integers or floats.
100///
101/// # Safety
102/// For integers, `rhs` must not contain any zero elements.
103/// Additionally for signed integers, `<int>::MIN / -1` is undefined behavior.
104#[rustc_intrinsic]
105#[rustc_nounwind]
106#[cfg(not(feature = "ferrocene_subset"))]
107pub const unsafe fn simd_rem<T>(lhs: T, rhs: T) -> T;
108
109/// Shifts vector left elementwise, with UB on overflow.
110///
111/// Shifts `lhs` left by `rhs`, shifting in sign bits for signed types.
112///
113/// `T` must be a vector of integers.
114///
115/// # Safety
116///
117/// Each element of `rhs` must be less than `<int>::BITS`.
118#[rustc_intrinsic]
119#[rustc_nounwind]
120#[cfg(not(feature = "ferrocene_subset"))]
121pub const unsafe fn simd_shl<T>(lhs: T, rhs: T) -> T;
122
123/// Shifts vector right elementwise, with UB on overflow.
124///
125/// `T` must be a vector of integers.
126///
127/// Shifts `lhs` right by `rhs`, shifting in sign bits for signed types.
128///
129/// # Safety
130///
131/// Each element of `rhs` must be less than `<int>::BITS`.
132#[rustc_intrinsic]
133#[rustc_nounwind]
134#[cfg(not(feature = "ferrocene_subset"))]
135pub const unsafe fn simd_shr<T>(lhs: T, rhs: T) -> T;
136
137/// Funnel Shifts vector left elementwise, with UB on overflow.
138///
139/// Concatenates `a` and `b` elementwise (with `a` in the most significant half),
140/// creating a vector of the same length, but with each element being twice as
141/// wide. Then shift this vector left elementwise by `shift`, shifting in zeros,
142/// and extract the most significant half of each of the elements. If `a` and `b`
143/// are the same, this is equivalent to an elementwise rotate left operation.
144///
145/// `T` must be a vector of integers.
146///
147/// # Safety
148///
149/// Each element of `shift` must be less than `<int>::BITS`.
150#[rustc_intrinsic]
151#[rustc_nounwind]
152#[cfg(not(feature = "ferrocene_subset"))]
153pub const unsafe fn simd_funnel_shl<T>(a: T, b: T, shift: T) -> T;
154
155/// Funnel Shifts vector right elementwise, with UB on overflow.
156///
157/// Concatenates `a` and `b` elementwise (with `a` in the most significant half),
158/// creating a vector of the same length, but with each element being twice as
159/// wide. Then shift this vector right elementwise by `shift`, shifting in zeros,
160/// and extract the least significant half of each of the elements. If `a` and `b`
161/// are the same, this is equivalent to an elementwise rotate right operation.
162///
163/// `T` must be a vector of integers.
164///
165/// # Safety
166///
167/// Each element of `shift` must be less than `<int>::BITS`.
168#[rustc_intrinsic]
169#[rustc_nounwind]
170#[cfg(not(feature = "ferrocene_subset"))]
171pub const unsafe fn simd_funnel_shr<T>(a: T, b: T, shift: T) -> T;
172
173/// Compute the carry-less product.
174///
175/// This is similar to long multiplication except that the carry is discarded.
176///
177/// This operation can be used to model multiplication in `GF(2)[X]`, the polynomial
178/// ring over `GF(2)`.
179///
180/// `T` must be a vector of integers.
181#[rustc_intrinsic]
182#[rustc_nounwind]
183pub unsafe fn simd_carryless_mul<T>(a: T, b: T) -> T;
184
185/// "And"s vectors elementwise.
186///
187/// `T` must be a vector of integers.
188#[rustc_intrinsic]
189#[rustc_nounwind]
190pub const unsafe fn simd_and<T>(x: T, y: T) -> T;
191
192/// "Ors" vectors elementwise.
193///
194/// `T` must be a vector of integers.
195#[rustc_intrinsic]
196#[rustc_nounwind]
197pub const unsafe fn simd_or<T>(x: T, y: T) -> T;
198
199/// "Exclusive ors" vectors elementwise.
200///
201/// `T` must be a vector of integers.
202#[rustc_intrinsic]
203#[rustc_nounwind]
204pub const unsafe fn simd_xor<T>(x: T, y: T) -> T;
205
206/// Numerically casts a vector, elementwise.
207///
208/// `T` and `U` must be vectors of integers or floats, and must have the same length.
209///
210/// When casting floats to integers, the result is truncated. Out-of-bounds result lead to UB.
211/// When casting integers to floats, the result is rounded.
212/// Otherwise, truncates or extends the value, maintaining the sign for signed integers.
213///
214/// # Safety
215/// Casting from integer types is always safe.
216/// Casting between two float types is also always safe.
217///
218/// Casting floats to integers truncates, following the same rules as `to_int_unchecked`.
219/// Specifically, each element must:
220/// * Not be `NaN`
221/// * Not be infinite
222/// * Be representable in the return type, after truncating off its fractional part
223#[rustc_intrinsic]
224#[rustc_nounwind]
225#[cfg(not(feature = "ferrocene_subset"))]
226pub const unsafe fn simd_cast<T, U>(x: T) -> U;
227
228/// Numerically casts a vector, elementwise.
229///
230/// `T` and `U` be a vectors of integers or floats, and must have the same length.
231///
232/// Like `simd_cast`, but saturates float-to-integer conversions (NaN becomes 0).
233/// This matches regular `as` and is always safe.
234///
235/// When casting floats to integers, the result is truncated.
236/// When casting integers to floats, the result is rounded.
237/// Otherwise, truncates or extends the value, maintaining the sign for signed integers.
238#[rustc_intrinsic]
239#[rustc_nounwind]
240#[cfg(not(feature = "ferrocene_subset"))]
241pub const unsafe fn simd_as<T, U>(x: T) -> U;
242
243/// Negates a vector elementwise.
244///
245/// `T` must be a vector of integers or floats.
246///
247/// Rust panics for `-<int>::Min` due to overflow, but it is not UB with this intrinsic.
248#[rustc_intrinsic]
249#[rustc_nounwind]
250pub const unsafe fn simd_neg<T>(x: T) -> T;
251
252/// Returns absolute value of a vector, elementwise.
253///
254/// `T` must be a vector of floating-point primitive types.
255#[rustc_intrinsic]
256#[rustc_nounwind]
257#[cfg(not(feature = "ferrocene_subset"))]
258pub const unsafe fn simd_fabs<T>(x: T) -> T;
259
260/// Returns the minimum of two vectors, elementwise.
261///
262/// `T` must be a vector of floating-point primitive types.
263///
264/// Follows IEEE-754 `minNum` semantics.
265#[rustc_intrinsic]
266#[rustc_nounwind]
267#[cfg(not(feature = "ferrocene_subset"))]
268pub const unsafe fn simd_fmin<T>(x: T, y: T) -> T;
269
270/// Returns the maximum of two vectors, elementwise.
271///
272/// `T` must be a vector of floating-point primitive types.
273///
274/// Follows IEEE-754 `maxNum` semantics.
275#[rustc_intrinsic]
276#[rustc_nounwind]
277#[cfg(not(feature = "ferrocene_subset"))]
278pub const unsafe fn simd_fmax<T>(x: T, y: T) -> T;
279
280/// Tests elementwise equality of two vectors.
281///
282/// `T` must be a vector of integers or floats.
283///
284/// `U` must be a vector of integers with the same number of elements and element size as `T`.
285///
286/// Returns `0` for false and `!0` for true.
287#[rustc_intrinsic]
288#[rustc_nounwind]
289#[cfg(not(feature = "ferrocene_subset"))]
290pub const unsafe fn simd_eq<T, U>(x: T, y: T) -> U;
291
292/// Tests elementwise inequality equality of two vectors.
293///
294/// `T` must be a vector of integers or floats.
295///
296/// `U` must be a vector of integers with the same number of elements and element size as `T`.
297///
298/// Returns `0` for false and `!0` for true.
299#[rustc_intrinsic]
300#[rustc_nounwind]
301#[cfg(not(feature = "ferrocene_subset"))]
302pub const unsafe fn simd_ne<T, U>(x: T, y: T) -> U;
303
304/// Tests if `x` is less than `y`, elementwise.
305///
306/// `T` must be a vector of integers or floats.
307///
308/// `U` must be a vector of integers with the same number of elements and element size as `T`.
309///
310/// Returns `0` for false and `!0` for true.
311#[rustc_intrinsic]
312#[rustc_nounwind]
313#[cfg(not(feature = "ferrocene_subset"))]
314pub const unsafe fn simd_lt<T, U>(x: T, y: T) -> U;
315
316/// Tests if `x` is less than or equal to `y`, elementwise.
317///
318/// `T` must be a vector of integers or floats.
319///
320/// `U` must be a vector of integers with the same number of elements and element size as `T`.
321///
322/// Returns `0` for false and `!0` for true.
323#[rustc_intrinsic]
324#[rustc_nounwind]
325#[cfg(not(feature = "ferrocene_subset"))]
326pub const unsafe fn simd_le<T, U>(x: T, y: T) -> U;
327
328/// Tests if `x` is greater than `y`, elementwise.
329///
330/// `T` must be a vector of integers or floats.
331///
332/// `U` must be a vector of integers with the same number of elements and element size as `T`.
333///
334/// Returns `0` for false and `!0` for true.
335#[rustc_intrinsic]
336#[rustc_nounwind]
337#[cfg(not(feature = "ferrocene_subset"))]
338pub const unsafe fn simd_gt<T, U>(x: T, y: T) -> U;
339
340/// Tests if `x` is greater than or equal to `y`, elementwise.
341///
342/// `T` must be a vector of integers or floats.
343///
344/// `U` must be a vector of integers with the same number of elements and element size as `T`.
345///
346/// Returns `0` for false and `!0` for true.
347#[rustc_intrinsic]
348#[rustc_nounwind]
349#[cfg(not(feature = "ferrocene_subset"))]
350pub const unsafe fn simd_ge<T, U>(x: T, y: T) -> U;
351
352/// Shuffles two vectors by const indices.
353///
354/// `T` must be a vector.
355///
356/// `U` must be a **const** vector of `u32`s. This means it must either refer to a named
357/// const or be given as an inline const expression (`const { ... }`).
358///
359/// `V` must be a vector with the same element type as `T` and the same length as `U`.
360///
361/// Returns a new vector such that element `i` is selected from `xy[idx[i]]`, where `xy`
362/// is the concatenation of `x` and `y`. It is a compile-time error if `idx[i]` is out-of-bounds
363/// of `xy`.
364#[rustc_intrinsic]
365#[rustc_nounwind]
366pub const unsafe fn simd_shuffle<T, U, V>(x: T, y: T, idx: U) -> V;
367
368/// Reads a vector of pointers.
369///
370/// `T` must be a vector.
371///
372/// `U` must be a vector of pointers to the element type of `T`, with the same length as `T`.
373///
374/// `V` must be a vector of integers with the same length as `T` (but any element size).
375///
376/// For each pointer in `ptr`, if the corresponding value in `mask` is `!0`, read the pointer.
377/// Otherwise if the corresponding value in `mask` is `0`, return the corresponding value from
378/// `val`.
379///
380/// # Safety
381/// Unmasked values in `T` must be readable as if by `<ptr>::read` (e.g. aligned to the element
382/// type).
383///
384/// `mask` must only contain `0` or `!0` values.
385#[rustc_intrinsic]
386#[rustc_nounwind]
387#[cfg(not(feature = "ferrocene_subset"))]
388pub const unsafe fn simd_gather<T, U, V>(val: T, ptr: U, mask: V) -> T;
389
390/// Writes to a vector of pointers.
391///
392/// `T` must be a vector.
393///
394/// `U` must be a vector of pointers to the element type of `T`, with the same length as `T`.
395///
396/// `V` must be a vector of integers with the same length as `T` (but any element size).
397///
398/// For each pointer in `ptr`, if the corresponding value in `mask` is `!0`, write the
399/// corresponding value in `val` to the pointer.
400/// Otherwise if the corresponding value in `mask` is `0`, do nothing.
401///
402/// The stores happen in left-to-right order.
403/// (This is relevant in case two of the stores overlap.)
404///
405/// # Safety
406/// Unmasked values in `T` must be writeable as if by `<ptr>::write` (e.g. aligned to the element
407/// type).
408///
409/// `mask` must only contain `0` or `!0` values.
410#[rustc_intrinsic]
411#[rustc_nounwind]
412#[cfg(not(feature = "ferrocene_subset"))]
413pub const unsafe fn simd_scatter<T, U, V>(val: T, ptr: U, mask: V);
414
415/// A type for alignment options for SIMD masked load/store intrinsics.
416#[derive(Debug, ConstParamTy, PartialEq, Eq)]
417#[cfg(not(feature = "ferrocene_subset"))]
418pub enum SimdAlign {
419 // These values must match the compiler's `SimdAlign` defined in
420 // `rustc_middle/src/ty/consts/int.rs`!
421 /// No alignment requirements on the pointer
422 Unaligned = 0,
423 /// The pointer must be aligned to the element type of the SIMD vector
424 Element = 1,
425 /// The pointer must be aligned to the SIMD vector type
426 Vector = 2,
427}
428
429/// Reads a vector of pointers.
430///
431/// `T` must be a vector.
432///
433/// `U` must be a pointer to the element type of `T`
434///
435/// `V` must be a vector of integers with the same length as `T` (but any element size).
436///
437/// For each element, if the corresponding value in `mask` is `!0`, read the corresponding
438/// pointer offset from `ptr`.
439/// The first element is loaded from `ptr`, the second from `ptr.wrapping_offset(1)` and so on.
440/// Otherwise if the corresponding value in `mask` is `0`, return the corresponding value from
441/// `val`.
442///
443/// # Safety
444/// `ptr` must be aligned according to the `ALIGN` parameter, see [`SimdAlign`] for details.
445///
446/// `mask` must only contain `0` or `!0` values.
447#[rustc_intrinsic]
448#[rustc_nounwind]
449#[cfg(not(feature = "ferrocene_subset"))]
450pub const unsafe fn simd_masked_load<V, U, T, const ALIGN: SimdAlign>(mask: V, ptr: U, val: T)
451-> T;
452
453/// Writes to a vector of pointers.
454///
455/// `T` must be a vector.
456///
457/// `U` must be a pointer to the element type of `T`
458///
459/// `V` must be a vector of integers with the same length as `T` (but any element size).
460///
461/// For each element, if the corresponding value in `mask` is `!0`, write the corresponding
462/// value in `val` to the pointer offset from `ptr`.
463/// The first element is written to `ptr`, the second to `ptr.wrapping_offset(1)` and so on.
464/// Otherwise if the corresponding value in `mask` is `0`, do nothing.
465///
466/// # Safety
467/// `ptr` must be aligned according to the `ALIGN` parameter, see [`SimdAlign`] for details.
468///
469/// `mask` must only contain `0` or `!0` values.
470#[rustc_intrinsic]
471#[rustc_nounwind]
472#[cfg(not(feature = "ferrocene_subset"))]
473pub const unsafe fn simd_masked_store<V, U, T, const ALIGN: SimdAlign>(mask: V, ptr: U, val: T);
474
475/// Adds two simd vectors elementwise, with saturation.
476///
477/// `T` must be a vector of integer primitive types.
478#[rustc_intrinsic]
479#[rustc_nounwind]
480#[cfg(not(feature = "ferrocene_subset"))]
481pub const unsafe fn simd_saturating_add<T>(x: T, y: T) -> T;
482
483/// Subtracts two simd vectors elementwise, with saturation.
484///
485/// `T` must be a vector of integer primitive types.
486///
487/// Subtract `rhs` from `lhs`.
488#[rustc_intrinsic]
489#[rustc_nounwind]
490#[cfg(not(feature = "ferrocene_subset"))]
491pub const unsafe fn simd_saturating_sub<T>(lhs: T, rhs: T) -> T;
492
493/// Adds elements within a vector from left to right.
494///
495/// `T` must be a vector of integers or floats.
496///
497/// `U` must be the element type of `T`.
498///
499/// Starting with the value `y`, add the elements of `x` and accumulate.
500#[rustc_intrinsic]
501#[rustc_nounwind]
502#[cfg(not(feature = "ferrocene_subset"))]
503pub const unsafe fn simd_reduce_add_ordered<T, U>(x: T, y: U) -> U;
504
505/// Adds elements within a vector in arbitrary order. May also be re-associated with
506/// unordered additions on the inputs/outputs.
507///
508/// `T` must be a vector of integers or floats.
509///
510/// `U` must be the element type of `T`.
511#[rustc_intrinsic]
512#[rustc_nounwind]
513#[cfg(not(feature = "ferrocene_subset"))]
514pub unsafe fn simd_reduce_add_unordered<T, U>(x: T) -> U;
515
516/// Multiplies elements within a vector from left to right.
517///
518/// `T` must be a vector of integers or floats.
519///
520/// `U` must be the element type of `T`.
521///
522/// Starting with the value `y`, multiply the elements of `x` and accumulate.
523#[rustc_intrinsic]
524#[rustc_nounwind]
525#[cfg(not(feature = "ferrocene_subset"))]
526pub const unsafe fn simd_reduce_mul_ordered<T, U>(x: T, y: U) -> U;
527
528/// Multiplies elements within a vector in arbitrary order. May also be re-associated with
529/// unordered additions on the inputs/outputs.
530///
531/// `T` must be a vector of integers or floats.
532///
533/// `U` must be the element type of `T`.
534#[rustc_intrinsic]
535#[rustc_nounwind]
536#[cfg(not(feature = "ferrocene_subset"))]
537pub unsafe fn simd_reduce_mul_unordered<T, U>(x: T) -> U;
538
539/// Checks if all mask values are true.
540///
541/// `T` must be a vector of integer primitive types.
542///
543/// # Safety
544/// `x` must contain only `0` or `!0`.
545#[rustc_intrinsic]
546#[rustc_nounwind]
547#[cfg(not(feature = "ferrocene_subset"))]
548pub const unsafe fn simd_reduce_all<T>(x: T) -> bool;
549
550/// Checks if any mask value is true.
551///
552/// `T` must be a vector of integer primitive types.
553///
554/// # Safety
555/// `x` must contain only `0` or `!0`.
556#[rustc_intrinsic]
557#[rustc_nounwind]
558#[cfg(not(feature = "ferrocene_subset"))]
559pub const unsafe fn simd_reduce_any<T>(x: T) -> bool;
560
561/// Returns the maximum element of a vector.
562///
563/// `T` must be a vector of integers or floats.
564///
565/// `U` must be the element type of `T`.
566///
567/// For floating-point values, uses IEEE-754 `maxNum`.
568#[rustc_intrinsic]
569#[rustc_nounwind]
570#[cfg(not(feature = "ferrocene_subset"))]
571pub const unsafe fn simd_reduce_max<T, U>(x: T) -> U;
572
573/// Returns the minimum element of a vector.
574///
575/// `T` must be a vector of integers or floats.
576///
577/// `U` must be the element type of `T`.
578///
579/// For floating-point values, uses IEEE-754 `minNum`.
580#[rustc_intrinsic]
581#[rustc_nounwind]
582#[cfg(not(feature = "ferrocene_subset"))]
583pub const unsafe fn simd_reduce_min<T, U>(x: T) -> U;
584
585/// Logical "and"s all elements together.
586///
587/// `T` must be a vector of integers or floats.
588///
589/// `U` must be the element type of `T`.
590#[rustc_intrinsic]
591#[rustc_nounwind]
592#[cfg(not(feature = "ferrocene_subset"))]
593pub const unsafe fn simd_reduce_and<T, U>(x: T) -> U;
594
595/// Logical "ors" all elements together.
596///
597/// `T` must be a vector of integers or floats.
598///
599/// `U` must be the element type of `T`.
600#[rustc_intrinsic]
601#[rustc_nounwind]
602#[cfg(not(feature = "ferrocene_subset"))]
603pub const unsafe fn simd_reduce_or<T, U>(x: T) -> U;
604
605/// Logical "exclusive ors" all elements together.
606///
607/// `T` must be a vector of integers or floats.
608///
609/// `U` must be the element type of `T`.
610#[rustc_intrinsic]
611#[rustc_nounwind]
612#[cfg(not(feature = "ferrocene_subset"))]
613pub const unsafe fn simd_reduce_xor<T, U>(x: T) -> U;
614
615/// Truncates an integer vector to a bitmask.
616///
617/// `T` must be an integer vector.
618///
619/// `U` must be either the smallest unsigned integer with at least as many bits as the length
620/// of `T`, or the smallest array of `u8` with at least as many bits as the length of `T`.
621///
622/// Each element is truncated to a single bit and packed into the result.
623///
624/// No matter whether the output is an array or an unsigned integer, it is treated as a single
625/// contiguous list of bits. The bitmask is always packed on the least-significant side of the
626/// output, and padded with 0s in the most-significant bits. The order of the bits depends on
627/// endianness:
628///
629/// * On little endian, the least significant bit corresponds to the first vector element.
630/// * On big endian, the least significant bit corresponds to the last vector element.
631///
632/// For example, `[!0, 0, !0, !0]` packs to
633/// - `0b1101u8` or `[0b1101]` on little endian, and
634/// - `0b1011u8` or `[0b1011]` on big endian.
635///
636/// To consider a larger example,
637/// `[!0, 0, 0, 0, 0, 0, 0, 0, !0, !0, 0, 0, 0, 0, !0, 0]` packs to
638/// - `0b0100001100000001u16` or `[0b00000001, 0b01000011]` on little endian, and
639/// - `0b1000000011000010u16` or `[0b10000000, 0b11000010]` on big endian.
640///
641/// And finally, a non-power-of-2 example with multiple bytes:
642/// `[!0, !0, 0, !0, 0, 0, !0, 0, !0, 0]` packs to
643/// - `0b0101001011u16` or `[0b01001011, 0b01]` on little endian, and
644/// - `0b1101001010u16` or `[0b11, 0b01001010]` on big endian.
645///
646/// # Safety
647/// `x` must contain only `0` and `!0`.
648#[rustc_intrinsic]
649#[rustc_nounwind]
650#[cfg(not(feature = "ferrocene_subset"))]
651pub const unsafe fn simd_bitmask<T, U>(x: T) -> U;
652
653/// Selects elements from a mask.
654///
655/// `T` must be a vector.
656///
657/// `M` must be an integer vector with the same length as `T` (but any element size).
658///
659/// For each element, if the corresponding value in `mask` is `!0`, select the element from
660/// `if_true`. If the corresponding value in `mask` is `0`, select the element from
661/// `if_false`.
662///
663/// # Safety
664/// `mask` must only contain `0` and `!0`.
665#[rustc_intrinsic]
666#[rustc_nounwind]
667#[cfg(not(feature = "ferrocene_subset"))]
668pub const unsafe fn simd_select<M, T>(mask: M, if_true: T, if_false: T) -> T;
669
670/// Selects elements from a bitmask.
671///
672/// `M` must be an unsigned integer or array of `u8`, matching `simd_bitmask`.
673///
674/// `T` must be a vector.
675///
676/// For each element, if the bit in `mask` is `1`, select the element from
677/// `if_true`. If the corresponding bit in `mask` is `0`, select the element from
678/// `if_false`.
679/// The remaining bits of the mask are ignored.
680///
681/// The bitmask bit order matches `simd_bitmask`.
682#[rustc_intrinsic]
683#[rustc_nounwind]
684#[cfg(not(feature = "ferrocene_subset"))]
685pub const unsafe fn simd_select_bitmask<M, T>(m: M, yes: T, no: T) -> T;
686
687/// Calculates the offset from a pointer vector elementwise, potentially
688/// wrapping.
689///
690/// `T` must be a vector of pointers.
691///
692/// `U` must be a vector of `isize` or `usize` with the same number of elements as `T`.
693///
694/// Operates as if by `<ptr>::wrapping_offset`.
695#[rustc_intrinsic]
696#[rustc_nounwind]
697#[cfg(not(feature = "ferrocene_subset"))]
698pub const unsafe fn simd_arith_offset<T, U>(ptr: T, offset: U) -> T;
699
700/// Casts a vector of pointers.
701///
702/// `T` and `U` must be vectors of pointers with the same number of elements.
703#[rustc_intrinsic]
704#[rustc_nounwind]
705#[cfg(not(feature = "ferrocene_subset"))]
706pub const unsafe fn simd_cast_ptr<T, U>(ptr: T) -> U;
707
708/// Exposes a vector of pointers as a vector of addresses.
709///
710/// `T` must be a vector of pointers.
711///
712/// `U` must be a vector of `usize` with the same length as `T`.
713#[rustc_intrinsic]
714#[rustc_nounwind]
715#[cfg(not(feature = "ferrocene_subset"))]
716pub unsafe fn simd_expose_provenance<T, U>(ptr: T) -> U;
717
718/// Creates a vector of pointers from a vector of addresses.
719///
720/// `T` must be a vector of `usize`.
721///
722/// `U` must be a vector of pointers, with the same length as `T`.
723#[rustc_intrinsic]
724#[rustc_nounwind]
725#[cfg(not(feature = "ferrocene_subset"))]
726pub const unsafe fn simd_with_exposed_provenance<T, U>(addr: T) -> U;
727
728/// Swaps bytes of each element.
729///
730/// `T` must be a vector of integers.
731#[rustc_intrinsic]
732#[rustc_nounwind]
733#[cfg(not(feature = "ferrocene_subset"))]
734pub const unsafe fn simd_bswap<T>(x: T) -> T;
735
736/// Reverses bits of each element.
737///
738/// `T` must be a vector of integers.
739#[rustc_intrinsic]
740#[rustc_nounwind]
741#[cfg(not(feature = "ferrocene_subset"))]
742pub const unsafe fn simd_bitreverse<T>(x: T) -> T;
743
744/// Counts the leading zeros of each element.
745///
746/// `T` must be a vector of integers.
747#[rustc_intrinsic]
748#[rustc_nounwind]
749#[cfg(not(feature = "ferrocene_subset"))]
750pub const unsafe fn simd_ctlz<T>(x: T) -> T;
751
752/// Counts the number of ones in each element.
753///
754/// `T` must be a vector of integers.
755#[rustc_intrinsic]
756#[rustc_nounwind]
757#[cfg(not(feature = "ferrocene_subset"))]
758pub const unsafe fn simd_ctpop<T>(x: T) -> T;
759
760/// Counts the trailing zeros of each element.
761///
762/// `T` must be a vector of integers.
763#[rustc_intrinsic]
764#[rustc_nounwind]
765#[cfg(not(feature = "ferrocene_subset"))]
766pub const unsafe fn simd_cttz<T>(x: T) -> T;
767
768/// Rounds up each element to the next highest integer-valued float.
769///
770/// `T` must be a vector of floats.
771#[rustc_intrinsic]
772#[rustc_nounwind]
773#[cfg(not(feature = "ferrocene_subset"))]
774pub const unsafe fn simd_ceil<T>(x: T) -> T;
775
776/// Rounds down each element to the next lowest integer-valued float.
777///
778/// `T` must be a vector of floats.
779#[rustc_intrinsic]
780#[rustc_nounwind]
781#[cfg(not(feature = "ferrocene_subset"))]
782pub const unsafe fn simd_floor<T>(x: T) -> T;
783
784/// Rounds each element to the closest integer-valued float.
785/// Ties are resolved by rounding away from 0.
786///
787/// `T` must be a vector of floats.
788#[rustc_intrinsic]
789#[rustc_nounwind]
790#[cfg(not(feature = "ferrocene_subset"))]
791pub const unsafe fn simd_round<T>(x: T) -> T;
792
793/// Rounds each element to the closest integer-valued float.
794/// Ties are resolved by rounding to the number with an even least significant digit
795///
796/// `T` must be a vector of floats.
797#[rustc_intrinsic]
798#[rustc_nounwind]
799#[cfg(not(feature = "ferrocene_subset"))]
800pub const unsafe fn simd_round_ties_even<T>(x: T) -> T;
801
802/// Returns the integer part of each element as an integer-valued float.
803/// In other words, non-integer values are truncated towards zero.
804///
805/// `T` must be a vector of floats.
806#[rustc_intrinsic]
807#[rustc_nounwind]
808#[cfg(not(feature = "ferrocene_subset"))]
809pub const unsafe fn simd_trunc<T>(x: T) -> T;
810
811/// Takes the square root of each element.
812///
813/// `T` must be a vector of floats.
814#[rustc_intrinsic]
815#[rustc_nounwind]
816#[cfg(not(feature = "ferrocene_subset"))]
817pub unsafe fn simd_fsqrt<T>(x: T) -> T;
818
819/// Computes `(x*y) + z` for each element, but without any intermediate rounding.
820///
821/// `T` must be a vector of floats.
822#[rustc_intrinsic]
823#[rustc_nounwind]
824pub const unsafe fn simd_fma<T>(x: T, y: T, z: T) -> T;
825
826/// Computes `(x*y) + z` for each element, non-deterministically executing either
827/// a fused multiply-add or two operations with rounding of the intermediate result.
828///
829/// The operation is fused if the code generator determines that target instruction
830/// set has support for a fused operation, and that the fused operation is more efficient
831/// than the equivalent, separate pair of mul and add instructions. It is unspecified
832/// whether or not a fused operation is selected, and that may depend on optimization
833/// level and context, for example. It may even be the case that some SIMD lanes get fused
834/// and others do not.
835///
836/// `T` must be a vector of floats.
837#[rustc_intrinsic]
838#[rustc_nounwind]
839#[cfg(not(feature = "ferrocene_subset"))]
840pub const unsafe fn simd_relaxed_fma<T>(x: T, y: T, z: T) -> T;
841
842// Computes the sine of each element.
843///
844/// `T` must be a vector of floats.
845#[rustc_intrinsic]
846#[rustc_nounwind]
847#[cfg(not(feature = "ferrocene_subset"))]
848pub unsafe fn simd_fsin<T>(a: T) -> T;
849
850// Computes the cosine of each element.
851///
852/// `T` must be a vector of floats.
853#[rustc_intrinsic]
854#[rustc_nounwind]
855#[cfg(not(feature = "ferrocene_subset"))]
856pub unsafe fn simd_fcos<T>(a: T) -> T;
857
858// Computes the exponential function of each element.
859///
860/// `T` must be a vector of floats.
861#[rustc_intrinsic]
862#[rustc_nounwind]
863#[cfg(not(feature = "ferrocene_subset"))]
864pub unsafe fn simd_fexp<T>(a: T) -> T;
865
866// Computes 2 raised to the power of each element.
867///
868/// `T` must be a vector of floats.
869#[rustc_intrinsic]
870#[rustc_nounwind]
871#[cfg(not(feature = "ferrocene_subset"))]
872pub unsafe fn simd_fexp2<T>(a: T) -> T;
873
874// Computes the base 10 logarithm of each element.
875///
876/// `T` must be a vector of floats.
877#[rustc_intrinsic]
878#[rustc_nounwind]
879#[cfg(not(feature = "ferrocene_subset"))]
880pub unsafe fn simd_flog10<T>(a: T) -> T;
881
882// Computes the base 2 logarithm of each element.
883///
884/// `T` must be a vector of floats.
885#[rustc_intrinsic]
886#[rustc_nounwind]
887#[cfg(not(feature = "ferrocene_subset"))]
888pub unsafe fn simd_flog2<T>(a: T) -> T;
889
890// Computes the natural logarithm of each element.
891///
892/// `T` must be a vector of floats.
893#[rustc_intrinsic]
894#[rustc_nounwind]
895#[cfg(not(feature = "ferrocene_subset"))]
896pub unsafe fn simd_flog<T>(a: T) -> T;