Skip to content
This repository was archived by the owner on May 28, 2025. It is now read-only.

Commit 74653b6

Browse files
committed
Add implied target features to target_feature attribute
1 parent 6696447 commit 74653b6

File tree

5 files changed

+113
-31
lines changed

5 files changed

+113
-31
lines changed

compiler/rustc_codegen_llvm/src/llvm_util.rs

Lines changed: 0 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -646,22 +646,6 @@ pub(crate) fn global_llvm_features(sess: &Session, diagnostics: bool) -> Vec<Str
646646
}
647647
}
648648

649-
// This is a workaround for a LLVM bug that doesn't implicitly enable
650-
// `simd128` when `relaxed-simd` is.
651-
// See <https://github.com/llvm/llvm-project/pull/99803>, which didn't make
652-
// it into a released version of LLVM yet.
653-
//
654-
// This doesn't use the "implicit target feature" system because it is only
655-
// used for function attributes in other targets, which fixes this bug as
656-
// well on the function attribute level.
657-
if sess.target.families.contains(&"wasm".into()) {
658-
if features.iter().any(|f| f == "+relaxed-simd")
659-
&& !features.iter().any(|f| f == "+simd128")
660-
{
661-
features.push("+simd128".into());
662-
}
663-
}
664-
665649
if diagnostics && let Some(f) = check_tied_features(sess, &featsmap) {
666650
sess.dcx().emit_err(TargetFeatureDisableOrEnable {
667651
features: f,

compiler/rustc_codegen_ssa/src/target_features.rs

Lines changed: 31 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
use rustc_ast::ast;
22
use rustc_attr::InstructionSetAttr;
3-
use rustc_data_structures::fx::FxIndexSet;
4-
use rustc_data_structures::unord::UnordMap;
3+
use rustc_data_structures::fx::{FxHashMap, FxIndexSet};
4+
use rustc_data_structures::unord::{UnordMap, UnordSet};
55
use rustc_errors::Applicability;
66
use rustc_hir::def::DefKind;
77
use rustc_hir::def_id::{DefId, LocalDefId, LOCAL_CRATE};
@@ -30,6 +30,7 @@ pub fn from_target_feature(
3030
.emit();
3131
};
3232
let rust_features = tcx.features();
33+
let mut added_target_features = Vec::new();
3334
for item in list {
3435
// Only `enable = ...` is accepted in the meta-item list.
3536
if !item.has_name(sym::enable) {
@@ -44,7 +45,7 @@ pub fn from_target_feature(
4445
};
4546

4647
// We allow comma separation to enable multiple features.
47-
target_features.extend(value.as_str().split(',').filter_map(|feature| {
48+
added_target_features.extend(value.as_str().split(',').filter_map(|feature| {
4849
let Some(feature_gate) = supported_target_features.get(feature) else {
4950
let msg = format!("the feature named `{feature}` is not valid for this target");
5051
let mut err = tcx.dcx().struct_span_err(item.span(), msg);
@@ -98,13 +99,12 @@ pub fn from_target_feature(
9899
}));
99100
}
100101

101-
for (feature, requires) in tcx.sess.target.implicit_target_features() {
102-
if target_features.iter().any(|f| f.as_str() == *feature)
103-
&& !target_features.iter().any(|f| f.as_str() == *requires)
104-
{
105-
target_features.push(Symbol::intern(requires));
106-
}
102+
// Add implied features
103+
for feature in added_target_features.iter() {
104+
target_features
105+
.extend(tcx.implied_target_features(*feature).clone().into_sorted_stable_ord());
107106
}
107+
target_features.extend(added_target_features)
108108
}
109109

110110
/// Computes the set of target features used in a function for the purposes of
@@ -162,6 +162,28 @@ pub(crate) fn provide(providers: &mut Providers) {
162162
.collect()
163163
}
164164
},
165+
implied_target_features: |tcx, feature| {
166+
let implied_features = tcx
167+
.sess
168+
.target
169+
.implied_target_features()
170+
.iter()
171+
.map(|(f, i)| (Symbol::intern(f), i))
172+
.collect::<FxHashMap<_, _>>();
173+
174+
// implied target features have their own implied target features, so we traverse the
175+
// map until there are no more features to add
176+
let mut features = UnordSet::new();
177+
let mut new_features = vec![feature];
178+
while let Some(new_feature) = new_features.pop() {
179+
if features.insert(new_feature) {
180+
if let Some(implied_features) = implied_features.get(&new_feature) {
181+
new_features.extend(implied_features.iter().copied().map(Symbol::intern))
182+
}
183+
}
184+
}
185+
features
186+
},
165187
asm_target_features,
166188
..*providers
167189
}

compiler/rustc_middle/src/query/mod.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2183,6 +2183,12 @@ rustc_queries! {
21832183
desc { "looking up supported target features" }
21842184
}
21852185

2186+
query implied_target_features(feature: Symbol) -> &'tcx UnordSet<Symbol> {
2187+
arena_cache
2188+
eval_always
2189+
desc { "looking up implied target features" }
2190+
}
2191+
21862192
query features_query(_: ()) -> &'tcx rustc_feature::Features {
21872193
feedable
21882194
desc { "looking up enabled feature gates" }

compiler/rustc_target/src/target_features.rs

Lines changed: 52 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -339,8 +339,6 @@ const WASM_ALLOWED_FEATURES: &[(&str, Stability)] = &[
339339
// tidy-alphabetical-end
340340
];
341341

342-
const WASM_IMPLICIT_FEATURES: &[(&str, &str)] = &[("relaxed-simd", "simd128")];
343-
344342
const BPF_ALLOWED_FEATURES: &[(&str, Stability)] = &[("alu32", Unstable(sym::bpf_target_feature))];
345343

346344
const CSKY_ALLOWED_FEATURES: &[(&str, Stability)] = &[
@@ -411,6 +409,54 @@ const IBMZ_ALLOWED_FEATURES: &[(&str, Stability)] = &[
411409
// tidy-alphabetical-end
412410
];
413411

412+
const X86_IMPLIED_FEATURES: &[(&str, &[&str])] = &[
413+
// tidy-alphabetical-start
414+
("aes", &["sse2"]),
415+
("avx", &["sse4.2"]),
416+
("avx2", &["avx"]),
417+
("f16c", &["avx"]),
418+
("fma", &["avx"]),
419+
("pclmulqdq", &["sse2"]),
420+
("sha", &["sse2"]),
421+
("sse2", &["sse"]),
422+
("sse3", &["sse2"]),
423+
("sse4.1", &["ssse3"]),
424+
("sse4.2", &["sse4.1"]),
425+
("ssse3", &["sse3"]),
426+
// tidy-alphabetical-end
427+
];
428+
429+
const AARCH64_IMPLIED_FEATURES: &[(&str, &[&str])] = &[
430+
// tidy-alphabetical-start
431+
("aes", &["neon"]),
432+
("f32mm", &["sve"]),
433+
("f64mm", &["sve"]),
434+
("fcma", &["neon"]),
435+
("fhm", &["fp16"]),
436+
("fp16", &["neon"]),
437+
("jsconv", &["neon"]),
438+
("rcpc2", &["rcpc"]),
439+
("sha2", &["neon"]),
440+
("sha3", &["sha2"]),
441+
("sm4", &["neon"]),
442+
("sve", &["fp16"]),
443+
("sve2", &["sve"]),
444+
("sve2-aes", &["sve2", "aes"]),
445+
("sve2-bitperm", &["sve2"]),
446+
("sve2-sha3", &["sve2", "sha3"]),
447+
("sve2-sm4", &["sve2", "sm4"]),
448+
// tidy-alphabetical-end
449+
];
450+
451+
const RISCV_IMPLIED_FEATURES: &[(&str, &[&str])] = &[
452+
// tidy-alphabetical-start
453+
("zb", &["zba", "zbc", "zbs"]),
454+
("zk", &["zkn", "zkr", "zks", "zkt", "zbkb", "zbkc", "zkbx"]),
455+
("zkn", &["zknd", "zkne", "zknh", "zbkb", "zbkc", "zkbx"]),
456+
("zks", &["zksed", "zksh", "zbkb", "zbkc", "zkbx"]),
457+
// tidy-alphabetical-end
458+
];
459+
414460
/// When rustdoc is running, provide a list of all known features so that all their respective
415461
/// primitives may be documented.
416462
///
@@ -458,11 +504,11 @@ impl super::spec::Target {
458504
}
459505
}
460506

461-
/// Returns a list of target features. Each items first target feature
462-
/// implicitly enables the second one.
463-
pub fn implicit_target_features(&self) -> &'static [(&'static str, &'static str)] {
507+
pub fn implied_target_features(&self) -> &'static [(&'static str, &'static [&'static str])] {
464508
match &*self.arch {
465-
"wasm32" | "wasm64" => WASM_IMPLICIT_FEATURES,
509+
"aarch4" => AARCH64_IMPLIED_FEATURES,
510+
"riscv32" | "riscv64" => RISCV_IMPLIED_FEATURES,
511+
"x86" | "x86_64" => X86_IMPLIED_FEATURES,
466512
_ => &[],
467513
}
468514
}
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
//@ only-x86_64
2+
//@ run-pass
3+
#![feature(target_feature_11)]
4+
#![allow(dead_code)]
5+
6+
#[target_feature(enable = "ssse3")]
7+
fn call_ssse3() {}
8+
9+
#[target_feature(enable = "avx")]
10+
fn call_avx() {}
11+
12+
#[target_feature(enable = "avx2")]
13+
fn test_avx2() {
14+
call_ssse3();
15+
call_avx();
16+
}
17+
18+
#[target_feature(enable = "fma")]
19+
fn test_fma() {
20+
call_ssse3();
21+
call_avx();
22+
}
23+
24+
fn main() {}

0 commit comments

Comments
 (0)