Skip to content

Commit 801d955

Browse files
authored
Rollup merge of #95961 - RalfJung:gather-scatter, r=workingjubilee
implement SIMD gather/scatter via vector getelementptr Fixes rust-lang/portable-simd#271 However, I don't *really* know what I am doing here... Cc ``@workingjubilee`` ``@calebzulawski`` I didn't do anything for cranelift -- ``@bjorn3`` not sure if it's okay for that backend to temporarily break. I'm happy to cherry-pick a patch that adds cranelift support. :)
2 parents cca3b87 + eb905c0 commit 801d955

File tree

6 files changed

+63
-0
lines changed

6 files changed

+63
-0
lines changed

compiler/rustc_codegen_llvm/src/intrinsic.rs

+21
Original file line numberDiff line numberDiff line change
@@ -1839,6 +1839,27 @@ unsupported {} from `{}` with element `{}` of size `{}` to `{}`"#,
18391839
simd_neg: Int => neg, Float => fneg;
18401840
}
18411841

1842+
if name == sym::simd_arith_offset {
1843+
// This also checks that the first operand is a ptr type.
1844+
let pointee = in_elem.builtin_deref(true).unwrap_or_else(|| {
1845+
span_bug!(span, "must be called with a vector of pointer types as first argument")
1846+
});
1847+
let layout = bx.layout_of(pointee.ty);
1848+
let ptrs = args[0].immediate();
1849+
// The second argument must be a ptr-sized integer.
1850+
// (We don't care about the signedness, this is wrapping anyway.)
1851+
let (_offsets_len, offsets_elem) = arg_tys[1].simd_size_and_type(bx.tcx());
1852+
if !matches!(offsets_elem.kind(), ty::Int(ty::IntTy::Isize) | ty::Uint(ty::UintTy::Usize)) {
1853+
span_bug!(
1854+
span,
1855+
"must be called with a vector of pointer-sized integers as second argument"
1856+
);
1857+
}
1858+
let offsets = args[1].immediate();
1859+
1860+
return Ok(bx.gep(bx.backend_type(layout), ptrs, &[offsets]));
1861+
}
1862+
18421863
if name == sym::simd_saturating_add || name == sym::simd_saturating_sub {
18431864
let lhs = args[0].immediate();
18441865
let rhs = args[1].immediate();

compiler/rustc_span/src/symbol.rs

+1
Original file line numberDiff line numberDiff line change
@@ -1245,6 +1245,7 @@ symbols! {
12451245
simd,
12461246
simd_add,
12471247
simd_and,
1248+
simd_arith_offset,
12481249
simd_as,
12491250
simd_bitmask,
12501251
simd_cast,

compiler/rustc_typeck/src/check/intrinsic.rs

+1
Original file line numberDiff line numberDiff line change
@@ -437,6 +437,7 @@ pub fn check_platform_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem<'_>)
437437
| sym::simd_fpow
438438
| sym::simd_saturating_add
439439
| sym::simd_saturating_sub => (1, vec![param(0), param(0)], param(0)),
440+
sym::simd_arith_offset => (2, vec![param(0), param(1)], param(0)),
440441
sym::simd_neg
441442
| sym::simd_fsqrt
442443
| sym::simd_fsin

library/portable-simd/crates/core_simd/src/intrinsics.rs

+4
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,10 @@ extern "platform-intrinsic" {
6161
/// xor
6262
pub(crate) fn simd_xor<T>(x: T, y: T) -> T;
6363

64+
/// getelementptr (without inbounds)
65+
#[cfg(not(bootstrap))]
66+
pub(crate) fn simd_arith_offset<T, U>(ptrs: T, offsets: U) -> T;
67+
6468
/// fptoui/fptosi/uitofp/sitofp
6569
/// casting floats to integers is truncating, so it is safe to convert values like e.g. 1.5
6670
/// but the truncated value must fit in the target type or the result is poison.

library/portable-simd/crates/core_simd/src/vector/ptr.rs

+11
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
//! Private implementation details of public gather/scatter APIs.
2+
#[cfg(not(bootstrap))]
3+
use crate::simd::intrinsics;
24
use crate::simd::{LaneCount, Simd, SupportedLaneCount};
5+
#[cfg(bootstrap)]
36
use core::mem;
47

58
/// A vector of *const T.
@@ -21,12 +24,16 @@ where
2124
#[inline]
2225
#[must_use]
2326
pub fn wrapping_add(self, addend: Simd<usize, LANES>) -> Self {
27+
#[cfg(bootstrap)]
2428
// Safety: converting pointers to usize and vice-versa is safe
2529
// (even if using that pointer is not)
2630
unsafe {
2731
let x: Simd<usize, LANES> = mem::transmute_copy(&self);
2832
mem::transmute_copy(&{ x + (addend * Simd::splat(mem::size_of::<T>())) })
2933
}
34+
#[cfg(not(bootstrap))]
35+
// Safety: this intrinsic doesn't have a precondition
36+
unsafe { intrinsics::simd_arith_offset(self, addend) }
3037
}
3138
}
3239

@@ -49,11 +56,15 @@ where
4956
#[inline]
5057
#[must_use]
5158
pub fn wrapping_add(self, addend: Simd<usize, LANES>) -> Self {
59+
#[cfg(bootstrap)]
5260
// Safety: converting pointers to usize and vice-versa is safe
5361
// (even if using that pointer is not)
5462
unsafe {
5563
let x: Simd<usize, LANES> = mem::transmute_copy(&self);
5664
mem::transmute_copy(&{ x + (addend * Simd::splat(mem::size_of::<T>())) })
5765
}
66+
#[cfg(not(bootstrap))]
67+
// Safety: this intrinsic doesn't have a precondition
68+
unsafe { intrinsics::simd_arith_offset(self, addend) }
5869
}
5970
}

src/test/codegen/simd_arith_offset.rs

+25
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
// compile-flags: -C no-prepopulate-passes
2+
//
3+
4+
#![crate_type = "lib"]
5+
#![feature(repr_simd, platform_intrinsics)]
6+
7+
extern "platform-intrinsic" {
8+
pub(crate) fn simd_arith_offset<T, U>(ptrs: T, offsets: U) -> T;
9+
}
10+
11+
/// A vector of *const T.
12+
#[derive(Debug, Copy, Clone)]
13+
#[repr(simd)]
14+
pub struct SimdConstPtr<T, const LANES: usize>([*const T; LANES]);
15+
16+
#[derive(Debug, Copy, Clone)]
17+
#[repr(simd)]
18+
pub struct Simd<T, const LANES: usize>([T; LANES]);
19+
20+
// CHECK-LABEL: smoke
21+
#[no_mangle]
22+
pub fn smoke(ptrs: SimdConstPtr<u8, 8>, offsets: Simd<usize, 8>) -> SimdConstPtr<u8, 8> {
23+
// CHECK: getelementptr i8, <8 x i8*> %_3, <8 x i64> %_4
24+
unsafe { simd_arith_offset(ptrs, offsets) }
25+
}

0 commit comments

Comments
 (0)