Skip to content

Commit 840acd3

Browse files
committed
Auto merge of rust-lang#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`
2 parents 7743c9f + 4185b76 commit 840acd3

File tree

4 files changed

+83
-34
lines changed

4 files changed

+83
-34
lines changed

compiler/rustc_codegen_llvm/src/attributes.rs

+5-2
Original file line numberDiff line numberDiff line change
@@ -305,9 +305,12 @@ pub fn from_fn_attrs(cx: &CodegenCx<'ll, 'tcx>, llfn: &'ll Value, instance: ty::
305305
let mut function_features = codegen_fn_attrs
306306
.target_features
307307
.iter()
308-
.map(|f| {
308+
.flat_map(|f| {
309309
let feature = &f.as_str();
310-
format!("+{}", llvm_util::to_llvm_feature(cx.tcx.sess, feature))
310+
llvm_util::to_llvm_feature(cx.tcx.sess, feature)
311+
.into_iter()
312+
.map(|f| format!("+{}", f))
313+
.collect::<Vec<String>>()
311314
})
312315
.chain(codegen_fn_attrs.instruction_set.iter().map(|x| match x {
313316
InstructionSetAttr::ArmA32 => "-thumb-mode".to_string(),

compiler/rustc_codegen_llvm/src/llvm_util.rs

+50-32
Original file line numberDiff line numberDiff line change
@@ -166,25 +166,32 @@ pub fn time_trace_profiler_finish(file_name: &str) {
166166
// Though note that Rust can also be build with an external precompiled version of LLVM
167167
// which might lead to failures if the oldest tested / supported LLVM version
168168
// doesn't yet support the relevant intrinsics
169-
pub fn to_llvm_feature<'a>(sess: &Session, s: &'a str) -> &'a str {
169+
pub fn to_llvm_feature<'a>(sess: &Session, s: &'a str) -> Vec<&'a str> {
170170
let arch = if sess.target.arch == "x86_64" { "x86" } else { &*sess.target.arch };
171171
match (arch, s) {
172-
("x86", "pclmulqdq") => "pclmul",
173-
("x86", "rdrand") => "rdrnd",
174-
("x86", "bmi1") => "bmi",
175-
("x86", "cmpxchg16b") => "cx16",
176-
("x86", "avx512vaes") => "vaes",
177-
("x86", "avx512gfni") => "gfni",
178-
("x86", "avx512vpclmulqdq") => "vpclmulqdq",
179-
("aarch64", "fp") => "fp-armv8",
180-
("aarch64", "fp16") => "fullfp16",
181-
("aarch64", "fhm") => "fp16fml",
182-
("aarch64", "rcpc2") => "rcpc-immo",
183-
("aarch64", "dpb") => "ccpp",
184-
("aarch64", "dpb2") => "ccdp",
185-
("aarch64", "frintts") => "fptoint",
186-
("aarch64", "fcma") => "complxnum",
187-
(_, s) => s,
172+
("x86", "sse4.2") => {
173+
if get_version() >= (14, 0, 0) {
174+
vec!["sse4.2", "crc32"]
175+
} else {
176+
vec!["sse4.2"]
177+
}
178+
}
179+
("x86", "pclmulqdq") => vec!["pclmul"],
180+
("x86", "rdrand") => vec!["rdrnd"],
181+
("x86", "bmi1") => vec!["bmi"],
182+
("x86", "cmpxchg16b") => vec!["cx16"],
183+
("x86", "avx512vaes") => vec!["vaes"],
184+
("x86", "avx512gfni") => vec!["gfni"],
185+
("x86", "avx512vpclmulqdq") => vec!["vpclmulqdq"],
186+
("aarch64", "fp") => vec!["fp-armv8"],
187+
("aarch64", "fp16") => vec!["fullfp16"],
188+
("aarch64", "fhm") => vec!["fp16fml"],
189+
("aarch64", "rcpc2") => vec!["rcpc-immo"],
190+
("aarch64", "dpb") => vec!["ccpp"],
191+
("aarch64", "dpb2") => vec!["ccdp"],
192+
("aarch64", "frintts") => vec!["fptoint"],
193+
("aarch64", "fcma") => vec!["complxnum"],
194+
(_, s) => vec![s],
188195
}
189196
}
190197

@@ -198,9 +205,13 @@ pub fn target_features(sess: &Session) -> Vec<Symbol> {
198205
},
199206
)
200207
.filter(|feature| {
201-
let llvm_feature = to_llvm_feature(sess, feature);
202-
let cstr = CString::new(llvm_feature).unwrap();
203-
unsafe { llvm::LLVMRustHasFeature(target_machine, cstr.as_ptr()) }
208+
for llvm_feature in to_llvm_feature(sess, feature) {
209+
let cstr = CString::new(llvm_feature).unwrap();
210+
if unsafe { llvm::LLVMRustHasFeature(target_machine, cstr.as_ptr()) } {
211+
return true;
212+
}
213+
}
214+
false
204215
})
205216
.map(|feature| Symbol::intern(feature))
206217
.collect()
@@ -253,12 +264,19 @@ fn print_target_features(sess: &Session, tm: &llvm::TargetMachine) {
253264
let mut rustc_target_features = supported_target_features(sess)
254265
.iter()
255266
.filter_map(|(feature, _gate)| {
256-
let llvm_feature = to_llvm_feature(sess, *feature);
257-
// LLVM asserts that these are sorted. LLVM and Rust both use byte comparison for these strings.
258-
target_features.binary_search_by_key(&llvm_feature, |(f, _d)| *f).ok().map(|index| {
259-
let (_f, desc) = target_features.remove(index);
260-
(*feature, desc)
261-
})
267+
for llvm_feature in to_llvm_feature(sess, *feature) {
268+
// LLVM asserts that these are sorted. LLVM and Rust both use byte comparison for these strings.
269+
match target_features.binary_search_by_key(&llvm_feature, |(f, _d)| (*f)).ok().map(
270+
|index| {
271+
let (_f, desc) = target_features.remove(index);
272+
(*feature, desc)
273+
},
274+
) {
275+
Some(v) => return Some(v),
276+
None => {}
277+
}
278+
}
279+
None
262280
})
263281
.collect::<Vec<_>>();
264282
rustc_target_features.extend_from_slice(&[(
@@ -373,30 +391,30 @@ pub fn llvm_global_features(sess: &Session) -> Vec<String> {
373391

374392
let filter = |s: &str| {
375393
if s.is_empty() {
376-
return None;
394+
return vec![];
377395
}
378396
let feature = if s.starts_with('+') || s.starts_with('-') {
379397
&s[1..]
380398
} else {
381-
return Some(s.to_string());
399+
return vec![s.to_string()];
382400
};
383401
// Rustc-specific feature requests like `+crt-static` or `-crt-static`
384402
// are not passed down to LLVM.
385403
if RUSTC_SPECIFIC_FEATURES.contains(&feature) {
386-
return None;
404+
return vec![];
387405
}
388406
// ... otherwise though we run through `to_llvm_feature` feature when
389407
// passing requests down to LLVM. This means that all in-language
390408
// features also work on the command line instead of having two
391409
// different names when the LLVM name and the Rust name differ.
392-
Some(format!("{}{}", &s[..1], to_llvm_feature(sess, feature)))
410+
to_llvm_feature(sess, feature).iter().map(|f| format!("{}{}", &s[..1], f)).collect()
393411
};
394412

395413
// Features implied by an implicit or explicit `--target`.
396-
features.extend(sess.target.features.split(',').filter_map(&filter));
414+
features.extend(sess.target.features.split(',').flat_map(&filter));
397415

398416
// -Ctarget-features
399-
features.extend(sess.opts.cg.target_feature.split(',').filter_map(&filter));
417+
features.extend(sess.opts.cg.target_feature.split(',').flat_map(&filter));
400418

401419
features
402420
}

src/test/assembly/x86_64-sse_crc.rs

+12
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
// only-x86_64
2+
// assembly-output: emit-asm
3+
// compile-flags: --crate-type staticlib -Ctarget-feature=+sse4.2
4+
5+
// CHECK-LABEL: banana
6+
// CHECK: crc32
7+
#[no_mangle]
8+
pub unsafe fn banana(v: u8) -> u32 {
9+
use std::arch::x86_64::*;
10+
let out = !0u32;
11+
_mm_crc32_u8(out, v)
12+
}
+16
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
// only-x86_64
2+
// min-llvm-version: 14.0
3+
// compile-flags: -Copt-level=3
4+
5+
#![crate_type = "lib"]
6+
7+
#[cfg(target_arch = "x86_64")]
8+
#[target_feature(enable = "sse4.2")]
9+
#[no_mangle]
10+
pub unsafe fn crc32sse(v: u8) -> u32 {
11+
use std::arch::x86_64::*;
12+
let out = !0u32;
13+
_mm_crc32_u8(out, v)
14+
}
15+
16+
// CHECK: attributes #0 {{.*"target-features"="\+sse4.2,\+crc32"}}

0 commit comments

Comments
 (0)