Skip to content

Commit

Permalink
Shim some of the old std::simd functionality.
Browse files Browse the repository at this point in the history
Overload the operators using the traits so that things mostly keep
working during the deprecation period.
  • Loading branch information
huonw committed Aug 17, 2015
1 parent 62ba85b commit d792925
Show file tree
Hide file tree
Showing 3 changed files with 56 additions and 16 deletions.
2 changes: 1 addition & 1 deletion src/libcore/lib.rs
Expand Up @@ -79,7 +79,7 @@
#![feature(reflect)]
#![feature(rustc_attrs)]
#![cfg_attr(stage0, feature(simd))]
#![cfg_attr(not(stage0), feature(repr_simd))]
#![cfg_attr(not(stage0), feature(repr_simd, platform_intrinsics))]
#![feature(staged_api)]
#![feature(unboxed_closures)]

Expand Down
68 changes: 54 additions & 14 deletions src/libcore/simd.rs
Expand Up @@ -10,25 +10,12 @@

//! SIMD vectors.
//!
//! These types can be used for accessing basic SIMD operations. Each of them
//! implements the standard arithmetic operator traits (Add, Sub, Mul, Div,
//! Rem, Shl, Shr) through compiler magic, rather than explicitly. Currently
//! These types can be used for accessing basic SIMD operations. Currently
//! comparison operators are not implemented. To use SSE3+, you must enable
//! the features, like `-C target-feature=sse3,sse4.1,sse4.2`, or a more
//! specific `target-cpu`. No other SIMD intrinsics or high-level wrappers are
//! provided beyond this module.
//!
//! ```rust
//! #![feature(core_simd)]
//!
//! fn main() {
//! use std::simd::f32x4;
//! let a = f32x4(40.0, 41.0, 42.0, 43.0);
//! let b = f32x4(1.0, 1.1, 3.4, 9.8);
//! println!("{:?}", a + b);
//! }
//! ```
//!
//! # Stability Note
//!
//! These are all experimental. The interface may change entirely, without
Expand All @@ -44,6 +31,30 @@
#![allow(missing_docs)]
#![allow(deprecated)]

use ops::{Add, Sub, Mul, Div, Shl, Shr, BitAnd, BitOr, BitXor};

// FIXME(stage0): the contents of macro can be inlined.
// ABIs are verified as valid as soon as they are parsed, i.e. before
// `cfg` stripping. The `platform-intrinsic` ABI is new, so stage0
// doesn't know about it, but it still errors out when it hits it
// (despite this being in a `cfg(not(stage0))` module).
macro_rules! argh {
() => {
extern "platform-intrinsic" {
fn simd_add<T>(x: T, y: T) -> T;
fn simd_sub<T>(x: T, y: T) -> T;
fn simd_mul<T>(x: T, y: T) -> T;
fn simd_div<T>(x: T, y: T) -> T;
fn simd_shl<T>(x: T, y: T) -> T;
fn simd_shr<T>(x: T, y: T) -> T;
fn simd_and<T>(x: T, y: T) -> T;
fn simd_or<T>(x: T, y: T) -> T;
fn simd_xor<T>(x: T, y: T) -> T;
}
}
}
argh!();

#[repr(simd)]
#[derive(Copy, Clone, Debug)]
#[repr(C)]
Expand Down Expand Up @@ -101,3 +112,32 @@ pub struct f32x4(pub f32, pub f32, pub f32, pub f32);
#[derive(Copy, Clone, Debug)]
#[repr(C)]
pub struct f64x2(pub f64, pub f64);

macro_rules! impl_traits {
($($trayt: ident, $method: ident, $func: ident: $($ty: ty),*;)*) => {
$($(
impl $trayt<$ty> for $ty {
type Output = Self;
fn $method(self, other: Self) -> Self {
unsafe {
$func(self, other)
}
}
}
)*)*
}
}

impl_traits! {
Add, add, simd_add: u8x16, u16x8, u32x4, u64x2, i8x16, i16x8, i32x4, i64x2, f32x4, f64x2;
Sub, sub, simd_sub: u8x16, u16x8, u32x4, u64x2, i8x16, i16x8, i32x4, i64x2, f32x4, f64x2;
Mul, mul, simd_mul: u8x16, u16x8, u32x4, u64x2, i8x16, i16x8, i32x4, i64x2, f32x4, f64x2;

Div, div, simd_div: f32x4, f64x2;

Shl, shl, simd_shl: u8x16, u16x8, u32x4, u64x2, i8x16, i16x8, i32x4, i64x2;
Shr, shr, simd_shr: u8x16, u16x8, u32x4, u64x2, i8x16, i16x8, i32x4, i64x2;
BitAnd, bitand, simd_and: u8x16, u16x8, u32x4, u64x2, i8x16, i16x8, i32x4, i64x2;
BitOr, bitor, simd_or: u8x16, u16x8, u32x4, u64x2, i8x16, i16x8, i32x4, i64x2;
BitXor, bitxor, simd_xor: u8x16, u16x8, u32x4, u64x2, i8x16, i16x8, i32x4, i64x2;
}
2 changes: 1 addition & 1 deletion src/test/bench/shootout-spectralnorm.rs
Expand Up @@ -91,7 +91,7 @@ fn mult<F>(v: &[f64], out: &mut [f64], start: usize, a: F)
for (j, chunk) in v.chunks(2).enumerate().map(|(j, s)| (2 * j, s)) {
let top = f64x2(chunk[0], chunk[1]);
let bot = f64x2(a(i, j), a(i, j + 1));
sum += top / bot;
sum = sum + top / bot;
}
let f64x2(a, b) = sum;
*slot = a + b;
Expand Down

0 comments on commit d792925

Please sign in to comment.