Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

SIMD groundwork part 1 #27169

Merged
merged 40 commits into from
Aug 18, 2015
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
40 commits
Select commit Hold shift + click to select a range
c8b6d5b
Implement `repr(simd)` as an alias for `#[simd]`.
huonw Jul 13, 2015
c66554c
switch core::simd to repr(simd) and deprecate it.
huonw Jul 13, 2015
e364f0e
feature gate `cfg(target_feature)`.
huonw Jul 14, 2015
4f44258
Add some SIMD target_feature cfg's when appropriate.
huonw Jul 14, 2015
1bfbde6
Add comparison and shuffle SIMD intrinsics.
huonw Jul 16, 2015
9af385b
Add rustc_platform_intrinsics & some arm/x86 intrs.
huonw Jul 16, 2015
78eead6
Implement the simd_insert/simd_extract intrinsics.
huonw Jul 20, 2015
f1d3b02
Add x86 & arm reciprocal approximation intrinsics.
huonw Jul 29, 2015
ecb3df5
Add simd_cast intrinsic.
huonw Jul 29, 2015
8d8b489
Add intrinsics for SIMD arithmetic.
huonw Jul 31, 2015
cb1eb9d
Remove automatic built-in SIMD operators.
huonw Aug 4, 2015
5889127
Type check platform-intrinsics in typeck.
huonw Aug 5, 2015
717da95
Create "platform-intrinsic" ABI for SIMD/platform intrinsics.
huonw Aug 6, 2015
dbcd9f0
Create separate module for intrinsic typechecking.
huonw Aug 6, 2015
48f3507
Use error codes for platform-intrinsic typeck errors.
huonw Aug 6, 2015
bef1828
Rename `simd_basics` feature gate to `repr_simd`.
huonw Aug 6, 2015
4fe138c
Add _mm_shuffle_epi8 intrinsic.
huonw Aug 10, 2015
9b26895
Generalise SIMD casting to unequal bitwidths.
huonw Aug 10, 2015
e61f539
Add most SSE2 intrinsics.
huonw Aug 11, 2015
907bbac
Reorganise x86 intrinsic definitions.
huonw Aug 11, 2015
9d78efb
Add most SSE3 intrinsics.
huonw Aug 11, 2015
f6275b7
Add most SSSE3 intrinsics.
huonw Aug 11, 2015
627784b
Add most SSE4.1 intrinsics.
huonw Aug 11, 2015
67d56db
Rearrange x86 intrinsics to prepare for AVX.
huonw Aug 11, 2015
29b79aa
Add most AVX intrinsics.
huonw Aug 11, 2015
2a408ef
Add most AVX2 intrinsics.
huonw Aug 11, 2015
d598bdd
Reorganise ARM intrinsic definitions.
huonw Aug 11, 2015
2115468
Add most ARM intrinsics.
huonw Aug 12, 2015
1f5739f
Switch shuffle intrinsics to arrays of indices.
huonw Aug 12, 2015
8b68f58
Allow generic repr(simd) types.
huonw Aug 12, 2015
3e50067
Fix existing tests for new `#[repr(simd)]`.
huonw Aug 12, 2015
926b835
Tweak intrinsic error handling.
huonw Aug 13, 2015
84de8ca
Add tests for various intrinsic behaviours.
huonw Aug 13, 2015
4b24249
Code style tweaks.
huonw Aug 13, 2015
62ba85b
Rebase cleanup: is_simd lost its parameter.
huonw Aug 14, 2015
d792925
Shim some of the old std::simd functionality.
huonw Aug 14, 2015
891c914
simd_shuffleNNN returns its type parameter directly.
huonw Aug 14, 2015
502f9ac
Revamp SIMD intrinsic trans error handling.
huonw Aug 14, 2015
b067e44
Clean up simd_cast translation.
huonw Aug 14, 2015
02e9734
Add AArch64 vrecpeq_... intrinsic (necessary for minimal API).
huonw Aug 15, 2015
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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"]
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

you can possible replace the double-mod with just #[cfg_attr(stage0, path = "simd_old.rs")] pub mod simd;

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

cfg_attr doesn't work with path, e.g.

// path.rs

#[cfg_attr(all(), path = "path.rs")]
mod doesntexist;

fn main() {}

Fails to compile with:

path.rs:2:5: 2:16 error: file not found for module `doesntexist`
path.rs:2 mod doesntexist;
              ^~~~~~~~~~~
path.rs:2:5: 2:16 help: name the file either doesntexist.rs or doesntexist/mod.rs inside the directory ""

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Huh, that's unfortunate.

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 {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you explain in a comment why we need this macro? It seems like its contents could just be inlined.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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). It's unfortunate, to say the least, and hence the name.

(This is also included as an in-source comment.)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh wow, this is a very neat trick, it should be part of our usual bootstrapping toolbox!

() => {
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