Skip to content

Commit 1596d1b

Browse files
committed
initial commit
0 parents  commit 1596d1b

File tree

7 files changed

+234
-0
lines changed

7 files changed

+234
-0
lines changed

Cargo.toml

+6
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
[package]
2+
name = "spmd"
3+
version = "0.1.0"
4+
authors = ["gnzlbg <[email protected]>"]
5+
6+
[dependencies]

readme.md

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
# `Simd<[T; N]>` - alternative fully-conforming implementation of `std::simd`
2+
3+
> WIP

src/api/minimal_iuf.rs

+87
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
//! Minimal API of signed integer, unsigned integer, and floating-point vectors.
2+
3+
macro_rules! impl_minimal_iuf {
4+
([$elem_ty:ident; $elem_count:expr]: $tuple_id:ident |
5+
$($elem_name:ident),+ |
6+
$(#[$doc:meta])*) => {
7+
8+
$(#[$doc])*
9+
pub type $tuple_id = Simd<[$elem_ty; $elem_count]>;
10+
11+
impl Simd<[$elem_ty; $elem_count]> {
12+
/// Creates a new instance with each vector elements initialized
13+
/// with the provided values.
14+
#[inline]
15+
pub const fn new($($elem_name: $elem_ty),*) -> Self {
16+
Simd(sealed::$tuple_id($($elem_name),*))
17+
}
18+
19+
/// Returns the number of vector lanes.
20+
#[inline]
21+
pub const fn lanes() -> usize {
22+
$elem_count
23+
}
24+
25+
/// Constructs a new instance with each element initialized to
26+
/// `value`.
27+
#[inline]
28+
pub const fn splat(value: $elem_ty) -> Self {
29+
Simd(sealed::$tuple_id($({
30+
#[allow(non_camel_case_types, dead_code)]
31+
struct $elem_name;
32+
value
33+
}),*))
34+
}
35+
36+
/// Extracts the value at `index`.
37+
///
38+
/// # Panics
39+
///
40+
/// If `index >= Self::lanes()`.
41+
#[inline]
42+
pub fn extract(self, index: usize) -> $elem_ty {
43+
assert!(index < $elem_count);
44+
unsafe { self.extract_unchecked(index) }
45+
}
46+
47+
/// Extracts the value at `index`.
48+
///
49+
/// # Precondition
50+
///
51+
/// If `index >= Self::lanes()` the behavior is undefined.
52+
#[inline]
53+
pub unsafe fn extract_unchecked(self, index: usize) -> $elem_ty {
54+
use llvm::simd_extract;
55+
simd_extract(self.0, index as u32)
56+
}
57+
58+
/// Returns a new vector where the value at `index` is replaced by `new_value`.
59+
///
60+
/// # Panics
61+
///
62+
/// If `index >= Self::lanes()`.
63+
#[inline]
64+
#[must_use = "replace does not modify the original value - it returns a new vector with the value at `index` replaced by `new_value`d"]
65+
pub fn replace(self, index: usize, new_value: $elem_ty) -> Self {
66+
assert!(index < $elem_count);
67+
unsafe { self.replace_unchecked(index, new_value) }
68+
}
69+
70+
/// Returns a new vector where the value at `index` is replaced by `new_value`.
71+
///
72+
/// # Precondition
73+
///
74+
/// If `index >= Self::lanes()` the behavior is undefined.
75+
#[inline]
76+
#[must_use = "replace_unchecked does not modify the original value - it returns a new vector with the value at `index` replaced by `new_value`d"]
77+
pub unsafe fn replace_unchecked(
78+
self,
79+
index: usize,
80+
new_value: $elem_ty,
81+
) -> Self {
82+
use llvm::simd_insert;
83+
Simd(simd_insert(self.0, index as u32, new_value))
84+
}
85+
}
86+
}
87+
}

src/api/mod.rs

+26
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
#[macro_use]
2+
mod minimal_iuf;
3+
4+
macro_rules! impl_i {
5+
([$elem_ty:ident; $elem_count:expr]: $tuple_id:ident
6+
| $($elem_ids:ident),* | $(#[$doc:meta])*) => {
7+
impl_minimal_iuf!([$elem_ty; $elem_count]: $tuple_id
8+
| $($elem_ids),* | $(#[$doc])*);
9+
}
10+
}
11+
12+
macro_rules! impl_u {
13+
([$elem_ty:ident; $elem_count:expr]: $tuple_id:ident
14+
| $($elem_ids:ident),* | $(#[$doc:meta])*) => {
15+
impl_minimal_iuf!([$elem_ty; $elem_count]: $tuple_id
16+
| $($elem_ids),* | $(#[$doc])*);
17+
}
18+
}
19+
20+
macro_rules! impl_f {
21+
([$elem_ty:ident; $elem_count:expr]: $tuple_id:ident
22+
| $($elem_ids:ident),* | $(#[$doc:meta])*) => {
23+
impl_minimal_iuf!([$elem_ty; $elem_count]: $tuple_id
24+
| $($elem_ids),* | $(#[$doc])*);
25+
}
26+
}

src/lib.rs

+31
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
//! SPMD - Single Program Multiple Data
2+
#![feature(repr_simd, const_fn, platform_intrinsics)]
3+
#![allow(non_camel_case_types)]
4+
#![allow(dead_code)] // FIXME: remove this allow
5+
6+
mod llvm;
7+
mod sealed;
8+
#[macro_use]
9+
mod api;
10+
11+
/// SIMD vector type
12+
///
13+
/// # Examples
14+
///
15+
/// ```
16+
/// # use spmd::Simd;
17+
/// let v = Simd::<[i32; 4]>::new(0, 1, 2, 3);
18+
/// assert_eq!(v.extract(2), 2);
19+
/// ```
20+
#[derive(Copy, Clone)]
21+
pub struct Simd<A: sealed::SimdArray>(<A as sealed::SimdArray>::Tuple);
22+
23+
impl_i!([i32; 4]: i32x4 | x0, x1, x2, x3 |
24+
/// A 128-bit vector with 4 `i32` lanes.
25+
);
26+
impl_u!([u32; 4]: u32x4 | x0, x1, x2, x3 |
27+
/// A 128-bit vector with 4 `u32` lanes.
28+
);
29+
impl_f!([f32; 4]: f32x4 | x0, x1, x2, x3 |
30+
/// A 128-bit vector with 4 `f32` lanes.
31+
);

src/llvm.rs

+55
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
//! LLVM's simd platform intrinsics
2+
3+
extern "platform-intrinsic" {
4+
pub fn simd_eq<T, U>(x: T, y: T) -> U;
5+
pub fn simd_ne<T, U>(x: T, y: T) -> U;
6+
pub fn simd_lt<T, U>(x: T, y: T) -> U;
7+
pub fn simd_le<T, U>(x: T, y: T) -> U;
8+
pub fn simd_gt<T, U>(x: T, y: T) -> U;
9+
pub fn simd_ge<T, U>(x: T, y: T) -> U;
10+
11+
pub fn simd_shuffle2<T, U>(x: T, y: T, idx: [u32; 2]) -> U;
12+
pub fn simd_shuffle4<T, U>(x: T, y: T, idx: [u32; 4]) -> U;
13+
pub fn simd_shuffle8<T, U>(x: T, y: T, idx: [u32; 8]) -> U;
14+
pub fn simd_shuffle16<T, U>(x: T, y: T, idx: [u32; 16]) -> U;
15+
pub fn simd_shuffle32<T, U>(x: T, y: T, idx: [u32; 32]) -> U;
16+
17+
pub fn simd_insert<T, U>(x: T, idx: u32, val: U) -> T;
18+
pub fn simd_extract<T, U>(x: T, idx: u32) -> U;
19+
20+
pub fn simd_cast<T, U>(x: T) -> U;
21+
22+
pub fn simd_add<T>(x: T, y: T) -> T;
23+
pub fn simd_sub<T>(x: T, y: T) -> T;
24+
pub fn simd_mul<T>(x: T, y: T) -> T;
25+
pub fn simd_div<T>(x: T, y: T) -> T;
26+
pub fn simd_rem<T>(x: T, y: T) -> T;
27+
pub fn simd_shl<T>(x: T, y: T) -> T;
28+
pub fn simd_shr<T>(x: T, y: T) -> T;
29+
pub fn simd_and<T>(x: T, y: T) -> T;
30+
pub fn simd_or<T>(x: T, y: T) -> T;
31+
pub fn simd_xor<T>(x: T, y: T) -> T;
32+
33+
pub fn simd_reduce_add_unordered<T, U>(x: T) -> U;
34+
pub fn simd_reduce_mul_unordered<T, U>(x: T) -> U;
35+
pub fn simd_reduce_add_ordered<T, U>(x: T, acc: U) -> U;
36+
pub fn simd_reduce_mul_ordered<T, U>(x: T, acc: U) -> U;
37+
pub fn simd_reduce_min<T, U>(x: T) -> U;
38+
pub fn simd_reduce_max<T, U>(x: T) -> U;
39+
pub fn simd_reduce_min_nanless<T, U>(x: T) -> U;
40+
pub fn simd_reduce_max_nanless<T, U>(x: T) -> U;
41+
pub fn simd_reduce_and<T, U>(x: T) -> U;
42+
pub fn simd_reduce_or<T, U>(x: T) -> U;
43+
pub fn simd_reduce_xor<T, U>(x: T) -> U;
44+
pub fn simd_reduce_all<T>(x: T) -> bool;
45+
pub fn simd_reduce_any<T>(x: T) -> bool;
46+
47+
pub fn simd_select<M, T>(m: M, a: T, b: T) -> T;
48+
49+
pub fn simd_fmin<T>(a: T, b: T) -> T;
50+
// FIXME: https://github.com/rust-lang-nursery/stdsimd/issues/416
51+
// pub fn simd_fmax<T>(a: T, b: T) -> T;
52+
53+
pub fn simd_fsqrt<T>(a: T) -> T;
54+
pub fn simd_fma<T>(a: T, b: T, c: T) -> T;
55+
}

src/sealed.rs

+26
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
//! Sealed traits
2+
3+
/// Trait implemented by arrays that can be SIMD types
4+
pub trait SimdArray {
5+
type Tuple: Copy + Clone;
6+
type T;
7+
const N: usize;
8+
}
9+
10+
macro_rules! impl_simd_array {
11+
([$elem_ty:ident; $elem_cnt:expr]: $tuple_id:ident | $($elem_tys:ident),*) => {
12+
#[derive(Copy, Clone)]
13+
#[repr(simd)]
14+
pub struct $tuple_id($(pub $elem_tys),*);
15+
16+
impl SimdArray for [$elem_ty; $elem_cnt] {
17+
type Tuple = $tuple_id;
18+
type T = $elem_ty;
19+
const N: usize = $elem_cnt;
20+
}
21+
}
22+
}
23+
24+
impl_simd_array!([i32; 4]: i32x4 | i32, i32, i32, i32);
25+
impl_simd_array!([u32; 4]: u32x4 | u32, u32, u32, u32);
26+
impl_simd_array!([f32; 4]: f32x4 | f32, f32, f32, f32);

0 commit comments

Comments
 (0)