Skip to content

Commit 40c14d9

Browse files
committed
Add funnel_sh{l,r} functions and intrinsics
1 parent 040a98a commit 40c14d9

File tree

3 files changed

+116
-0
lines changed

3 files changed

+116
-0
lines changed

library/core/src/intrinsics/mod.rs

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2102,6 +2102,48 @@ pub const fn saturating_add<T: Copy>(a: T, b: T) -> T;
21022102
#[rustc_intrinsic]
21032103
pub const fn saturating_sub<T: Copy>(a: T, b: T) -> T;
21042104

2105+
/// Funnel Shift left, with wrapping on overflow.
2106+
///
2107+
/// Concatenates `a` and `b` (with `a` in the most significant half),
2108+
/// creating an integer twice as wide. Then shift this vector left
2109+
/// by `shift`, shifting in zeros, and extract the most significant
2110+
/// half. If `a` and `b` are the same, this is equivalent to a rotate
2111+
/// left operation.
2112+
///
2113+
/// Note that, unlike most intrinsics, this is safe to call;
2114+
/// it does not require an `unsafe` block.
2115+
/// Therefore, implementations must not require the user to uphold
2116+
/// any safety invariants.
2117+
///
2118+
/// Safer versions of this intrinsic are available on the integer primitives
2119+
/// via the `funnel_shl` method. For example, [`u32::funnel_shl`].
2120+
#[rustc_intrinsic]
2121+
#[rustc_nounwind]
2122+
#[rustc_const_unstable(feature = "funnel_shifts", issue = "145686")]
2123+
#[unstable(feature = "funnel_shifts", issue = "145686")]
2124+
pub const fn funnel_shl<T: Copy>(a: T, b: T, shift: u32) -> T;
2125+
2126+
/// Funnel Shift right, with wrapping on overflow.
2127+
///
2128+
/// Concatenates `a` and `b` (with `a` in the most significant half),
2129+
/// creating an integer twice as wide. Then shift this vector right
2130+
/// by `shift`, shifting in zeros, and extract the least significant
2131+
/// half. If `a` and `b` are the same, this is equivalent to a rotate
2132+
/// right operation.
2133+
///
2134+
/// Note that, unlike most intrinsics, this is safe to call;
2135+
/// it does not require an `unsafe` block.
2136+
/// Therefore, implementations must not require the user to uphold
2137+
/// any safety invariants.
2138+
///
2139+
/// Safer versions of this intrinsic are available on the integer primitives
2140+
/// via the `funnel_shr` method. For example, [`u32::funnel_shr`]
2141+
#[rustc_intrinsic]
2142+
#[rustc_nounwind]
2143+
#[rustc_const_unstable(feature = "funnel_shifts", issue = "145686")]
2144+
#[unstable(feature = "funnel_shifts", issue = "145686")]
2145+
pub const fn funnel_shr<T: Copy>(a: T, b: T, shift: u32) -> T;
2146+
21052147
/// This is an implementation detail of [`crate::ptr::read`] and should
21062148
/// not be used anywhere else. See its comments for why this exists.
21072149
///

library/core/src/num/mod.rs

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -454,6 +454,9 @@ impl u8 {
454454
rot = 2,
455455
rot_op = "0x82",
456456
rot_result = "0xa",
457+
fsh_op = "0x36",
458+
fshl_result = "0x8",
459+
fshr_result = "0x8d",
457460
swap_op = "0x12",
458461
swapped = "0x12",
459462
reversed = "0x48",
@@ -1088,6 +1091,9 @@ impl u16 {
10881091
rot = 4,
10891092
rot_op = "0xa003",
10901093
rot_result = "0x3a",
1094+
fsh_op = "0x2de",
1095+
fshl_result = "0x30",
1096+
fshr_result = "0x302d",
10911097
swap_op = "0x1234",
10921098
swapped = "0x3412",
10931099
reversed = "0x2c48",
@@ -1135,6 +1141,9 @@ impl u32 {
11351141
rot = 8,
11361142
rot_op = "0x10000b3",
11371143
rot_result = "0xb301",
1144+
fsh_op = "0x2fe78e45",
1145+
fshl_result = "0xb32f",
1146+
fshr_result = "0xb32fe78e",
11381147
swap_op = "0x12345678",
11391148
swapped = "0x78563412",
11401149
reversed = "0x1e6a2c48",
@@ -1158,6 +1167,9 @@ impl u64 {
11581167
rot = 12,
11591168
rot_op = "0xaa00000000006e1",
11601169
rot_result = "0x6e10aa",
1170+
fsh_op = "0x2fe78e45983acd98",
1171+
fshl_result = "0x6e12fe",
1172+
fshr_result = "0x6e12fe78e45983ac",
11611173
swap_op = "0x1234567890123456",
11621174
swapped = "0x5634129078563412",
11631175
reversed = "0x6a2c48091e6a2c48",
@@ -1181,6 +1193,9 @@ impl u128 {
11811193
rot = 16,
11821194
rot_op = "0x13f40000000000000000000000004f76",
11831195
rot_result = "0x4f7613f4",
1196+
fsh_op = "0x2fe78e45983acd98039000008736273",
1197+
fshl_result = "0x4f7602fe",
1198+
fshr_result = "0x4f7602fe78e45983acd9803900000873",
11841199
swap_op = "0x12345678901234567890123456789012",
11851200
swapped = "0x12907856341290785634129078563412",
11861201
reversed = "0x48091e6a2c48091e6a2c48091e6a2c48",

library/core/src/num/uint_macros.rs

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,9 @@ macro_rules! uint_impl {
1414
rot = $rot:literal,
1515
rot_op = $rot_op:literal,
1616
rot_result = $rot_result:literal,
17+
fsh_op = $fsh_op:literal,
18+
fshl_result = $fshl_result:literal,
19+
fshr_result = $fshr_result:literal,
1720
swap_op = $swap_op:literal,
1821
swapped = $swapped:literal,
1922
reversed = $reversed:literal,
@@ -375,6 +378,62 @@ macro_rules! uint_impl {
375378
return intrinsics::rotate_right(self, n);
376379
}
377380

381+
/// Performs an left funnel shift (concatenates `rhs` with `self`, with `self`
382+
/// making up the most significant half, then shifts the combined value left
383+
/// by `n`, and most significant half is extracted to produce the result).
384+
///
385+
/// Please note this isn't the same operation as the `<<` shifting operator or
386+
/// [`rotate_left`](Self::rotate_left), although `a.funnel_shl(a, n)` is *equivalent*
387+
/// to `a.rotate_left(n)`.
388+
///
389+
/// # Examples
390+
///
391+
/// Basic usage:
392+
///
393+
/// ```
394+
#[doc = concat!("let a = ", $rot_op, stringify!($SelfT), ";")]
395+
#[doc = concat!("let b = ", $fsh_op, stringify!($SelfT), ";")]
396+
#[doc = concat!("let m = ", $fshl_result, ";")]
397+
///
398+
#[doc = concat!("assert_eq!(a.funnel_shl(b, ", $rot, "), m);")]
399+
/// ```
400+
#[rustc_const_unstable(feature = "funnel_shifts", issue = "145686")]
401+
#[unstable(feature = "funnel_shifts", issue = "145686")]
402+
#[must_use = "this returns the result of the operation, \
403+
without modifying the original"]
404+
#[inline(always)]
405+
pub const fn funnel_shl(self, rhs: Self, n: u32) -> Self {
406+
return intrinsics::funnel_shl(self, rhs, n);
407+
}
408+
409+
/// Performs an right funnel shift (concatenates `self` and `rhs`, with `self`
410+
/// making up the most significant half, then shifts the combined value right
411+
/// by `n`, and least significant half is extracted to produce the result).
412+
///
413+
/// Please note this isn't the same operation as the `>>` shifting operator or
414+
/// [`rotate_right`](Self::rotate_right), although `a.funnel_shr(a, n)` is *equivalent*
415+
/// to `a.rotate_right(n)`.
416+
///
417+
/// # Examples
418+
///
419+
/// Basic usage:
420+
///
421+
/// ```
422+
#[doc = concat!("let a = ", $rot_op, stringify!($SelfT), ";")]
423+
#[doc = concat!("let b = ", $fsh_op, stringify!($SelfT), ";")]
424+
#[doc = concat!("let m = ", $fshr_result, ";")]
425+
///
426+
#[doc = concat!("assert_eq!(a.funnel_shr(b, ", $rot, "), m);")]
427+
/// ```
428+
#[rustc_const_unstable(feature = "funnel_shifts", issue = "145686")]
429+
#[unstable(feature = "funnel_shifts", issue = "145686")]
430+
#[must_use = "this returns the result of the operation, \
431+
without modifying the original"]
432+
#[inline(always)]
433+
pub const fn funnel_shr(self, rhs: Self, n: u32) -> Self {
434+
return intrinsics::funnel_shr(self, rhs, n);
435+
}
436+
378437
/// Reverses the byte order of the integer.
379438
///
380439
/// # Examples

0 commit comments

Comments
 (0)