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