Skip to content
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
35 changes: 13 additions & 22 deletions compiler/rustc_codegen_gcc/src/gcc_util.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ fn gcc_features_by_flags(sess: &Session, features: &mut Vec<String>) {

/// The list of GCC features computed from CLI flags (`-Ctarget-cpu`, `-Ctarget-feature`,
/// `--target` and similar).
pub(crate) fn global_gcc_features(sess: &Session, diagnostics: bool) -> Vec<String> {
pub(crate) fn global_gcc_features(sess: &Session) -> Vec<String> {
// Features that come earlier are overridden by conflicting features later in the string.
// Typically we'll want more explicit settings to override the implicit ones, so:
//
Expand All @@ -36,27 +36,18 @@ pub(crate) fn global_gcc_features(sess: &Session, diagnostics: bool) -> Vec<Stri
features.extend(sess.target.features.split(',').filter(|v| !v.is_empty()).map(String::from));

// -Ctarget-features
target_features::flag_to_backend_features(
sess,
diagnostics,
|feature| to_gcc_features(sess, feature),
|feature, enable| {
// We run through `to_gcc_features` when
// passing requests down to GCC. This means that all in-language
// features also work on the command line instead of having two
// different names when the GCC name and the Rust name differ.
features.extend(
to_gcc_features(sess, feature)
.iter()
.flat_map(|feat| to_gcc_features(sess, feat).into_iter())
.map(
|feature| {
if !enable { format!("-{}", feature) } else { feature.to_string() }
},
),
);
},
);
target_features::flag_to_backend_features(sess, |feature, enable| {
// We run through `to_gcc_features` when
// passing requests down to GCC. This means that all in-language
// features also work on the command line instead of having two
// different names when the GCC name and the Rust name differ.
features.extend(
to_gcc_features(sess, feature)
.iter()
.flat_map(|feat| to_gcc_features(sess, feat).into_iter())
.map(|feature| if !enable { format!("-{}", feature) } else { feature.to_string() }),
);
});

gcc_features_by_flags(sess, &mut features);

Expand Down
38 changes: 21 additions & 17 deletions compiler/rustc_codegen_gcc/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,7 @@ use rustc_target::spec::RelocModel;
use tempfile::TempDir;

use crate::back::lto::ModuleBuffer;
use crate::gcc_util::target_cpu;
use crate::gcc_util::{target_cpu, to_gcc_features};

rustc_fluent_macro::fluent_messages! { "../messages.ftl" }

Expand Down Expand Up @@ -220,7 +220,7 @@ impl CodegenBackend for GccCodegenBackend {
}

fn provide(&self, providers: &mut Providers) {
providers.global_backend_features = |tcx, ()| gcc_util::global_gcc_features(tcx.sess, true)
providers.global_backend_features = |tcx, ()| gcc_util::global_gcc_features(tcx.sess)
}

fn codegen_crate(&self, tcx: TyCtxt<'_>) -> Box<dyn Any> {
Expand Down Expand Up @@ -446,21 +446,25 @@ fn to_gcc_opt_level(optlevel: Option<OptLevel>) -> OptimizationLevel {

/// Returns the features that should be set in `cfg(target_feature)`.
fn target_config(sess: &Session, target_info: &LockedTargetInfo) -> TargetConfig {
let (unstable_target_features, target_features) = cfg_target_feature(sess, |feature| {
// TODO: we disable Neon for now since we don't support the LLVM intrinsics for it.
if feature == "neon" {
return false;
}
target_info.cpu_supports(feature)
// cSpell:disable
/*
adx, aes, avx, avx2, avx512bf16, avx512bitalg, avx512bw, avx512cd, avx512dq, avx512er, avx512f, avx512fp16, avx512ifma,
avx512pf, avx512vbmi, avx512vbmi2, avx512vl, avx512vnni, avx512vp2intersect, avx512vpopcntdq,
bmi1, bmi2, cmpxchg16b, ermsb, f16c, fma, fxsr, gfni, lzcnt, movbe, pclmulqdq, popcnt, rdrand, rdseed, rtm,
sha, sse, sse2, sse3, sse4.1, sse4.2, sse4a, ssse3, tbm, vaes, vpclmulqdq, xsave, xsavec, xsaveopt, xsaves
*/
// cSpell:enable
});
let (unstable_target_features, target_features) = cfg_target_feature(
sess,
|feature| to_gcc_features(sess, feature),
|feature| {
// TODO: we disable Neon for now since we don't support the LLVM intrinsics for it.
if feature == "neon" {
return false;
}
target_info.cpu_supports(feature)
// cSpell:disable
/*
adx, aes, avx, avx2, avx512bf16, avx512bitalg, avx512bw, avx512cd, avx512dq, avx512er, avx512f, avx512fp16, avx512ifma,
avx512pf, avx512vbmi, avx512vbmi2, avx512vl, avx512vnni, avx512vp2intersect, avx512vpopcntdq,
bmi1, bmi2, cmpxchg16b, ermsb, f16c, fma, fxsr, gfni, lzcnt, movbe, pclmulqdq, popcnt, rdrand, rdseed, rtm,
sha, sse, sse2, sse3, sse4.1, sse4.2, sse4a, ssse3, tbm, vaes, vpclmulqdq, xsave, xsavec, xsaveopt, xsaves
*/
// cSpell:enable
},
);

let has_reliable_f16 = target_info.supports_target_dependent_type(CType::Float16);
let has_reliable_f128 = target_info.supports_target_dependent_type(CType::Float128);
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_codegen_llvm/src/back/write.rs
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,7 @@ pub(crate) fn create_informational_target_machine(
let config = TargetMachineFactoryConfig { split_dwarf_file: None, output_obj_file: None };
// Can't use query system here quite yet because this function is invoked before the query
// system/tcx is set up.
let features = llvm_util::global_llvm_features(sess, false, only_base_features);
let features = llvm_util::global_llvm_features(sess, only_base_features);
target_machine_factory(sess, config::OptLevel::No, &features)(config)
.unwrap_or_else(|err| llvm_err(sess.dcx(), err))
}
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_codegen_llvm/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -247,7 +247,7 @@ impl CodegenBackend for LlvmCodegenBackend {

fn provide(&self, providers: &mut Providers) {
providers.global_backend_features =
|tcx, ()| llvm_util::global_llvm_features(tcx.sess, true, false)
|tcx, ()| llvm_util::global_llvm_features(tcx.sess, false)
}

fn print(&self, req: &PrintRequest, out: &mut String, sess: &Session) {
Expand Down
94 changes: 43 additions & 51 deletions compiler/rustc_codegen_llvm/src/llvm_util.rs
Original file line number Diff line number Diff line change
Expand Up @@ -291,26 +291,34 @@ pub(crate) fn to_llvm_features<'a>(sess: &Session, s: &'a str) -> Option<LLVMFea
pub(crate) fn target_config(sess: &Session) -> TargetConfig {
let target_machine = create_informational_target_machine(sess, true);

let (unstable_target_features, target_features) = cfg_target_feature(sess, |feature| {
// This closure determines whether the target CPU has the feature according to LLVM. We do
// *not* consider the `-Ctarget-feature`s here, as that will be handled later in
// `cfg_target_feature`.
if let Some(feat) = to_llvm_features(sess, feature) {
// All the LLVM features this expands to must be enabled.
for llvm_feature in feat {
let cstr = SmallCStr::new(llvm_feature);
// `LLVMRustHasFeature` is moderately expensive. On targets with many
// features (e.g. x86) these calls take a non-trivial fraction of runtime
// when compiling very small programs.
if !unsafe { llvm::LLVMRustHasFeature(target_machine.raw(), cstr.as_ptr()) } {
return false;
let (unstable_target_features, target_features) = cfg_target_feature(
sess,
|feature| {
to_llvm_features(sess, feature)
.map(|f| SmallVec::<[&str; 2]>::from_iter(f.into_iter()))
.unwrap_or_default()
},
|feature| {
// This closure determines whether the target CPU has the feature according to LLVM. We do
// *not* consider the `-Ctarget-feature`s here, as that will be handled later in
// `cfg_target_feature`.
if let Some(feat) = to_llvm_features(sess, feature) {
// All the LLVM features this expands to must be enabled.
for llvm_feature in feat {
let cstr = SmallCStr::new(llvm_feature);
// `LLVMRustHasFeature` is moderately expensive. On targets with many
// features (e.g. x86) these calls take a non-trivial fraction of runtime
// when compiling very small programs.
if !unsafe { llvm::LLVMRustHasFeature(target_machine.raw(), cstr.as_ptr()) } {
return false;
}
}
true
} else {
false
}
true
} else {
false
}
});
},
);

let mut cfg = TargetConfig {
target_features,
Expand Down Expand Up @@ -615,11 +623,7 @@ fn llvm_features_by_flags(sess: &Session, features: &mut Vec<String>) {

/// The list of LLVM features computed from CLI flags (`-Ctarget-cpu`, `-Ctarget-feature`,
/// `--target` and similar).
pub(crate) fn global_llvm_features(
sess: &Session,
diagnostics: bool,
only_base_features: bool,
) -> Vec<String> {
pub(crate) fn global_llvm_features(sess: &Session, only_base_features: bool) -> Vec<String> {
// Features that come earlier are overridden by conflicting features later in the string.
// Typically we'll want more explicit settings to override the implicit ones, so:
//
Expand Down Expand Up @@ -679,39 +683,27 @@ pub(crate) fn global_llvm_features(

// -Ctarget-features
if !only_base_features {
target_features::flag_to_backend_features(
sess,
diagnostics,
|feature| {
to_llvm_features(sess, feature)
.map(|f| SmallVec::<[&str; 2]>::from_iter(f.into_iter()))
.unwrap_or_default()
},
|feature, enable| {
let enable_disable = if enable { '+' } else { '-' };
// We run through `to_llvm_features` 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.
let Some(llvm_feature) = to_llvm_features(sess, feature) else { return };

features.extend(
std::iter::once(format!(
"{}{}",
enable_disable, llvm_feature.llvm_feature_name
))
.chain(llvm_feature.dependencies.into_iter().filter_map(
move |feat| match (enable, feat) {
target_features::flag_to_backend_features(sess, |feature, enable| {
let enable_disable = if enable { '+' } else { '-' };
// We run through `to_llvm_features` 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.
let Some(llvm_feature) = to_llvm_features(sess, feature) else { return };

features.extend(
std::iter::once(format!("{}{}", enable_disable, llvm_feature.llvm_feature_name))
.chain(llvm_feature.dependencies.into_iter().filter_map(move |feat| {
match (enable, feat) {
(_, TargetFeatureFoldStrength::Both(f))
| (true, TargetFeatureFoldStrength::EnableOnly(f)) => {
Some(format!("{enable_disable}{f}"))
}
_ => None,
},
)),
)
},
);
}
})),
)
});
}

// We add this in the "base target" so that these show up in `sess.unstable_target_features`.
Expand Down
Loading
Loading