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

Stabilize x86/x86_64 SIMD #49664

Merged
merged 2 commits into from
Apr 17, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
29 changes: 26 additions & 3 deletions src/libcore/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,6 @@
#![feature(asm)]
#![feature(associated_type_defaults)]
#![feature(attr_literals)]
#![feature(cfg_target_feature)]
#![feature(cfg_target_has_atomic)]
#![feature(concat_idents)]
#![feature(const_fn)]
Expand Down Expand Up @@ -96,11 +95,21 @@
#![feature(specialization)]
#![feature(staged_api)]
#![feature(stmt_expr_attributes)]
#![feature(target_feature)]
#![feature(unboxed_closures)]
#![feature(untagged_unions)]
#![feature(unwind_attributes)]

#![cfg_attr(not(stage0), feature(mmx_target_feature))]
#![cfg_attr(not(stage0), feature(tbm_target_feature))]
#![cfg_attr(not(stage0), feature(sse4a_target_feature))]
#![cfg_attr(not(stage0), feature(arm_target_feature))]
#![cfg_attr(not(stage0), feature(powerpc_target_feature))]
#![cfg_attr(not(stage0), feature(mips_target_feature))]
#![cfg_attr(not(stage0), feature(aarch64_target_feature))]

#![cfg_attr(stage0, feature(target_feature))]
#![cfg_attr(stage0, feature(cfg_target_feature))]

#[prelude_import]
#[allow(unused)]
use prelude::v1::*;
Expand Down Expand Up @@ -204,6 +213,20 @@ mod unit;
// things like SIMD and such. Note that the actual source for all this lies in a
// different repository, rust-lang-nursery/stdsimd. That's why the setup here is
// a bit wonky.
#[allow(unused_macros)]
macro_rules! test_v16 { ($item:item) => {}; }
#[allow(unused_macros)]
macro_rules! test_v32 { ($item:item) => {}; }
#[allow(unused_macros)]
macro_rules! test_v64 { ($item:item) => {}; }
#[allow(unused_macros)]
macro_rules! test_v128 { ($item:item) => {}; }
#[allow(unused_macros)]
macro_rules! test_v256 { ($item:item) => {}; }
#[allow(unused_macros)]
macro_rules! test_v512 { ($item:item) => {}; }
#[allow(unused_macros)]
macro_rules! vector_impl { ($([$f:ident, $($args:tt)*]),*) => { $($f!($($args)*);)* } }
#[path = "../stdsimd/coresimd/mod.rs"]
#[allow(missing_docs, missing_debug_implementations, dead_code)]
#[unstable(feature = "stdsimd", issue = "48556")]
Expand All @@ -213,6 +236,6 @@ mod coresimd;
#[unstable(feature = "stdsimd", issue = "48556")]
#[cfg(not(stage0))]
pub use coresimd::simd;
#[unstable(feature = "stdsimd", issue = "48556")]
#[stable(feature = "simd_arch", since = "1.27.0")]
#[cfg(not(stage0))]
pub use coresimd::arch;
2 changes: 1 addition & 1 deletion src/librustc/ty/maps/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -437,7 +437,7 @@ define_maps! { <'tcx>
substitute_normalize_and_test_predicates_node((DefId, &'tcx Substs<'tcx>)) -> bool,

[] fn target_features_whitelist:
target_features_whitelist_node(CrateNum) -> Lrc<FxHashSet<String>>,
target_features_whitelist_node(CrateNum) -> Lrc<FxHashMap<String, Option<String>>>,

// Get an estimate of the size of an InstanceDef based on its MIR for CGU partitioning.
[] fn instance_def_size_estimate: instance_def_size_estimate_dep_node(ty::InstanceDef<'tcx>)
Expand Down
4 changes: 2 additions & 2 deletions src/librustc_trans/attributes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -174,12 +174,12 @@ pub fn provide(providers: &mut Providers) {
// rustdoc needs to be able to document functions that use all the features, so
// whitelist them all
Lrc::new(llvm_util::all_known_features()
.map(|c| c.to_string())
.map(|(a, b)| (a.to_string(), b.map(|s| s.to_string())))
.collect())
} else {
Lrc::new(llvm_util::target_feature_whitelist(tcx.sess)
.iter()
.map(|c| c.to_string())
.map(|&(a, b)| (a.to_string(), b.map(|s| s.to_string())))
.collect())
}
};
Expand Down
123 changes: 94 additions & 29 deletions src/librustc_trans/llvm_util.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ use rustc::session::Session;
use rustc::session::config::PrintRequest;
use libc::c_int;
use std::ffi::CString;
use syntax::feature_gate::UnstableFeatures;

use std::sync::atomic::{AtomicBool, Ordering};
use std::sync::Once;
Expand Down Expand Up @@ -82,40 +83,95 @@ unsafe fn configure_llvm(sess: &Session) {
// to LLVM or the feature detection code will walk past the end of the feature
// array, leading to crashes.

const ARM_WHITELIST: &'static [&'static str] = &["neon", "v7", "vfp2", "vfp3", "vfp4"];

const AARCH64_WHITELIST: &'static [&'static str] = &["fp", "neon", "sve", "crc", "crypto",
"ras", "lse", "rdm", "fp16", "rcpc",
"dotprod", "v8.1a", "v8.2a", "v8.3a"];

const X86_WHITELIST: &'static [&'static str] = &["aes", "avx", "avx2", "avx512bw",
"avx512cd", "avx512dq", "avx512er",
"avx512f", "avx512ifma", "avx512pf",
"avx512vbmi", "avx512vl", "avx512vpopcntdq",
"bmi1", "bmi2", "fma", "fxsr",
"lzcnt", "mmx", "pclmulqdq",
"popcnt", "rdrand", "rdseed",
"sha",
"sse", "sse2", "sse3", "sse4.1",
"sse4.2", "sse4a", "ssse3",
"tbm", "xsave", "xsavec",
"xsaveopt", "xsaves"];

const HEXAGON_WHITELIST: &'static [&'static str] = &["hvx", "hvx-double"];

const POWERPC_WHITELIST: &'static [&'static str] = &["altivec",
"power8-altivec", "power9-altivec",
"power8-vector", "power9-vector",
"vsx"];

const MIPS_WHITELIST: &'static [&'static str] = &["fp64", "msa"];
const ARM_WHITELIST: &[(&str, Option<&str>)] = &[
("neon", Some("arm_target_feature")),
("v7", Some("arm_target_feature")),
("vfp2", Some("arm_target_feature")),
("vfp3", Some("arm_target_feature")),
("vfp4", Some("arm_target_feature")),
];

const AARCH64_WHITELIST: &[(&str, Option<&str>)] = &[
("fp", Some("aarch64_target_feature")),
("neon", Some("aarch64_target_feature")),
("sve", Some("aarch64_target_feature")),
("crc", Some("aarch64_target_feature")),
("crypto", Some("aarch64_target_feature")),
("ras", Some("aarch64_target_feature")),
("lse", Some("aarch64_target_feature")),
("rdm", Some("aarch64_target_feature")),
("fp16", Some("aarch64_target_feature")),
("rcpc", Some("aarch64_target_feature")),
("dotprod", Some("aarch64_target_feature")),
("v8.1a", Some("aarch64_target_feature")),
("v8.2a", Some("aarch64_target_feature")),
("v8.3a", Some("aarch64_target_feature")),
];

const X86_WHITELIST: &[(&str, Option<&str>)] = &[
("aes", None),
("avx", None),
("avx2", None),
("avx512bw", Some("avx512_target_feature")),
("avx512cd", Some("avx512_target_feature")),
("avx512dq", Some("avx512_target_feature")),
("avx512er", Some("avx512_target_feature")),
("avx512f", Some("avx512_target_feature")),
("avx512ifma", Some("avx512_target_feature")),
("avx512pf", Some("avx512_target_feature")),
("avx512vbmi", Some("avx512_target_feature")),
("avx512vl", Some("avx512_target_feature")),
("avx512vpopcntdq", Some("avx512_target_feature")),
("bmi1", None),
("bmi2", None),
("fma", None),
("fxsr", None),
("lzcnt", None),
("mmx", Some("mmx_target_feature")),
("pclmulqdq", None),
("popcnt", None),
("rdrand", None),
("rdseed", None),
("sha", None),
("sse", None),
("sse2", None),
("sse3", None),
("sse4.1", None),
("sse4.2", None),
("sse4a", Some("sse4a_target_feature")),
("ssse3", None),
("tbm", Some("tbm_target_feature")),
("xsave", None),
("xsavec", None),
("xsaveopt", None),
("xsaves", None),
];

const HEXAGON_WHITELIST: &[(&str, Option<&str>)] = &[
("hvx", Some("hexagon_target_feature")),
("hvx-double", Some("hexagon_target_feature")),
];

const POWERPC_WHITELIST: &[(&str, Option<&str>)] = &[
("altivec", Some("powerpc_target_feature")),
("power8-altivec", Some("powerpc_target_feature")),
("power9-altivec", Some("powerpc_target_feature")),
("power8-vector", Some("powerpc_target_feature")),
("power9-vector", Some("powerpc_target_feature")),
("vsx", Some("powerpc_target_feature")),
];

const MIPS_WHITELIST: &[(&str, Option<&str>)] = &[
("fp64", Some("mips_target_feature")),
("msa", Some("mips_target_feature")),
];

/// When rustdoc is running, provide a list of all known features so that all their respective
/// primtives may be documented.
///
/// IMPORTANT: If you're adding another whitelist to the above lists, make sure to add it to this
/// iterator!
pub fn all_known_features() -> impl Iterator<Item=&'static str> {
pub fn all_known_features() -> impl Iterator<Item=(&'static str, Option<&'static str>)> {
ARM_WHITELIST.iter().cloned()
.chain(AARCH64_WHITELIST.iter().cloned())
.chain(X86_WHITELIST.iter().cloned())
Expand Down Expand Up @@ -144,6 +200,13 @@ pub fn target_features(sess: &Session) -> Vec<Symbol> {
let target_machine = create_target_machine(sess, true);
target_feature_whitelist(sess)
.iter()
.filter_map(|&(feature, gate)| {
if UnstableFeatures::from_environment().is_nightly_build() || gate.is_none() {
Some(feature)
} else {
None
}
})
.filter(|feature| {
let llvm_feature = to_llvm_feature(sess, feature);
let cstr = CString::new(llvm_feature).unwrap();
Expand All @@ -152,7 +215,9 @@ pub fn target_features(sess: &Session) -> Vec<Symbol> {
.map(|feature| Symbol::intern(feature)).collect()
}

pub fn target_feature_whitelist(sess: &Session) -> &'static [&'static str] {
pub fn target_feature_whitelist(sess: &Session)
-> &'static [(&'static str, Option<&'static str>)]
{
match &*sess.target.target.arch {
"arm" => ARM_WHITELIST,
"aarch64" => AARCH64_WHITELIST,
Expand Down
4 changes: 2 additions & 2 deletions src/librustc_trans_utils/trans_crate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ use rustc::middle::cstore::EncodedMetadata;
use rustc::middle::cstore::MetadataLoader;
use rustc::dep_graph::DepGraph;
use rustc_back::target::Target;
use rustc_data_structures::fx::FxHashSet;
use rustc_data_structures::fx::FxHashMap;
use rustc_mir::monomorphize::collector;
use link::{build_link_meta, out_filename};

Expand Down Expand Up @@ -203,7 +203,7 @@ impl TransCrate for MetadataOnlyTransCrate {
::symbol_names::provide(providers);

providers.target_features_whitelist = |_tcx, _cnum| {
Lrc::new(FxHashSet()) // Just a dummy
Lrc::new(FxHashMap()) // Just a dummy
};
}
fn provide_extern(&self, _providers: &mut Providers) {}
Expand Down
87 changes: 54 additions & 33 deletions src/librustc_typeck/collect.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,13 +37,14 @@ use rustc::ty::maps::Providers;
use rustc::ty::util::IntTypeExt;
use rustc::ty::util::Discr;
use rustc::util::captures::Captures;
use rustc::util::nodemap::{FxHashSet, FxHashMap};
use rustc::util::nodemap::FxHashMap;

use syntax::{abi, ast};
use syntax::ast::MetaItemKind;
use syntax::attr::{InlineAttr, list_contains_name, mark_used};
use syntax::codemap::Spanned;
use syntax::symbol::{Symbol, keywords};
use syntax::feature_gate;
use syntax_pos::{Span, DUMMY_SP};

use rustc::hir::{self, map as hir_map, TransFnAttrs, TransFnAttrFlags, Unsafety};
Expand Down Expand Up @@ -1682,7 +1683,7 @@ fn is_foreign_item<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
fn from_target_feature(
tcx: TyCtxt,
attr: &ast::Attribute,
whitelist: &FxHashSet<String>,
whitelist: &FxHashMap<String, Option<String>>,
target_features: &mut Vec<Symbol>,
) {
let list = match attr.meta_item_list() {
Expand All @@ -1694,41 +1695,75 @@ fn from_target_feature(
return
}
};

let rust_features = tcx.features();
for item in list {
// Only `enable = ...` is accepted in the meta item list
if !item.check_name("enable") {
let msg = "#[target_feature(..)] only accepts sub-keys of `enable` \
currently";
tcx.sess.span_err(item.span, &msg);
continue
}

// Must be of the form `enable = "..."` ( a string)
let value = match item.value_str() {
Some(list) => list,
Some(value) => value,
None => {
let msg = "#[target_feature] attribute must be of the form \
#[target_feature(enable = \"..\")]";
tcx.sess.span_err(item.span, &msg);
continue
}
};
let value = value.as_str();
for feature in value.split(',') {
if whitelist.contains(feature) {
target_features.push(Symbol::intern(feature));
continue
}

let msg = format!("the feature named `{}` is not valid for \
this target", feature);
let mut err = tcx.sess.struct_span_err(item.span, &msg);

if feature.starts_with("+") {
let valid = whitelist.contains(&feature[1..]);
if valid {
err.help("consider removing the leading `+` in the feature name");
// We allow comma separation to enable multiple features
for feature in value.as_str().split(',') {

// Only allow whitelisted features per platform
let feature_gate = match whitelist.get(feature) {
Some(g) => g,
None => {
let msg = format!("the feature named `{}` is not valid for \
this target", feature);
let mut err = tcx.sess.struct_span_err(item.span, &msg);

if feature.starts_with("+") {
let valid = whitelist.contains_key(&feature[1..]);
if valid {
err.help("consider removing the leading `+` in the feature name");
}
}
err.emit();
continue
}
};

// Only allow features whose feature gates have been enabled
let allowed = match feature_gate.as_ref().map(|s| &**s) {
Some("arm_target_feature") => rust_features.arm_target_feature,
Some("aarch64_target_feature") => rust_features.aarch64_target_feature,
Some("hexagon_target_feature") => rust_features.hexagon_target_feature,
Some("powerpc_target_feature") => rust_features.powerpc_target_feature,
Some("mips_target_feature") => rust_features.mips_target_feature,
Some("avx512_target_feature") => rust_features.avx512_target_feature,
Some("mmx_target_feature") => rust_features.mmx_target_feature,
Some("sse4a_target_feature") => rust_features.sse4a_target_feature,
Some("tbm_target_feature") => rust_features.tbm_target_feature,
Some(name) => bug!("unknown target feature gate {}", name),
None => true,
};
if !allowed {
feature_gate::emit_feature_err(
&tcx.sess.parse_sess,
feature_gate.as_ref().unwrap(),
item.span,
feature_gate::GateIssue::Language,
&format!("the target feature `{}` is currently unstable",
feature),
);
continue
}
err.emit();
target_features.push(Symbol::intern(feature));
}
}
}
Expand Down Expand Up @@ -1835,20 +1870,6 @@ fn trans_fn_attrs<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, id: DefId) -> TransFnAt
.emit();
}
} else if attr.check_name("target_feature") {
// handle deprecated #[target_feature = "..."]
if let Some(val) = attr.value_str() {
for feat in val.as_str().split(",").map(|f| f.trim()) {
if !feat.is_empty() && !feat.contains('\0') {
trans_fn_attrs.target_features.push(Symbol::intern(feat));
}
}
let msg = "#[target_feature = \"..\"] is deprecated and will \
eventually be removed, use \
#[target_feature(enable = \"..\")] instead";
tcx.sess.span_warn(attr.span, &msg);
continue
}

if tcx.fn_sig(id).unsafety() == Unsafety::Normal {
let msg = "#[target_feature(..)] can only be applied to \
`unsafe` function";
Expand Down
Loading