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