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] |
14 | pub 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] |
25 | pub 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 | #[rustc_intrinsic] |
38 | pub 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(count: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 | #[rustc_intrinsic] |
55 | pub 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(count: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] |
65 | pub 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] |
72 | pub 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] |
79 | pub 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] |
90 | pub 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] |
101 | pub 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] |
114 | pub 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] |
127 | pub 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] |
134 | pub 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] |
141 | pub 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] |
148 | pub 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] |
169 | pub 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] |
183 | pub 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] |
192 | pub 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] |
199 | pub 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] |
208 | pub 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] |
217 | pub 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] |
228 | pub 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] |
239 | pub 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] |
250 | pub 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] |
261 | pub 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] |
272 | pub 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] |
283 | pub 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] |
299 | pub 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 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] |
320 | pub 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 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] |
344 | pub 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 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] |
367 | pub 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 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] |
389 | pub 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] |
396 | pub 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] |
405 | pub 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] |
416 | pub 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] |
426 | pub 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] |
437 | pub 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] |
447 | pub 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] |
457 | pub 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] |
467 | pub 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] |
478 | pub 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] |
489 | pub 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] |
498 | pub 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] |
507 | pub 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] |
516 | pub 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] |
553 | pub 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 an 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] |
569 | pub 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 | /// The remaining bits of the mask are ignored. |
581 | /// |
582 | /// The bitmask bit order matches `simd_bitmask`. |
583 | #[rustc_intrinsic] |
584 | #[rustc_nounwind] |
585 | pub unsafe fn simd_select_bitmask<M, T>(m: M, yes: T, no: T) -> T; |
586 | |
587 | /// Calculates the offset from a pointer vector elementwise, potentially |
588 | /// wrapping. |
589 | /// |
590 | /// `T` must be a vector of pointers. |
591 | /// |
592 | /// `U` must be a vector of `isize` or `usize` with the same number of elements as `T`. |
593 | /// |
594 | /// Operates as if by `<ptr>::wrapping_offset`. |
595 | #[rustc_intrinsic] |
596 | #[rustc_nounwind] |
597 | pub unsafe fn simd_arith_offset<T, U>(ptr: T, offset: U) -> T; |
598 | |
599 | /// Casts a vector of pointers. |
600 | /// |
601 | /// `T` and `U` must be vectors of pointers with the same number of elements. |
602 | #[rustc_intrinsic] |
603 | #[rustc_nounwind] |
604 | pub unsafe fn simd_cast_ptr<T, U>(ptr: T) -> U; |
605 | |
606 | /// Exposes a vector of pointers as a vector of addresses. |
607 | /// |
608 | /// `T` must be a vector of pointers. |
609 | /// |
610 | /// `U` must be a vector of `usize` with the same length as `T`. |
611 | #[rustc_intrinsic] |
612 | #[rustc_nounwind] |
613 | pub unsafe fn simd_expose_provenance<T, U>(ptr: T) -> U; |
614 | |
615 | /// Creates a vector of pointers from a vector of addresses. |
616 | /// |
617 | /// `T` must be a vector of `usize`. |
618 | /// |
619 | /// `U` must be a vector of pointers, with the same length as `T`. |
620 | #[rustc_intrinsic] |
621 | #[rustc_nounwind] |
622 | pub unsafe fn simd_with_exposed_provenance<T, U>(addr: T) -> U; |
623 | |
624 | /// Swaps bytes of each element. |
625 | /// |
626 | /// `T` must be a vector of integers. |
627 | #[rustc_intrinsic] |
628 | #[rustc_nounwind] |
629 | pub unsafe fn simd_bswap<T>(x: T) -> T; |
630 | |
631 | /// Reverses bits of each element. |
632 | /// |
633 | /// `T` must be a vector of integers. |
634 | #[rustc_intrinsic] |
635 | #[rustc_nounwind] |
636 | pub unsafe fn simd_bitreverse<T>(x: T) -> T; |
637 | |
638 | /// Counts the leading zeros of each element. |
639 | /// |
640 | /// `T` must be a vector of integers. |
641 | #[rustc_intrinsic] |
642 | #[rustc_nounwind] |
643 | pub unsafe fn simd_ctlz<T>(x: T) -> T; |
644 | |
645 | /// Counts the number of ones in each element. |
646 | /// |
647 | /// `T` must be a vector of integers. |
648 | #[rustc_intrinsic] |
649 | #[rustc_nounwind] |
650 | pub unsafe fn simd_ctpop<T>(x: T) -> T; |
651 | |
652 | /// Counts the trailing zeros of each element. |
653 | /// |
654 | /// `T` must be a vector of integers. |
655 | #[rustc_intrinsic] |
656 | #[rustc_nounwind] |
657 | pub unsafe fn simd_cttz<T>(x: T) -> T; |
658 | |
659 | /// Rounds up each element to the next highest integer-valued float. |
660 | /// |
661 | /// `T` must be a vector of floats. |
662 | #[rustc_intrinsic] |
663 | #[rustc_nounwind] |
664 | pub unsafe fn simd_ceil<T>(x: T) -> T; |
665 | |
666 | /// Rounds down each element to the next lowest integer-valued float. |
667 | /// |
668 | /// `T` must be a vector of floats. |
669 | #[rustc_intrinsic] |
670 | #[rustc_nounwind] |
671 | pub unsafe fn simd_floor<T>(x: T) -> T; |
672 | |
673 | /// Rounds each element to the closest integer-valued float. |
674 | /// Ties are resolved by rounding away from 0. |
675 | /// |
676 | /// `T` must be a vector of floats. |
677 | #[rustc_intrinsic] |
678 | #[rustc_nounwind] |
679 | pub unsafe fn simd_round<T>(x: T) -> T; |
680 | |
681 | /// Returns the integer part of each element as an integer-valued float. |
682 | /// In other words, non-integer values are truncated towards zero. |
683 | /// |
684 | /// `T` must be a vector of floats. |
685 | #[rustc_intrinsic] |
686 | #[rustc_nounwind] |
687 | pub unsafe fn simd_trunc<T>(x: T) -> T; |
688 | |
689 | /// Takes the square root of each element. |
690 | /// |
691 | /// `T` must be a vector of floats. |
692 | #[rustc_intrinsic] |
693 | #[rustc_nounwind] |
694 | pub unsafe fn simd_fsqrt<T>(x: T) -> T; |
695 | |
696 | /// Computes `(x*y) + z` for each element, but without any intermediate rounding. |
697 | /// |
698 | /// `T` must be a vector of floats. |
699 | #[rustc_intrinsic] |
700 | #[rustc_nounwind] |
701 | pub unsafe fn simd_fma<T>(x: T, y: T, z: T) -> T; |
702 | |
703 | /// Computes `(x*y) + z` for each element, non-deterministically executing either |
704 | /// a fused multiply-add or two operations with rounding of the intermediate result. |
705 | /// |
706 | /// The operation is fused if the code generator determines that target instruction |
707 | /// set has support for a fused operation, and that the fused operation is more efficient |
708 | /// than the equivalent, separate pair of mul and add instructions. It is unspecified |
709 | /// whether or not a fused operation is selected, and that may depend on optimization |
710 | /// level and context, for example. It may even be the case that some SIMD lanes get fused |
711 | /// and others do not. |
712 | /// |
713 | /// `T` must be a vector of floats. |
714 | #[rustc_intrinsic] |
715 | #[rustc_nounwind] |
716 | pub unsafe fn simd_relaxed_fma<T>(x: T, y: T, z: T) -> T; |
717 | |
718 | // Computes the sine of each element. |
719 | /// |
720 | /// `T` must be a vector of floats. |
721 | #[rustc_intrinsic] |
722 | #[rustc_nounwind] |
723 | pub unsafe fn simd_fsin<T>(a: T) -> T; |
724 | |
725 | // Computes the cosine of each element. |
726 | /// |
727 | /// `T` must be a vector of floats. |
728 | #[rustc_intrinsic] |
729 | #[rustc_nounwind] |
730 | pub unsafe fn simd_fcos<T>(a: T) -> T; |
731 | |
732 | // Computes the exponential function of each element. |
733 | /// |
734 | /// `T` must be a vector of floats. |
735 | #[rustc_intrinsic] |
736 | #[rustc_nounwind] |
737 | pub unsafe fn simd_fexp<T>(a: T) -> T; |
738 | |
739 | // Computes 2 raised to the power of each element. |
740 | /// |
741 | /// `T` must be a vector of floats. |
742 | #[rustc_intrinsic] |
743 | #[rustc_nounwind] |
744 | pub unsafe fn simd_fexp2<T>(a: T) -> T; |
745 | |
746 | // Computes the base 10 logarithm of each element. |
747 | /// |
748 | /// `T` must be a vector of floats. |
749 | #[rustc_intrinsic] |
750 | #[rustc_nounwind] |
751 | pub unsafe fn simd_flog10<T>(a: T) -> T; |
752 | |
753 | // Computes the base 2 logarithm of each element. |
754 | /// |
755 | /// `T` must be a vector of floats. |
756 | #[rustc_intrinsic] |
757 | #[rustc_nounwind] |
758 | pub unsafe fn simd_flog2<T>(a: T) -> T; |
759 | |
760 | // Computes the natural logarithm of each element. |
761 | /// |
762 | /// `T` must be a vector of floats. |
763 | #[rustc_intrinsic] |
764 | #[rustc_nounwind] |
765 | pub unsafe fn simd_flog<T>(a: T) -> T; |
766 |
Definitions
- simd_insert
- simd_extract
- simd_insert_dyn
- simd_extract_dyn
- simd_add
- simd_sub
- simd_mul
- simd_div
- simd_rem
- simd_shl
- simd_shr
- simd_and
- simd_or
- simd_xor
- simd_cast
- simd_as
- simd_neg
- simd_fabs
- simd_fmin
- simd_fmax
- simd_eq
- simd_ne
- simd_lt
- simd_le
- simd_gt
- simd_ge
- simd_shuffle
- simd_gather
- simd_scatter
- simd_masked_load
- simd_masked_store
- simd_saturating_add
- simd_saturating_sub
- simd_reduce_add_ordered
- simd_reduce_add_unordered
- simd_reduce_mul_ordered
- simd_reduce_mul_unordered
- simd_reduce_all
- simd_reduce_any
- simd_reduce_max
- simd_reduce_min
- simd_reduce_and
- simd_reduce_or
- simd_reduce_xor
- simd_bitmask
- simd_select
- simd_select_bitmask
- simd_arith_offset
- simd_cast_ptr
- simd_expose_provenance
- simd_with_exposed_provenance
- simd_bswap
- simd_bitreverse
- simd_ctlz
- simd_ctpop
- simd_cttz
- simd_ceil
- simd_floor
- simd_round
- simd_trunc
- simd_fsqrt
- simd_fma
- simd_relaxed_fma
- simd_fsin
- simd_fcos
- simd_fexp
- simd_fexp2
- simd_flog10
- simd_flog2
Learn Rust with the experts
Find out more