Skip to content

Commit 9cc8723

Browse files
authored
Unrolled build for #142078
Rollup merge of #142078 - sayantn:more-intrinsics, r=workingjubilee Add SIMD funnel shift and round-to-even intrinsics This PR adds 3 new SIMD intrinsics - `simd_funnel_shl` - funnel shift left - `simd_funnel_shr` - funnel shift right - `simd_round_ties_even` (vector version of `round_ties_even_fN`) TODO (future PR): implement `simd_fsh{l,r}` in miri, cg_gcc and cg_clif (it is surprisingly hard to implement without branches, the common tricks that rotate uses doesn't work because we have 2 elements now. e.g, the `-n&31` trick used by cg_gcc to implement rotate doesn't work with this because then `fshl(a, b, 0)` will be `a | b`) [#t-compiler > More SIMD intrinsics](https://rust-lang.zulipchat.com/#narrow/channel/131828-t-compiler/topic/More.20SIMD.20intrinsics/with/522130286) `@rustbot` label T-compiler T-libs A-intrinsics F-core_intrinsics r? `@workingjubilee`
2 parents 5ca574e + 2ffa1dd commit 9cc8723

File tree

12 files changed

+217
-28
lines changed

12 files changed

+217
-28
lines changed

compiler/rustc_codegen_cranelift/src/intrinsics/simd.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -496,7 +496,8 @@ pub(super) fn codegen_simd_intrinsic_call<'tcx>(
496496
| sym::simd_flog
497497
| sym::simd_flog10
498498
| sym::simd_flog2
499-
| sym::simd_round => {
499+
| sym::simd_round
500+
| sym::simd_round_ties_even => {
500501
intrinsic_args!(fx, args => (a); intrinsic);
501502

502503
if !a.layout().ty.is_simd() {
@@ -527,6 +528,8 @@ pub(super) fn codegen_simd_intrinsic_call<'tcx>(
527528
(sym::simd_flog2, types::F64) => "log2",
528529
(sym::simd_round, types::F32) => "roundf",
529530
(sym::simd_round, types::F64) => "round",
531+
(sym::simd_round_ties_even, types::F32) => "rintf",
532+
(sym::simd_round_ties_even, types::F64) => "rint",
530533
_ => unreachable!("{:?}", intrinsic),
531534
};
532535
fx.lib_call(

compiler/rustc_codegen_gcc/src/intrinsic/simd.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -780,6 +780,7 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>(
780780
sym::simd_fsin => "sin",
781781
sym::simd_fsqrt => "sqrt",
782782
sym::simd_round => "round",
783+
sym::simd_round_ties_even => "rint",
783784
sym::simd_trunc => "trunc",
784785
_ => return_error!(InvalidMonomorphization::UnrecognizedIntrinsic { span, name }),
785786
};
@@ -827,6 +828,7 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>(
827828
| sym::simd_fsin
828829
| sym::simd_fsqrt
829830
| sym::simd_round
831+
| sym::simd_round_ties_even
830832
| sym::simd_trunc
831833
) {
832834
return simd_simple_float_intrinsic(name, in_elem, in_ty, in_len, bx, span, args);

compiler/rustc_codegen_llvm/src/intrinsic.rs

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1537,6 +1537,7 @@ fn generic_simd_intrinsic<'ll, 'tcx>(
15371537
sym::simd_fsin => "llvm.sin",
15381538
sym::simd_fsqrt => "llvm.sqrt",
15391539
sym::simd_round => "llvm.round",
1540+
sym::simd_round_ties_even => "llvm.rint",
15401541
sym::simd_trunc => "llvm.trunc",
15411542
_ => return_error!(InvalidMonomorphization::UnrecognizedIntrinsic { span, name }),
15421543
};
@@ -1563,6 +1564,7 @@ fn generic_simd_intrinsic<'ll, 'tcx>(
15631564
| sym::simd_fsqrt
15641565
| sym::simd_relaxed_fma
15651566
| sym::simd_round
1567+
| sym::simd_round_ties_even
15661568
| sym::simd_trunc
15671569
) {
15681570
return simd_simple_float_intrinsic(name, in_elem, in_ty, in_len, bx, span, args);
@@ -2309,7 +2311,13 @@ fn generic_simd_intrinsic<'ll, 'tcx>(
23092311
// Unary integer intrinsics
23102312
if matches!(
23112313
name,
2312-
sym::simd_bswap | sym::simd_bitreverse | sym::simd_ctlz | sym::simd_ctpop | sym::simd_cttz
2314+
sym::simd_bswap
2315+
| sym::simd_bitreverse
2316+
| sym::simd_ctlz
2317+
| sym::simd_ctpop
2318+
| sym::simd_cttz
2319+
| sym::simd_funnel_shl
2320+
| sym::simd_funnel_shr
23132321
) {
23142322
let vec_ty = bx.cx.type_vector(
23152323
match *in_elem.kind() {
@@ -2330,6 +2338,8 @@ fn generic_simd_intrinsic<'ll, 'tcx>(
23302338
sym::simd_ctlz => "llvm.ctlz",
23312339
sym::simd_ctpop => "llvm.ctpop",
23322340
sym::simd_cttz => "llvm.cttz",
2341+
sym::simd_funnel_shl => "llvm.fshl",
2342+
sym::simd_funnel_shr => "llvm.fshr",
23332343
_ => unreachable!(),
23342344
};
23352345
let int_size = in_elem.int_size_and_signed(bx.tcx()).0.bits();
@@ -2350,6 +2360,11 @@ fn generic_simd_intrinsic<'ll, 'tcx>(
23502360
// simple unary argument cases
23512361
Ok(bx.call_intrinsic(llvm_intrinsic, &[vec_ty], &[args[0].immediate()]))
23522362
}
2363+
sym::simd_funnel_shl | sym::simd_funnel_shr => Ok(bx.call_intrinsic(
2364+
llvm_intrinsic,
2365+
&[vec_ty],
2366+
&[args[0].immediate(), args[1].immediate(), args[2].immediate()],
2367+
)),
23532368
_ => unreachable!(),
23542369
};
23552370
}

compiler/rustc_hir_analysis/src/check/intrinsic.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -594,8 +594,9 @@ pub(crate) fn check_intrinsic_type(
594594
| sym::simd_ceil
595595
| sym::simd_floor
596596
| sym::simd_round
597+
| sym::simd_round_ties_even
597598
| sym::simd_trunc => (1, 0, vec![param(0)], param(0)),
598-
sym::simd_fma | sym::simd_relaxed_fma => {
599+
sym::simd_fma | sym::simd_relaxed_fma | sym::simd_funnel_shl | sym::simd_funnel_shr => {
599600
(1, 0, vec![param(0), param(0), param(0)], param(0))
600601
}
601602
sym::simd_gather => (3, 0, vec![param(0), param(1), param(2)], param(0)),

compiler/rustc_span/src/symbol.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1977,6 +1977,8 @@ symbols! {
19771977
simd_fmin,
19781978
simd_fsin,
19791979
simd_fsqrt,
1980+
simd_funnel_shl,
1981+
simd_funnel_shr,
19801982
simd_gather,
19811983
simd_ge,
19821984
simd_gt,
@@ -2004,6 +2006,7 @@ symbols! {
20042006
simd_relaxed_fma,
20052007
simd_rem,
20062008
simd_round,
2009+
simd_round_ties_even,
20072010
simd_saturating_add,
20082011
simd_saturating_sub,
20092012
simd_scatter,

library/core/src/intrinsics/simd.rs

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,40 @@ pub unsafe fn simd_shl<T>(lhs: T, rhs: T) -> T;
126126
#[rustc_nounwind]
127127
pub unsafe fn simd_shr<T>(lhs: T, rhs: T) -> T;
128128

129+
/// Funnel Shifts vector left elementwise, with UB on overflow.
130+
///
131+
/// Concatenates `a` and `b` elementwise (with `a` in the most significant half),
132+
/// creating a vector of the same length, but with each element being twice as
133+
/// wide. Then shift this vector left elementwise by `shift`, shifting in zeros,
134+
/// and extract the most significant half of each of the elements. If `a` and `b`
135+
/// are the same, this is equivalent to an elementwise rotate left operation.
136+
///
137+
/// `T` must be a vector of integers.
138+
///
139+
/// # Safety
140+
///
141+
/// Each element of `shift` must be less than `<int>::BITS`.
142+
#[rustc_intrinsic]
143+
#[rustc_nounwind]
144+
pub unsafe fn simd_funnel_shl<T>(a: T, b: T, shift: T) -> T;
145+
146+
/// Funnel Shifts vector right elementwise, with UB on overflow.
147+
///
148+
/// Concatenates `a` and `b` elementwise (with `a` in the most significant half),
149+
/// creating a vector of the same length, but with each element being twice as
150+
/// wide. Then shift this vector right elementwise by `shift`, shifting in zeros,
151+
/// and extract the least significant half of each of the elements. If `a` and `b`
152+
/// are the same, this is equivalent to an elementwise rotate right operation.
153+
///
154+
/// `T` must be a vector of integers.
155+
///
156+
/// # Safety
157+
///
158+
/// Each element of `shift` must be less than `<int>::BITS`.
159+
#[rustc_intrinsic]
160+
#[rustc_nounwind]
161+
pub unsafe fn simd_funnel_shr<T>(a: T, b: T, shift: T) -> T;
162+
129163
/// "Ands" vectors elementwise.
130164
///
131165
/// `T` must be a vector of integers.
@@ -678,6 +712,14 @@ pub unsafe fn simd_floor<T>(x: T) -> T;
678712
#[rustc_nounwind]
679713
pub unsafe fn simd_round<T>(x: T) -> T;
680714

715+
/// Rounds each element to the closest integer-valued float.
716+
/// Ties are resolved by rounding to the number with an even least significant digit
717+
///
718+
/// `T` must be a vector of floats.
719+
#[rustc_intrinsic]
720+
#[rustc_nounwind]
721+
pub unsafe fn simd_round_ties_even<T>(x: T) -> T;
722+
681723
/// Returns the integer part of each element as an integer-valued float.
682724
/// In other words, non-integer values are truncated towards zero.
683725
///

src/tools/miri/src/intrinsics/simd.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
3636
| "ceil"
3737
| "floor"
3838
| "round"
39+
| "round_ties_even"
3940
| "trunc"
4041
| "fsqrt"
4142
| "fsin"
@@ -71,6 +72,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
7172
"ceil" => Op::Round(rustc_apfloat::Round::TowardPositive),
7273
"floor" => Op::Round(rustc_apfloat::Round::TowardNegative),
7374
"round" => Op::Round(rustc_apfloat::Round::NearestTiesToAway),
75+
"round_ties_even" => Op::Round(rustc_apfloat::Round::NearestTiesToEven),
7476
"trunc" => Op::Round(rustc_apfloat::Round::TowardZero),
7577
"ctlz" => Op::Numeric(sym::ctlz),
7678
"ctpop" => Op::Numeric(sym::ctpop),

src/tools/miri/tests/pass/intrinsics/portable-simd.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -569,6 +569,10 @@ fn simd_round() {
569569
f32x4::from_array([0.9, 1.001, 2.0, -4.5]).round(),
570570
f32x4::from_array([1.0, 1.0, 2.0, -5.0])
571571
);
572+
assert_eq!(
573+
unsafe { intrinsics::simd_round_ties_even(f32x4::from_array([0.9, 1.001, 2.0, -4.5])) },
574+
f32x4::from_array([1.0, 1.0, 2.0, -4.0])
575+
);
572576
assert_eq!(
573577
f32x4::from_array([0.9, 1.001, 2.0, -4.5]).trunc(),
574578
f32x4::from_array([0.0, 1.0, 2.0, -4.0])
@@ -586,6 +590,10 @@ fn simd_round() {
586590
f64x4::from_array([0.9, 1.001, 2.0, -4.5]).round(),
587591
f64x4::from_array([1.0, 1.0, 2.0, -5.0])
588592
);
593+
assert_eq!(
594+
unsafe { intrinsics::simd_round_ties_even(f64x4::from_array([0.9, 1.001, 2.0, -4.5])) },
595+
f64x4::from_array([1.0, 1.0, 2.0, -4.0])
596+
);
589597
assert_eq!(
590598
f64x4::from_array([0.9, 1.001, 2.0, -4.5]).trunc(),
591599
f64x4::from_array([0.0, 1.0, 2.0, -4.0])

tests/ui/simd/intrinsic/float-math-pass.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,9 @@ fn main() {
8585
let r = simd_round(h);
8686
assert_eq!(x, r);
8787

88+
let r = simd_round_ties_even(h);
89+
assert_eq!(z, r);
90+
8891
let r = simd_trunc(h);
8992
assert_eq!(z, r);
9093
}

tests/ui/simd/intrinsic/generic-arithmetic-2.rs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,10 @@ fn main() {
4343
simd_shl(y, y);
4444
simd_shr(x, x);
4545
simd_shr(y, y);
46+
simd_funnel_shl(x, x, x);
47+
simd_funnel_shl(y, y, y);
48+
simd_funnel_shr(x, x, x);
49+
simd_funnel_shr(y, y, y);
4650
simd_and(x, x);
4751
simd_and(y, y);
4852
simd_or(x, x);
@@ -73,6 +77,10 @@ fn main() {
7377
//~^ ERROR expected SIMD input type, found non-SIMD `i32`
7478
simd_shr(0, 0);
7579
//~^ ERROR expected SIMD input type, found non-SIMD `i32`
80+
simd_funnel_shl(0, 0, 0);
81+
//~^ ERROR expected SIMD input type, found non-SIMD `i32`
82+
simd_funnel_shr(0, 0, 0);
83+
//~^ ERROR expected SIMD input type, found non-SIMD `i32`
7684
simd_and(0, 0);
7785
//~^ ERROR expected SIMD input type, found non-SIMD `i32`
7886
simd_or(0, 0);
@@ -95,6 +103,10 @@ fn main() {
95103
//~^ ERROR unsupported operation on `f32x4` with element `f32`
96104
simd_shr(z, z);
97105
//~^ ERROR unsupported operation on `f32x4` with element `f32`
106+
simd_funnel_shl(z, z, z);
107+
//~^ ERROR unsupported operation on `f32x4` with element `f32`
108+
simd_funnel_shr(z, z, z);
109+
//~^ ERROR unsupported operation on `f32x4` with element `f32`
98110
simd_and(z, z);
99111
//~^ ERROR unsupported operation on `f32x4` with element `f32`
100112
simd_or(z, z);

0 commit comments

Comments
 (0)