Skip to content

Commit 51e45a1

Browse files
committed
add simd_insert_dyn and simd_extract_dyn
1 parent f5729cf commit 51e45a1

File tree

6 files changed

+188
-7
lines changed

6 files changed

+188
-7
lines changed

compiler/rustc_codegen_llvm/src/intrinsic.rs

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1445,6 +1445,23 @@ fn generic_simd_intrinsic<'ll, 'tcx>(
14451445
bx.const_i32(idx as i32),
14461446
));
14471447
}
1448+
if name == sym::simd_insert_dyn {
1449+
require!(
1450+
in_elem == arg_tys[2],
1451+
InvalidMonomorphization::InsertedType {
1452+
span,
1453+
name,
1454+
in_elem,
1455+
in_ty,
1456+
out_ty: arg_tys[2]
1457+
}
1458+
);
1459+
return Ok(bx.insert_element(
1460+
args[0].immediate(),
1461+
args[2].immediate(),
1462+
args[1].immediate(),
1463+
));
1464+
}
14481465
if name == sym::simd_extract {
14491466
require!(
14501467
ret_ty == in_elem,
@@ -1463,6 +1480,13 @@ fn generic_simd_intrinsic<'ll, 'tcx>(
14631480
}
14641481
return Ok(bx.extract_element(args[0].immediate(), bx.const_i32(idx as i32)));
14651482
}
1483+
if name == sym::simd_extract_dyn {
1484+
require!(
1485+
ret_ty == in_elem,
1486+
InvalidMonomorphization::ReturnType { span, name, in_elem, in_ty, ret_ty }
1487+
);
1488+
return Ok(bx.extract_element(args[0].immediate(), args[1].immediate()));
1489+
}
14661490

14671491
if name == sym::simd_select {
14681492
let m_elem_ty = in_elem;

compiler/rustc_hir_analysis/src/check/intrinsic.rs

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -676,8 +676,12 @@ pub fn check_intrinsic_type(
676676
sym::simd_masked_load => (3, 0, vec![param(0), param(1), param(2)], param(2)),
677677
sym::simd_masked_store => (3, 0, vec![param(0), param(1), param(2)], tcx.types.unit),
678678
sym::simd_scatter => (3, 0, vec![param(0), param(1), param(2)], tcx.types.unit),
679-
sym::simd_insert => (2, 0, vec![param(0), tcx.types.u32, param(1)], param(0)),
680-
sym::simd_extract => (2, 0, vec![param(0), tcx.types.u32], param(1)),
679+
sym::simd_insert | sym::simd_insert_dyn => {
680+
(2, 0, vec![param(0), tcx.types.u32, param(1)], param(0))
681+
}
682+
sym::simd_extract | sym::simd_extract_dyn => {
683+
(2, 0, vec![param(0), tcx.types.u32], param(1))
684+
}
681685
sym::simd_cast
682686
| sym::simd_as
683687
| sym::simd_cast_ptr

compiler/rustc_span/src/symbol.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1865,6 +1865,7 @@ symbols! {
18651865
simd_eq,
18661866
simd_expose_provenance,
18671867
simd_extract,
1868+
simd_extract_dyn,
18681869
simd_fabs,
18691870
simd_fcos,
18701871
simd_fexp,
@@ -1885,6 +1886,7 @@ symbols! {
18851886
simd_ge,
18861887
simd_gt,
18871888
simd_insert,
1889+
simd_insert_dyn,
18881890
simd_le,
18891891
simd_lt,
18901892
simd_masked_load,

library/core/src/intrinsics/simd.rs

Lines changed: 35 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
55
/// Inserts an element into a vector, returning the updated vector.
66
///
7-
/// `T` must be a vector with element type `U`.
7+
/// `T` must be a vector with element type `U`, and `idx` must be `const`.
88
///
99
/// # Safety
1010
///
@@ -15,14 +15,46 @@ pub unsafe fn simd_insert<T, U>(_x: T, _idx: u32, _val: U) -> T;
1515

1616
/// Extracts an element from a vector.
1717
///
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 unsafe fn simd_extract<T, U>(_x: T, _idx: u32) -> U {
26+
unreachable!()
27+
}
28+
29+
/// Inserts an element into a vector, returning the updated vector.
30+
///
1831
/// `T` must be a vector with element type `U`.
1932
///
33+
/// If the index is `const`, [`simd_insert`] may emit better assembly.
34+
///
35+
/// # Safety
36+
///
37+
/// `idx` must be in-bounds of the vector.
38+
#[rustc_nounwind]
39+
#[cfg_attr(not(bootstrap), rustc_intrinsic)]
40+
pub unsafe fn simd_insert_dyn<T, U>(_x: T, _idx: u32, _val: U) -> T {
41+
unreachable!()
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+
///
2050
/// # Safety
2151
///
2252
/// `idx` must be in-bounds of the vector.
23-
#[rustc_intrinsic]
2453
#[rustc_nounwind]
25-
pub unsafe fn simd_extract<T, U>(_x: T, _idx: u32) -> U;
54+
#[cfg_attr(not(bootstrap), rustc_intrinsic)]
55+
pub unsafe fn simd_extract_dyn<T, U>(_x: T, _idx: u32) -> U {
56+
unreachable!()
57+
}
2658

2759
/// Adds two simd vectors elementwise.
2860
///
Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
//@compile-flags: -Copt-level=3 -Z merge-functions=disabled
2+
3+
#![feature(core_intrinsics, s390x_target_feature, repr_simd)]
4+
#![no_std]
5+
#![crate_type = "lib"]
6+
#![allow(non_camel_case_types)]
7+
8+
// test that `core::intrinsics::simd::{simd_extract_dyn, simd_insert_dyn}`
9+
// optimize to their dedicated instructions on platforms that support them.
10+
11+
use core::intrinsics::simd::{simd_extract, simd_extract_dyn, simd_insert, simd_insert_dyn};
12+
13+
#[repr(simd)]
14+
#[derive(Clone, Copy)]
15+
pub struct u32x16([u32; 16]);
16+
17+
#[repr(simd)]
18+
#[derive(Clone, Copy)]
19+
pub struct i8x16([i8; 16]);
20+
21+
// CHECK-LABEL: dyn_simd_extract
22+
// CHECK: extractelement <16 x i8> %x, i32 %idx
23+
// CHECK-NEXT: ret
24+
#[no_mangle]
25+
unsafe extern "C" fn dyn_simd_extract(x: i8x16, idx: u32) -> i8 {
26+
simd_extract_dyn(x, idx)
27+
}
28+
29+
// CHECK-LABEL: literal_dyn_simd_extract
30+
// CHECK: extractelement <16 x i8> %x, i64 7
31+
// CHECK-NEXT: ret
32+
#[no_mangle]
33+
unsafe extern "C" fn literal_dyn_simd_extract(x: i8x16) -> i8 {
34+
simd_extract_dyn(x, 7)
35+
}
36+
37+
// CHECK-LABEL: const_dyn_simd_extract
38+
// CHECK: extractelement <16 x i8> %x, i64 7
39+
// CHECK-NEXT: ret
40+
#[no_mangle]
41+
unsafe extern "C" fn const_dyn_simd_extract(x: i8x16) -> i8 {
42+
simd_extract_dyn(x, const { 3 + 4 })
43+
}
44+
45+
// CHECK-LABEL: const_simd_extract
46+
// CHECK: extractelement <16 x i8> %x, i64 7
47+
// CHECK-NEXT: ret
48+
#[no_mangle]
49+
unsafe extern "C" fn const_simd_extract(x: i8x16) -> i8 {
50+
simd_extract(x, const { 3 + 4 })
51+
}
52+
53+
// CHECK-LABEL: dyn_simd_insert
54+
// CHECK: insertelement <16 x i8> %x, i8 %e, i32 %idx
55+
// CHECK-NEXT: ret
56+
#[no_mangle]
57+
unsafe extern "C" fn dyn_simd_insert(x: i8x16, e: i8, idx: u32) -> i8x16 {
58+
simd_insert_dyn(x, idx, e)
59+
}
60+
61+
// CHECK-LABEL: literal_dyn_simd_insert
62+
// CHECK: insertelement <16 x i8> %x, i8 %e, i64 7
63+
// CHECK-NEXT: ret
64+
#[no_mangle]
65+
unsafe extern "C" fn literal_dyn_simd_insert(x: i8x16, e: i8) -> i8x16 {
66+
simd_insert_dyn(x, 7, e)
67+
}
68+
69+
// CHECK-LABEL: const_dyn_simd_insert
70+
// CHECK: insertelement <16 x i8> %x, i8 %e, i64 7
71+
// CHECK-NEXT: ret
72+
#[no_mangle]
73+
unsafe extern "C" fn const_dyn_simd_insert(x: i8x16, e: i8) -> i8x16 {
74+
simd_insert_dyn(x, const { 3 + 4 }, e)
75+
}
76+
77+
// CHECK-LABEL: const_simd_insert
78+
// CHECK: insertelement <16 x i8> %x, i8 %e, i64 7
79+
// CHECK-NEXT: ret
80+
#[no_mangle]
81+
unsafe extern "C" fn const_simd_insert(x: i8x16, e: i8) -> i8x16 {
82+
simd_insert(x, const { 3 + 4 }, e)
83+
}

tests/ui/simd/intrinsic/generic-elements-pass.rs

Lines changed: 38 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
//@ run-pass
22
//@ ignore-emscripten FIXME(#45351) hits an LLVM assert
33

4-
#![feature(repr_simd, intrinsics)]
4+
#![feature(repr_simd, intrinsics, core_intrinsics)]
5+
6+
use std::intrinsics::simd::{simd_extract_dyn, simd_insert_dyn};
57

68
#[repr(simd)]
79
#[derive(Copy, Clone, Debug, PartialEq)]
@@ -22,7 +24,6 @@ unsafe fn simd_insert<T, E>(x: T, idx: u32, y: E) -> T;
2224
#[rustc_intrinsic]
2325
unsafe fn simd_extract<T, E>(x: T, idx: u32) -> E;
2426

25-
2627
#[rustc_intrinsic]
2728
unsafe fn simd_shuffle<T, I, U>(x: T, y: T, idx: I) -> U;
2829

@@ -79,6 +80,41 @@ fn main() {
7980
all_eq!(simd_extract(x8, 6), 86);
8081
all_eq!(simd_extract(x8, 7), 87);
8182
}
83+
unsafe {
84+
all_eq!(simd_insert_dyn(x2, 0, 100), i32x2([100, 21]));
85+
all_eq!(simd_insert_dyn(x2, 1, 100), i32x2([20, 100]));
86+
87+
all_eq!(simd_insert_dyn(x4, 0, 100), i32x4([100, 41, 42, 43]));
88+
all_eq!(simd_insert_dyn(x4, 1, 100), i32x4([40, 100, 42, 43]));
89+
all_eq!(simd_insert_dyn(x4, 2, 100), i32x4([40, 41, 100, 43]));
90+
all_eq!(simd_insert_dyn(x4, 3, 100), i32x4([40, 41, 42, 100]));
91+
92+
all_eq!(simd_insert_dyn(x8, 0, 100), i32x8([100, 81, 82, 83, 84, 85, 86, 87]));
93+
all_eq!(simd_insert_dyn(x8, 1, 100), i32x8([80, 100, 82, 83, 84, 85, 86, 87]));
94+
all_eq!(simd_insert_dyn(x8, 2, 100), i32x8([80, 81, 100, 83, 84, 85, 86, 87]));
95+
all_eq!(simd_insert_dyn(x8, 3, 100), i32x8([80, 81, 82, 100, 84, 85, 86, 87]));
96+
all_eq!(simd_insert_dyn(x8, 4, 100), i32x8([80, 81, 82, 83, 100, 85, 86, 87]));
97+
all_eq!(simd_insert_dyn(x8, 5, 100), i32x8([80, 81, 82, 83, 84, 100, 86, 87]));
98+
all_eq!(simd_insert_dyn(x8, 6, 100), i32x8([80, 81, 82, 83, 84, 85, 100, 87]));
99+
all_eq!(simd_insert_dyn(x8, 7, 100), i32x8([80, 81, 82, 83, 84, 85, 86, 100]));
100+
101+
all_eq!(simd_extract_dyn(x2, 0), 20);
102+
all_eq!(simd_extract_dyn(x2, 1), 21);
103+
104+
all_eq!(simd_extract_dyn(x4, 0), 40);
105+
all_eq!(simd_extract_dyn(x4, 1), 41);
106+
all_eq!(simd_extract_dyn(x4, 2), 42);
107+
all_eq!(simd_extract_dyn(x4, 3), 43);
108+
109+
all_eq!(simd_extract_dyn(x8, 0), 80);
110+
all_eq!(simd_extract_dyn(x8, 1), 81);
111+
all_eq!(simd_extract_dyn(x8, 2), 82);
112+
all_eq!(simd_extract_dyn(x8, 3), 83);
113+
all_eq!(simd_extract_dyn(x8, 4), 84);
114+
all_eq!(simd_extract_dyn(x8, 5), 85);
115+
all_eq!(simd_extract_dyn(x8, 6), 86);
116+
all_eq!(simd_extract_dyn(x8, 7), 87);
117+
}
82118

83119
let y2 = i32x2([120, 121]);
84120
let y4 = i32x4([140, 141, 142, 143]);

0 commit comments

Comments
 (0)