Skip to content

Commit

Permalink
Auto merge of #27169 - huonw:simd, r=alexcrichton
Browse files Browse the repository at this point in the history
This implements rust-lang/rfcs#1199 (except for doing all the platform intrinsics).

Things remaining for SIMD (not necessarily in this PR):

- [x] I (@huonw) am signed up to ensure the compiler matches the RFC, when it lands
- [x] the platform specific intrinsics aren't properly type checked at the moment (LLVM will throw a "random" assertion)
- [ ] there's a lot of useful intrinsics that are missing, including whole platforms (mips, powerpc)
- [ ] the target-feature `cfg` detection/adding is not so great at the moment
- [x] I think the platform specific intrinsics should go in their own `extern` ABI (i.e. not `"rust-intrinsic"`)

(I'm adjusting the RFC to reflect the latter.)

I think it would be very nice for this to land without requiring the RFC to land first, because of the first point, and because this is the only way for any further work to happen/be experimented with, without requiring people to build/install/multirust a compiler from a custom branch.

r? @alexcrichton
  • Loading branch information
bors committed Aug 17, 2015
2 parents 6d99272 + 02e9734 commit e35fd74
Show file tree
Hide file tree
Showing 77 changed files with 3,032 additions and 1,031 deletions.
7 changes: 4 additions & 3 deletions mk/crates.mk
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ TARGET_CRATES := libc std flate arena term \
alloc_system
RUSTC_CRATES := rustc rustc_typeck rustc_borrowck rustc_resolve rustc_driver \
rustc_trans rustc_back rustc_llvm rustc_privacy rustc_lint \
rustc_data_structures
rustc_data_structures rustc_platform_intrinsics
HOST_CRATES := syntax $(RUSTC_CRATES) rustdoc fmt_macros
TOOLS := compiletest rustdoc rustc rustbook error-index-generator

Expand All @@ -74,15 +74,16 @@ DEPS_rustc_driver := arena flate getopts graphviz libc rustc rustc_back rustc_bo
rustc_trans rustc_privacy rustc_lint

DEPS_rustc_trans := arena flate getopts graphviz libc rustc rustc_back \
log syntax serialize rustc_llvm
DEPS_rustc_typeck := rustc syntax
log syntax serialize rustc_llvm rustc_platform_intrinsics
DEPS_rustc_typeck := rustc syntax rustc_platform_intrinsics
DEPS_rustc_borrowck := rustc log graphviz syntax
DEPS_rustc_resolve := rustc log syntax
DEPS_rustc_privacy := rustc log syntax
DEPS_rustc_lint := rustc log syntax
DEPS_rustc := syntax flate arena serialize getopts rbml \
log graphviz rustc_llvm rustc_back rustc_data_structures
DEPS_rustc_llvm := native:rustllvm libc std rustc_bitflags
DEPS_rustc_platform_intrinsics := rustc rustc_llvm
DEPS_rustc_back := std syntax rustc_llvm flate log libc
DEPS_rustc_data_structures := std log serialize
DEPS_rustdoc := rustc rustc_driver native:hoedown serialize getopts \
Expand Down
9 changes: 8 additions & 1 deletion src/libcore/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,8 @@
#![feature(optin_builtin_traits)]
#![feature(reflect)]
#![feature(rustc_attrs)]
#![feature(simd)]
#![cfg_attr(stage0, feature(simd))]
#![cfg_attr(not(stage0), feature(repr_simd, platform_intrinsics))]
#![feature(staged_api)]
#![feature(unboxed_closures)]

Expand Down Expand Up @@ -150,7 +151,13 @@ pub mod iter;
pub mod option;
pub mod raw;
pub mod result;

#[cfg(stage0)]
#[path = "simd_old.rs"]
pub mod simd;
#[cfg(not(stage0))]
pub mod simd;

pub mod slice;
pub mod str;
pub mod hash;
Expand Down
91 changes: 67 additions & 24 deletions src/libcore/simd.rs
Original file line number Diff line number Diff line change
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 @@ -37,64 +24,120 @@
#![unstable(feature = "core_simd",
reason = "needs an RFC to flesh out the design",
issue = "27731")]
#![deprecated(since = "1.3.0",
reason = "use the external `simd` crate instead")]

#![allow(non_camel_case_types)]
#![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!();

#[simd]
#[repr(simd)]
#[derive(Copy, Clone, Debug)]
#[repr(C)]
pub struct i8x16(pub i8, pub i8, pub i8, pub i8,
pub i8, pub i8, pub i8, pub i8,
pub i8, pub i8, pub i8, pub i8,
pub i8, pub i8, pub i8, pub i8);

#[simd]
#[repr(simd)]
#[derive(Copy, Clone, Debug)]
#[repr(C)]
pub struct i16x8(pub i16, pub i16, pub i16, pub i16,
pub i16, pub i16, pub i16, pub i16);

#[simd]
#[repr(simd)]
#[derive(Copy, Clone, Debug)]
#[repr(C)]
pub struct i32x4(pub i32, pub i32, pub i32, pub i32);

#[simd]
#[repr(simd)]
#[derive(Copy, Clone, Debug)]
#[repr(C)]
pub struct i64x2(pub i64, pub i64);

#[simd]
#[repr(simd)]
#[derive(Copy, Clone, Debug)]
#[repr(C)]
pub struct u8x16(pub u8, pub u8, pub u8, pub u8,
pub u8, pub u8, pub u8, pub u8,
pub u8, pub u8, pub u8, pub u8,
pub u8, pub u8, pub u8, pub u8);

#[simd]
#[repr(simd)]
#[derive(Copy, Clone, Debug)]
#[repr(C)]
pub struct u16x8(pub u16, pub u16, pub u16, pub u16,
pub u16, pub u16, pub u16, pub u16);

#[simd]
#[repr(simd)]
#[derive(Copy, Clone, Debug)]
#[repr(C)]
pub struct u32x4(pub u32, pub u32, pub u32, pub u32);

#[simd]
#[repr(simd)]
#[derive(Copy, Clone, Debug)]
#[repr(C)]
pub struct u64x2(pub u64, pub u64);

#[simd]
#[repr(simd)]
#[derive(Copy, Clone, Debug)]
#[repr(C)]
pub struct f32x4(pub f32, pub f32, pub f32, pub f32);

#[simd]
#[repr(simd)]
#[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;
}
98 changes: 98 additions & 0 deletions src/libcore/simd_old.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! 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
//! 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
//! warning.

#![unstable(feature = "core_simd",
reason = "needs an RFC to flesh out the design")]

#![allow(non_camel_case_types)]
#![allow(missing_docs)]

#[simd]
#[derive(Copy, Clone, Debug)]
#[repr(C)]
pub struct i8x16(pub i8, pub i8, pub i8, pub i8,
pub i8, pub i8, pub i8, pub i8,
pub i8, pub i8, pub i8, pub i8,
pub i8, pub i8, pub i8, pub i8);

#[simd]
#[derive(Copy, Clone, Debug)]
#[repr(C)]
pub struct i16x8(pub i16, pub i16, pub i16, pub i16,
pub i16, pub i16, pub i16, pub i16);

#[simd]
#[derive(Copy, Clone, Debug)]
#[repr(C)]
pub struct i32x4(pub i32, pub i32, pub i32, pub i32);

#[simd]
#[derive(Copy, Clone, Debug)]
#[repr(C)]
pub struct i64x2(pub i64, pub i64);

#[simd]
#[derive(Copy, Clone, Debug)]
#[repr(C)]
pub struct u8x16(pub u8, pub u8, pub u8, pub u8,
pub u8, pub u8, pub u8, pub u8,
pub u8, pub u8, pub u8, pub u8,
pub u8, pub u8, pub u8, pub u8);

#[simd]
#[derive(Copy, Clone, Debug)]
#[repr(C)]
pub struct u16x8(pub u16, pub u16, pub u16, pub u16,
pub u16, pub u16, pub u16, pub u16);

#[simd]
#[derive(Copy, Clone, Debug)]
#[repr(C)]
pub struct u32x4(pub u32, pub u32, pub u32, pub u32);

#[simd]
#[derive(Copy, Clone, Debug)]
#[repr(C)]
pub struct u64x2(pub u64, pub u64);

#[simd]
#[derive(Copy, Clone, Debug)]
#[repr(C)]
pub struct f32x4(pub f32, pub f32, pub f32, pub f32);

#[simd]
#[derive(Copy, Clone, Debug)]
#[repr(C)]
pub struct f64x2(pub f64, pub f64);
2 changes: 1 addition & 1 deletion src/librustc/metadata/creader.rs
Original file line number Diff line number Diff line change
Expand Up @@ -704,7 +704,7 @@ impl<'a, 'b> LocalCrateReader<'a, 'b> {
}

fn process_foreign_mod(&mut self, i: &ast::Item, fm: &ast::ForeignMod) {
if fm.abi == abi::Rust || fm.abi == abi::RustIntrinsic {
if fm.abi == abi::Rust || fm.abi == abi::RustIntrinsic || fm.abi == abi::PlatformIntrinsic {
return;
}

Expand Down
2 changes: 1 addition & 1 deletion src/librustc/metadata/encoder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1501,7 +1501,7 @@ fn encode_info_for_foreign_item(ecx: &EncodeContext,
encode_family(rbml_w, FN_FAMILY);
encode_bounds_and_type_for_item(rbml_w, ecx, nitem.id);
encode_name(rbml_w, nitem.ident.name);
if abi == abi::RustIntrinsic {
if abi == abi::RustIntrinsic || abi == abi::PlatformIntrinsic {
encode_inlined_item(ecx, rbml_w, InlinedItemRef::Foreign(nitem));
}
encode_attributes(rbml_w, &*nitem.attrs);
Expand Down
5 changes: 3 additions & 2 deletions src/librustc/middle/ty.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3312,10 +3312,10 @@ impl<'tcx, 'container> AdtDefData<'tcx, 'container> {
variants: Vec<VariantDefData<'tcx, 'container>>) -> Self {
let mut flags = AdtFlags::NO_ADT_FLAGS;
let attrs = tcx.get_attrs(did);
if attrs.iter().any(|item| item.check_name("fundamental")) {
if attr::contains_name(&attrs, "fundamental") {
flags = flags | AdtFlags::IS_FUNDAMENTAL;
}
if attrs.iter().any(|item| item.check_name("simd")) {
if tcx.lookup_simd(did) {
flags = flags | AdtFlags::IS_SIMD;
}
if Some(did) == tcx.lang_items.phantom_data() {
Expand Down Expand Up @@ -6116,6 +6116,7 @@ impl<'tcx> ctxt<'tcx> {
/// Determine whether an item is annotated with `#[simd]`
pub fn lookup_simd(&self, did: DefId) -> bool {
self.has_attr(did, "simd")
|| self.lookup_repr_hints(did).contains(&attr::ReprSimd)
}

/// Obtain the representation annotation for a struct definition.
Expand Down
19 changes: 16 additions & 3 deletions src/librustc_driver/driver.rs
Original file line number Diff line number Diff line change
Expand Up @@ -406,8 +406,10 @@ pub fn phase_2_configure_and_expand(sess: &Session,
//
// baz! should not use this definition unless foo is enabled.

krate = time(time_passes, "configuration 1", move ||
syntax::config::strip_unconfigured_items(sess.diagnostic(), krate));
let mut feature_gated_cfgs = vec![];
krate = time(time_passes, "configuration 1", ||
syntax::config::strip_unconfigured_items(sess.diagnostic(), krate,
&mut feature_gated_cfgs));

*sess.crate_types.borrow_mut() =
collect_crate_types(sess, &krate.attrs);
Expand Down Expand Up @@ -511,6 +513,7 @@ pub fn phase_2_configure_and_expand(sess: &Session,
cfg,
macros,
syntax_exts,
&mut feature_gated_cfgs,
krate);
if cfg!(windows) {
env::set_var("PATH", &_old_path);
Expand All @@ -536,7 +539,17 @@ pub fn phase_2_configure_and_expand(sess: &Session,

// strip again, in case expansion added anything with a #[cfg].
krate = time(time_passes, "configuration 2", ||
syntax::config::strip_unconfigured_items(sess.diagnostic(), krate));
syntax::config::strip_unconfigured_items(sess.diagnostic(), krate,
&mut feature_gated_cfgs));

time(time_passes, "gated configuration checking", || {
let features = sess.features.borrow();
feature_gated_cfgs.sort();
feature_gated_cfgs.dedup();
for cfg in &feature_gated_cfgs {
cfg.check_and_emit(sess.diagnostic(), &features);
}
});

krate = time(time_passes, "maybe building test harness", ||
syntax::test::modify_for_testing(&sess.parse_sess,
Expand Down
Loading

0 comments on commit e35fd74

Please sign in to comment.