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