From 9feb567399205879c80f9165ac8cdbcf547211da Mon Sep 17 00:00:00 2001 From: DevJPM Date: Sun, 25 Oct 2020 16:53:25 +0100 Subject: [PATCH 1/4] Updated the list of white-listed target features for x86 This PR both adds in-source documentation on what to look out for when adding a new (X86) feature set and adds all that are detectable at run-time in Rust stable as of 1.27.0. This should only enable the use of the corresponding LLVM intrinsics. Actual intrinsics need to be added separately in rust-lang/stdarch. It also re-orders the run-time-detect test statements to be more consistent with the actual list of intrinsics whitelisted and removes underscores not present in the actual names (which might be mistaken as being part of the name) --- compiler/rustc_codegen_llvm/src/llvm_util.rs | 5 ++ .../rustc_codegen_ssa/src/target_features.rs | 13 ++++ library/std/tests/run-time-detect.rs | 63 +++++++++++-------- 3 files changed, 56 insertions(+), 25 deletions(-) diff --git a/compiler/rustc_codegen_llvm/src/llvm_util.rs b/compiler/rustc_codegen_llvm/src/llvm_util.rs index 9c1e1b8fac06f..2cc2825cf32ef 100644 --- a/compiler/rustc_codegen_llvm/src/llvm_util.rs +++ b/compiler/rustc_codegen_llvm/src/llvm_util.rs @@ -137,6 +137,8 @@ pub fn time_trace_profiler_finish(file_name: &str) { // WARNING: the features after applying `to_llvm_feature` must be known // to LLVM or the feature detection code will walk past the end of the feature // array, leading to crashes. +// To find a list of LLVM's names, check llvm-project/llvm/include/llvm/Support/*TargetParser.def +// where the * matches the architecture's name pub fn to_llvm_feature<'a>(sess: &Session, s: &'a str) -> &'a str { let arch = if sess.target.arch == "x86_64" { "x86" } else { &*sess.target.arch }; match (arch, s) { @@ -144,6 +146,9 @@ pub fn to_llvm_feature<'a>(sess: &Session, s: &'a str) -> &'a str { ("x86", "rdrand") => "rdrnd", ("x86", "bmi1") => "bmi", ("x86", "cmpxchg16b") => "cx16", + ("x86", "avx512vaes") => "vaes", + ("x86", "avx512gfni") => "gfni", + ("x86", "avx512vpclmulqdq") => "vpclmulqdq", ("aarch64", "fp") => "fp-armv8", ("aarch64", "fp16") => "fullfp16", (_, s) => s, diff --git a/compiler/rustc_codegen_ssa/src/target_features.rs b/compiler/rustc_codegen_ssa/src/target_features.rs index a8d88a95f7a27..cef96620884ff 100644 --- a/compiler/rustc_codegen_ssa/src/target_features.rs +++ b/compiler/rustc_codegen_ssa/src/target_features.rs @@ -4,6 +4,11 @@ use rustc_session::Session; use rustc_span::symbol::sym; use rustc_span::symbol::Symbol; +// When adding features to the below lists +// check whether they're named already elsewhere in rust +// e.g. in stdarch and whether the given name matches LLVM's +// if it doesn't, to_llvm_feature in llvm_util in rustc_codegen_llvm needs to be adapted + const ARM_ALLOWED_FEATURES: &[(&str, Option)] = &[ ("aclass", Some(sym::arm_target_feature)), ("mclass", Some(sym::arm_target_feature)), @@ -50,15 +55,23 @@ const X86_ALLOWED_FEATURES: &[(&str, Option)] = &[ ("aes", None), ("avx", None), ("avx2", None), + ("avx512bf16", Some(sym::avx512_target_feature)), + ("avx512bitalg", Some(sym::avx512_target_feature)), ("avx512bw", Some(sym::avx512_target_feature)), ("avx512cd", Some(sym::avx512_target_feature)), ("avx512dq", Some(sym::avx512_target_feature)), ("avx512er", Some(sym::avx512_target_feature)), ("avx512f", Some(sym::avx512_target_feature)), + ("avx512gfni", Some(sym::avx512_target_feature)), ("avx512ifma", Some(sym::avx512_target_feature)), ("avx512pf", Some(sym::avx512_target_feature)), + ("avx512vaes", Some(sym::avx512_target_feature)), ("avx512vbmi", Some(sym::avx512_target_feature)), + ("avx512vbmi2", Some(sym::avx512_target_feature)), ("avx512vl", Some(sym::avx512_target_feature)), + ("avx512vnni", Some(sym::avx512_target_feature)), + ("avx512vp2intersect", Some(sym::avx512_target_feature)), + ("avx512vpclmulqdq", Some(sym::avx512_target_feature)), ("avx512vpopcntdq", Some(sym::avx512_target_feature)), ("bmi1", None), ("bmi2", None), diff --git a/library/std/tests/run-time-detect.rs b/library/std/tests/run-time-detect.rs index 8dd1a8ac0d2df..ffd9a04d8643a 100644 --- a/library/std/tests/run-time-detect.rs +++ b/library/std/tests/run-time-detect.rs @@ -54,42 +54,55 @@ fn powerpc64_linux() { #[test] #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] fn x86_all() { + // the below is in alphabetical order and matches + // the order of X86_ALLOWED_FEATURES in rustc_codegen_ssa's target_features.rs + + println!("adx: {:?}", is_x86_feature_detected!("adx")); println!("aes: {:?}", is_x86_feature_detected!("aes")); - println!("pcmulqdq: {:?}", is_x86_feature_detected!("pclmulqdq")); + println!("avx: {:?}", is_x86_feature_detected!("avx")); + println!("avx2: {:?}", is_x86_feature_detected!("avx2")); + println!("avx512bf16: {:?}", is_x86_feature_detected!("avx512bf16")); + println!("avx512bitalg: {:?}", is_x86_feature_detected!("avx512bitalg")); + println!("avx512bw: {:?}", is_x86_feature_detected!("avx512bw")); + println!("avx512cd: {:?}", is_x86_feature_detected!("avx512cd")); + println!("avx512dq: {:?}", is_x86_feature_detected!("avx512dq")); + println!("avx512er: {:?}", is_x86_feature_detected!("avx512er")); + println!("avx512f: {:?}", is_x86_feature_detected!("avx512f")); + println!("avx512gfni: {:?}", is_x86_feature_detected!("avx512gfni")); + println!("avx512ifma: {:?}", is_x86_feature_detected!("avx512ifma")); + println!("avx512pf: {:?}", is_x86_feature_detected!("avx512pf")); + println!("avx512vaes: {:?}", is_x86_feature_detected!("avx512vaes")); + println!("avx512vbmi: {:?}", is_x86_feature_detected!("avx512vbmi")); + println!("avx512vbmi2: {:?}", is_x86_feature_detected!("avx512vbmi2")); + println!("avx512vl: {:?}", is_x86_feature_detected!("avx512vl")); + println!("avx512vnni: {:?}", is_x86_feature_detected!("avx512vnni")); + println!("avx512vp2intersect: {:?}", is_x86_feature_detected!("avx512vp2intersect")); + println!("avx512vpclmulqdq: {:?}", is_x86_feature_detected!("avx512vpclmulqdq")); + println!("avx512vpopcntdq: {:?}", is_x86_feature_detected!("avx512vpopcntdq")); + println!("bmi1: {:?}", is_x86_feature_detected!("bmi1")); + println!("bmi2: {:?}", is_x86_feature_detected!("bmi2")); + println!("cmpxchg16b: {:?}", is_x86_feature_detected!("cmpxchg16b")); + println!("f16c: {:?}", is_x86_feature_detected!("f16c")); + println!("fma: {:?}", is_x86_feature_detected!("fma")); + println!("fxsr: {:?}", is_x86_feature_detected!("fxsr")); + println!("lzcnt: {:?}", is_x86_feature_detected!("lzcnt")); + println!("movbe: {:?}", is_x86_feature_detected!("movbe")); + println!("pclmulqdq: {:?}", is_x86_feature_detected!("pclmulqdq")); + println!("popcnt: {:?}", is_x86_feature_detected!("popcnt")); println!("rdrand: {:?}", is_x86_feature_detected!("rdrand")); println!("rdseed: {:?}", is_x86_feature_detected!("rdseed")); - println!("tsc: {:?}", is_x86_feature_detected!("tsc")); - println!("mmx: {:?}", is_x86_feature_detected!("mmx")); + println!("rtm: {:?}", is_x86_feature_detected!("rtm")); + println!("sha: {:?}", is_x86_feature_detected!("sha")); println!("sse: {:?}", is_x86_feature_detected!("sse")); println!("sse2: {:?}", is_x86_feature_detected!("sse2")); println!("sse3: {:?}", is_x86_feature_detected!("sse3")); - println!("ssse3: {:?}", is_x86_feature_detected!("ssse3")); println!("sse4.1: {:?}", is_x86_feature_detected!("sse4.1")); println!("sse4.2: {:?}", is_x86_feature_detected!("sse4.2")); println!("sse4a: {:?}", is_x86_feature_detected!("sse4a")); - println!("sha: {:?}", is_x86_feature_detected!("sha")); - println!("avx: {:?}", is_x86_feature_detected!("avx")); - println!("avx2: {:?}", is_x86_feature_detected!("avx2")); - println!("avx512f {:?}", is_x86_feature_detected!("avx512f")); - println!("avx512cd {:?}", is_x86_feature_detected!("avx512cd")); - println!("avx512er {:?}", is_x86_feature_detected!("avx512er")); - println!("avx512pf {:?}", is_x86_feature_detected!("avx512pf")); - println!("avx512bw {:?}", is_x86_feature_detected!("avx512bw")); - println!("avx512dq {:?}", is_x86_feature_detected!("avx512dq")); - println!("avx512vl {:?}", is_x86_feature_detected!("avx512vl")); - println!("avx512_ifma {:?}", is_x86_feature_detected!("avx512ifma")); - println!("avx512_vbmi {:?}", is_x86_feature_detected!("avx512vbmi")); - println!("avx512_vpopcntdq {:?}", is_x86_feature_detected!("avx512vpopcntdq")); - println!("fma: {:?}", is_x86_feature_detected!("fma")); - println!("bmi1: {:?}", is_x86_feature_detected!("bmi1")); - println!("bmi2: {:?}", is_x86_feature_detected!("bmi2")); - println!("abm: {:?}", is_x86_feature_detected!("abm")); - println!("lzcnt: {:?}", is_x86_feature_detected!("lzcnt")); + println!("ssse3: {:?}", is_x86_feature_detected!("ssse3")); println!("tbm: {:?}", is_x86_feature_detected!("tbm")); - println!("popcnt: {:?}", is_x86_feature_detected!("popcnt")); - println!("fxsr: {:?}", is_x86_feature_detected!("fxsr")); println!("xsave: {:?}", is_x86_feature_detected!("xsave")); + println!("xsavec: {:?}", is_x86_feature_detected!("xsavec")); println!("xsaveopt: {:?}", is_x86_feature_detected!("xsaveopt")); println!("xsaves: {:?}", is_x86_feature_detected!("xsaves")); - println!("xsavec: {:?}", is_x86_feature_detected!("xsavec")); } From cd95e939bb9bef598be54067e93ac712d43fba71 Mon Sep 17 00:00:00 2001 From: DevJPM Date: Sun, 25 Oct 2020 17:27:22 +0100 Subject: [PATCH 2/4] Removed movbe from run-time-detect `movbe` seems to not be a run-time detectable feature on x86. It has thus been removed from the list. It was only commented out to ease comparison against the full list. --- library/std/tests/run-time-detect.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/std/tests/run-time-detect.rs b/library/std/tests/run-time-detect.rs index ffd9a04d8643a..04759d382a6fb 100644 --- a/library/std/tests/run-time-detect.rs +++ b/library/std/tests/run-time-detect.rs @@ -86,7 +86,7 @@ fn x86_all() { println!("fma: {:?}", is_x86_feature_detected!("fma")); println!("fxsr: {:?}", is_x86_feature_detected!("fxsr")); println!("lzcnt: {:?}", is_x86_feature_detected!("lzcnt")); - println!("movbe: {:?}", is_x86_feature_detected!("movbe")); + //println!("movbe: {:?}", is_x86_feature_detected!("movbe")); // movbe is unsupported as a target feature println!("pclmulqdq: {:?}", is_x86_feature_detected!("pclmulqdq")); println!("popcnt: {:?}", is_x86_feature_detected!("popcnt")); println!("rdrand: {:?}", is_x86_feature_detected!("rdrand")); From 3daa93f555f4dab102da2a8d05cc38c4087166af Mon Sep 17 00:00:00 2001 From: DevJPM Date: Mon, 26 Oct 2020 08:15:23 +0100 Subject: [PATCH 3/4] Updated documentation, x86 feature detection testing, and removed LLVM 9 exclusive features Updated the added documentation in llvm_util.rs to note which copies of LLVM need to be inspected. Removed avx512bf16 and avx512vp2intersect because they are unsupported before LLVM 9 with the build with external LLVM 8 being supported Re-introduced detection testing previously removed for un-requestable features tsc and mmx --- compiler/rustc_codegen_llvm/src/llvm_util.rs | 5 +++++ compiler/rustc_codegen_ssa/src/target_features.rs | 4 ++-- library/std/tests/run-time-detect.rs | 7 +++++++ 3 files changed, 14 insertions(+), 2 deletions(-) diff --git a/compiler/rustc_codegen_llvm/src/llvm_util.rs b/compiler/rustc_codegen_llvm/src/llvm_util.rs index 2cc2825cf32ef..91686d27442c0 100644 --- a/compiler/rustc_codegen_llvm/src/llvm_util.rs +++ b/compiler/rustc_codegen_llvm/src/llvm_util.rs @@ -139,6 +139,11 @@ pub fn time_trace_profiler_finish(file_name: &str) { // array, leading to crashes. // To find a list of LLVM's names, check llvm-project/llvm/include/llvm/Support/*TargetParser.def // where the * matches the architecture's name +// Beware to not use the llvm github project for this, but check the git submodule +// found in src/llvm-project +// Though note that Rust can also be build with an external precompiled version of LLVM +// which might lead to failures if the oldest tested / supported LLVM version +// doesn't yet support the relevant intrinsics pub fn to_llvm_feature<'a>(sess: &Session, s: &'a str) -> &'a str { let arch = if sess.target.arch == "x86_64" { "x86" } else { &*sess.target.arch }; match (arch, s) { diff --git a/compiler/rustc_codegen_ssa/src/target_features.rs b/compiler/rustc_codegen_ssa/src/target_features.rs index cef96620884ff..e624768824bcb 100644 --- a/compiler/rustc_codegen_ssa/src/target_features.rs +++ b/compiler/rustc_codegen_ssa/src/target_features.rs @@ -55,7 +55,7 @@ const X86_ALLOWED_FEATURES: &[(&str, Option)] = &[ ("aes", None), ("avx", None), ("avx2", None), - ("avx512bf16", Some(sym::avx512_target_feature)), + //("avx512bf16", Some(sym::avx512_target_feature)), // this seems to be unsupported by the supported build with external LLVM 8, LLVM 9 should be sufficient though ("avx512bitalg", Some(sym::avx512_target_feature)), ("avx512bw", Some(sym::avx512_target_feature)), ("avx512cd", Some(sym::avx512_target_feature)), @@ -70,7 +70,7 @@ const X86_ALLOWED_FEATURES: &[(&str, Option)] = &[ ("avx512vbmi2", Some(sym::avx512_target_feature)), ("avx512vl", Some(sym::avx512_target_feature)), ("avx512vnni", Some(sym::avx512_target_feature)), - ("avx512vp2intersect", Some(sym::avx512_target_feature)), + //("avx512vp2intersect", Some(sym::avx512_target_feature)), // this seems to be unsupported by the supported build with external LLVM 8, LLVM 9 should be sufficient though ("avx512vpclmulqdq", Some(sym::avx512_target_feature)), ("avx512vpopcntdq", Some(sym::avx512_target_feature)), ("bmi1", None), diff --git a/library/std/tests/run-time-detect.rs b/library/std/tests/run-time-detect.rs index 04759d382a6fb..61a04c467224b 100644 --- a/library/std/tests/run-time-detect.rs +++ b/library/std/tests/run-time-detect.rs @@ -54,6 +54,13 @@ fn powerpc64_linux() { #[test] #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] fn x86_all() { + // the below is the set of features we can test at runtime, but don't actually + // use to gate anything and are thus not part of the X86_ALLOWED_FEATURES list + + println!("abm: {:?}", is_x86_feature_detected!("abm")); // this is a synonym for lzcnt but we test it anyways + println!("mmx: {:?}", is_x86_feature_detected!("mmx")); + println!("tsc: {:?}", is_x86_feature_detected!("tsc")); + // the below is in alphabetical order and matches // the order of X86_ALLOWED_FEATURES in rustc_codegen_ssa's target_features.rs From 72b83af2ffadbc98fee52481c7168b0b644d73db Mon Sep 17 00:00:00 2001 From: DevJPM Date: Sun, 15 Nov 2020 11:34:08 +0100 Subject: [PATCH 4/4] Re-enable LLVM 9 target features with LLVM 9 being the minimum now With #78848 merged, the minimum supported LLVM version is now 9 which means we can actually use the target features introduced in LLVM 9 --- compiler/rustc_codegen_ssa/src/target_features.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/compiler/rustc_codegen_ssa/src/target_features.rs b/compiler/rustc_codegen_ssa/src/target_features.rs index e624768824bcb..cef96620884ff 100644 --- a/compiler/rustc_codegen_ssa/src/target_features.rs +++ b/compiler/rustc_codegen_ssa/src/target_features.rs @@ -55,7 +55,7 @@ const X86_ALLOWED_FEATURES: &[(&str, Option)] = &[ ("aes", None), ("avx", None), ("avx2", None), - //("avx512bf16", Some(sym::avx512_target_feature)), // this seems to be unsupported by the supported build with external LLVM 8, LLVM 9 should be sufficient though + ("avx512bf16", Some(sym::avx512_target_feature)), ("avx512bitalg", Some(sym::avx512_target_feature)), ("avx512bw", Some(sym::avx512_target_feature)), ("avx512cd", Some(sym::avx512_target_feature)), @@ -70,7 +70,7 @@ const X86_ALLOWED_FEATURES: &[(&str, Option)] = &[ ("avx512vbmi2", Some(sym::avx512_target_feature)), ("avx512vl", Some(sym::avx512_target_feature)), ("avx512vnni", Some(sym::avx512_target_feature)), - //("avx512vp2intersect", Some(sym::avx512_target_feature)), // this seems to be unsupported by the supported build with external LLVM 8, LLVM 9 should be sufficient though + ("avx512vp2intersect", Some(sym::avx512_target_feature)), ("avx512vpclmulqdq", Some(sym::avx512_target_feature)), ("avx512vpopcntdq", Some(sym::avx512_target_feature)), ("bmi1", None),