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