mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-24 15:54:15 +00:00
Auto merge of #88981 - durin42:llvm-14-crc32, r=nagisa
rustc_codegen_llvm: make sse4.2 imply crc32 for LLVM 14 This fixes compiling things like the `snap` crate after https://reviews.llvm.org/D105462. I added a test that verifies the additional attribute gets specified, and confirmed that I can build cargo with both LLVM 13 and 14 with this change applied. r? `@nagisa` cc `@nikic`
This commit is contained in:
commit
840acd378a
@ -305,9 +305,12 @@ pub fn from_fn_attrs(cx: &CodegenCx<'ll, 'tcx>, llfn: &'ll Value, instance: ty::
|
||||
let mut function_features = codegen_fn_attrs
|
||||
.target_features
|
||||
.iter()
|
||||
.map(|f| {
|
||||
.flat_map(|f| {
|
||||
let feature = &f.as_str();
|
||||
format!("+{}", llvm_util::to_llvm_feature(cx.tcx.sess, feature))
|
||||
llvm_util::to_llvm_feature(cx.tcx.sess, feature)
|
||||
.into_iter()
|
||||
.map(|f| format!("+{}", f))
|
||||
.collect::<Vec<String>>()
|
||||
})
|
||||
.chain(codegen_fn_attrs.instruction_set.iter().map(|x| match x {
|
||||
InstructionSetAttr::ArmA32 => "-thumb-mode".to_string(),
|
||||
|
@ -166,25 +166,32 @@ pub fn time_trace_profiler_finish(file_name: &str) {
|
||||
// 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 {
|
||||
pub fn to_llvm_feature<'a>(sess: &Session, s: &'a str) -> Vec<&'a str> {
|
||||
let arch = if sess.target.arch == "x86_64" { "x86" } else { &*sess.target.arch };
|
||||
match (arch, s) {
|
||||
("x86", "pclmulqdq") => "pclmul",
|
||||
("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",
|
||||
("aarch64", "fhm") => "fp16fml",
|
||||
("aarch64", "rcpc2") => "rcpc-immo",
|
||||
("aarch64", "dpb") => "ccpp",
|
||||
("aarch64", "dpb2") => "ccdp",
|
||||
("aarch64", "frintts") => "fptoint",
|
||||
("aarch64", "fcma") => "complxnum",
|
||||
(_, s) => s,
|
||||
("x86", "sse4.2") => {
|
||||
if get_version() >= (14, 0, 0) {
|
||||
vec!["sse4.2", "crc32"]
|
||||
} else {
|
||||
vec!["sse4.2"]
|
||||
}
|
||||
}
|
||||
("x86", "pclmulqdq") => vec!["pclmul"],
|
||||
("x86", "rdrand") => vec!["rdrnd"],
|
||||
("x86", "bmi1") => vec!["bmi"],
|
||||
("x86", "cmpxchg16b") => vec!["cx16"],
|
||||
("x86", "avx512vaes") => vec!["vaes"],
|
||||
("x86", "avx512gfni") => vec!["gfni"],
|
||||
("x86", "avx512vpclmulqdq") => vec!["vpclmulqdq"],
|
||||
("aarch64", "fp") => vec!["fp-armv8"],
|
||||
("aarch64", "fp16") => vec!["fullfp16"],
|
||||
("aarch64", "fhm") => vec!["fp16fml"],
|
||||
("aarch64", "rcpc2") => vec!["rcpc-immo"],
|
||||
("aarch64", "dpb") => vec!["ccpp"],
|
||||
("aarch64", "dpb2") => vec!["ccdp"],
|
||||
("aarch64", "frintts") => vec!["fptoint"],
|
||||
("aarch64", "fcma") => vec!["complxnum"],
|
||||
(_, s) => vec![s],
|
||||
}
|
||||
}
|
||||
|
||||
@ -198,9 +205,13 @@ pub fn target_features(sess: &Session) -> Vec<Symbol> {
|
||||
},
|
||||
)
|
||||
.filter(|feature| {
|
||||
let llvm_feature = to_llvm_feature(sess, feature);
|
||||
let cstr = CString::new(llvm_feature).unwrap();
|
||||
unsafe { llvm::LLVMRustHasFeature(target_machine, cstr.as_ptr()) }
|
||||
for llvm_feature in to_llvm_feature(sess, feature) {
|
||||
let cstr = CString::new(llvm_feature).unwrap();
|
||||
if unsafe { llvm::LLVMRustHasFeature(target_machine, cstr.as_ptr()) } {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
false
|
||||
})
|
||||
.map(|feature| Symbol::intern(feature))
|
||||
.collect()
|
||||
@ -253,12 +264,19 @@ fn print_target_features(sess: &Session, tm: &llvm::TargetMachine) {
|
||||
let mut rustc_target_features = supported_target_features(sess)
|
||||
.iter()
|
||||
.filter_map(|(feature, _gate)| {
|
||||
let llvm_feature = to_llvm_feature(sess, *feature);
|
||||
// LLVM asserts that these are sorted. LLVM and Rust both use byte comparison for these strings.
|
||||
target_features.binary_search_by_key(&llvm_feature, |(f, _d)| *f).ok().map(|index| {
|
||||
let (_f, desc) = target_features.remove(index);
|
||||
(*feature, desc)
|
||||
})
|
||||
for llvm_feature in to_llvm_feature(sess, *feature) {
|
||||
// LLVM asserts that these are sorted. LLVM and Rust both use byte comparison for these strings.
|
||||
match target_features.binary_search_by_key(&llvm_feature, |(f, _d)| (*f)).ok().map(
|
||||
|index| {
|
||||
let (_f, desc) = target_features.remove(index);
|
||||
(*feature, desc)
|
||||
},
|
||||
) {
|
||||
Some(v) => return Some(v),
|
||||
None => {}
|
||||
}
|
||||
}
|
||||
None
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
rustc_target_features.extend_from_slice(&[(
|
||||
@ -373,30 +391,30 @@ pub fn llvm_global_features(sess: &Session) -> Vec<String> {
|
||||
|
||||
let filter = |s: &str| {
|
||||
if s.is_empty() {
|
||||
return None;
|
||||
return vec![];
|
||||
}
|
||||
let feature = if s.starts_with('+') || s.starts_with('-') {
|
||||
&s[1..]
|
||||
} else {
|
||||
return Some(s.to_string());
|
||||
return vec![s.to_string()];
|
||||
};
|
||||
// Rustc-specific feature requests like `+crt-static` or `-crt-static`
|
||||
// are not passed down to LLVM.
|
||||
if RUSTC_SPECIFIC_FEATURES.contains(&feature) {
|
||||
return None;
|
||||
return vec![];
|
||||
}
|
||||
// ... otherwise though we run through `to_llvm_feature` feature when
|
||||
// passing requests down to LLVM. This means that all in-language
|
||||
// features also work on the command line instead of having two
|
||||
// different names when the LLVM name and the Rust name differ.
|
||||
Some(format!("{}{}", &s[..1], to_llvm_feature(sess, feature)))
|
||||
to_llvm_feature(sess, feature).iter().map(|f| format!("{}{}", &s[..1], f)).collect()
|
||||
};
|
||||
|
||||
// Features implied by an implicit or explicit `--target`.
|
||||
features.extend(sess.target.features.split(',').filter_map(&filter));
|
||||
features.extend(sess.target.features.split(',').flat_map(&filter));
|
||||
|
||||
// -Ctarget-features
|
||||
features.extend(sess.opts.cg.target_feature.split(',').filter_map(&filter));
|
||||
features.extend(sess.opts.cg.target_feature.split(',').flat_map(&filter));
|
||||
|
||||
features
|
||||
}
|
||||
|
12
src/test/assembly/x86_64-sse_crc.rs
Normal file
12
src/test/assembly/x86_64-sse_crc.rs
Normal file
@ -0,0 +1,12 @@
|
||||
// only-x86_64
|
||||
// assembly-output: emit-asm
|
||||
// compile-flags: --crate-type staticlib -Ctarget-feature=+sse4.2
|
||||
|
||||
// CHECK-LABEL: banana
|
||||
// CHECK: crc32
|
||||
#[no_mangle]
|
||||
pub unsafe fn banana(v: u8) -> u32 {
|
||||
use std::arch::x86_64::*;
|
||||
let out = !0u32;
|
||||
_mm_crc32_u8(out, v)
|
||||
}
|
16
src/test/codegen/sse42-implies-crc32.rs
Normal file
16
src/test/codegen/sse42-implies-crc32.rs
Normal file
@ -0,0 +1,16 @@
|
||||
// only-x86_64
|
||||
// min-llvm-version: 14.0
|
||||
// compile-flags: -Copt-level=3
|
||||
|
||||
#![crate_type = "lib"]
|
||||
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
#[target_feature(enable = "sse4.2")]
|
||||
#[no_mangle]
|
||||
pub unsafe fn crc32sse(v: u8) -> u32 {
|
||||
use std::arch::x86_64::*;
|
||||
let out = !0u32;
|
||||
_mm_crc32_u8(out, v)
|
||||
}
|
||||
|
||||
// CHECK: attributes #0 {{.*"target-features"="\+sse4.2,\+crc32"}}
|
Loading…
Reference in New Issue
Block a user