From 6dbac3f09e67c853f343df9d75a7eb213f16c959 Mon Sep 17 00:00:00 2001 From: Jed Brown Date: Wed, 26 Feb 2025 20:06:25 -0700 Subject: add nvptx_target_feature Add target features for sm_* and ptx*, both of which form a partial order, but cannot be combined to a single partial order. These mirror the LLVM target features, but we do not provide LLVM target processors (which imply both an sm_* and ptx* feature). Add some documentation for the nvptx target. --- compiler/rustc_codegen_llvm/src/llvm_util.rs | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'compiler/rustc_codegen_llvm/src') diff --git a/compiler/rustc_codegen_llvm/src/llvm_util.rs b/compiler/rustc_codegen_llvm/src/llvm_util.rs index 6fd07d562af..202b9641e56 100644 --- a/compiler/rustc_codegen_llvm/src/llvm_util.rs +++ b/compiler/rustc_codegen_llvm/src/llvm_util.rs @@ -262,6 +262,15 @@ pub(crate) fn to_llvm_features<'a>(sess: &Session, s: &'a str) -> Option None, // only existed in 18 ("arm", "fp16") => Some(LLVMFeature::new("fullfp16")), + // NVPTX targets added in LLVM 20 + ("nvptx64", "sm_100") if get_version().0 < 20 => None, + ("nvptx64", "sm_100a") if get_version().0 < 20 => None, + ("nvptx64", "sm_101") if get_version().0 < 20 => None, + ("nvptx64", "sm_101a") if get_version().0 < 20 => None, + ("nvptx64", "sm_120") if get_version().0 < 20 => None, + ("nvptx64", "sm_120a") if get_version().0 < 20 => None, + ("nvptx64", "ptx86") if get_version().0 < 20 => None, + ("nvptx64", "ptx87") if get_version().0 < 20 => None, // Filter out features that are not supported by the current LLVM version ("loongarch64", "div32" | "lam-bh" | "lamcas" | "ld-seq-sa" | "scq") if get_version().0 < 20 => -- cgit 1.4.1-3-g733a5 From 35a485ddd86229101c4c17d9167f23cf75cae644 Mon Sep 17 00:00:00 2001 From: Jed Brown Date: Wed, 21 May 2025 22:08:51 -0600 Subject: target-feature: enable rust target features implied by target-cpu Normally LLVM and rustc agree about what features are implied by target-cpu, but for NVPTX, LLVM considers sm_* and ptx* features to be exclusive, which makes sense for codegen purposes. But in Rust, we want to think of them as: sm_{sver} means that the target supports the hardware features of sver ptx{pver} means the driver supports PTX ISA pver Intrinsics usually require a minimum sm_{sver} and ptx{pver}. Prior to this commit, -Ctarget-cpu=sm_70 would activate only sm_70 and ptx60 (the minimum PTX version that supports sm_70, which maximizes driver compatibility). With this commit, it also activates all the implied target features (sm_20, ..., sm_62; ptx32, ..., ptx50). --- compiler/rustc_codegen_llvm/src/llvm_util.rs | 9 +++----- compiler/rustc_codegen_ssa/src/target_features.rs | 15 ++++++++++-- tests/ui/target-feature/implied-features-nvptx.rs | 28 +++++++++++++++++++++++ 3 files changed, 44 insertions(+), 8 deletions(-) create mode 100644 tests/ui/target-feature/implied-features-nvptx.rs (limited to 'compiler/rustc_codegen_llvm/src') diff --git a/compiler/rustc_codegen_llvm/src/llvm_util.rs b/compiler/rustc_codegen_llvm/src/llvm_util.rs index 202b9641e56..2c1882e24be 100644 --- a/compiler/rustc_codegen_llvm/src/llvm_util.rs +++ b/compiler/rustc_codegen_llvm/src/llvm_util.rs @@ -333,15 +333,12 @@ pub(crate) fn to_llvm_features<'a>(sess: &Session, s: &'a str) -> Option TargetConfig { - // Add base features for the target. - // We do *not* add the -Ctarget-features there, and instead duplicate the logic for that below. - // The reason is that if LLVM considers a feature implied but we do not, we don't want that to - // show up in `cfg`. That way, `cfg` is entirely under our control -- except for the handling of - // the target CPU, that is still expanded to target features (with all their implied features) - // by LLVM. 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 { diff --git a/compiler/rustc_codegen_ssa/src/target_features.rs b/compiler/rustc_codegen_ssa/src/target_features.rs index 67ac619091b..e291fb8649c 100644 --- a/compiler/rustc_codegen_ssa/src/target_features.rs +++ b/compiler/rustc_codegen_ssa/src/target_features.rs @@ -224,7 +224,10 @@ fn parse_rust_feature_flag<'a>( /// 2nd component of the return value, respectively). /// /// `target_base_has_feature` should check whether the given feature (a Rust feature name!) is -/// enabled in the "base" target machine, i.e., without applying `-Ctarget-feature`. +/// enabled in the "base" target machine, i.e., without applying `-Ctarget-feature`. Note that LLVM +/// may consider features to be implied that we do not and vice-versa. We want `cfg` to be entirely +/// consistent with Rust feature implications, and thus only consult LLVM to expand the target CPU +/// to target features. /// /// We do not have to worry about RUSTC_SPECIFIC_FEATURES here, those are handled elsewhere. pub fn cfg_target_feature( @@ -238,7 +241,15 @@ pub fn cfg_target_feature( .rust_target_features() .iter() .filter(|(feature, _, _)| target_base_has_feature(feature)) - .map(|(feature, _, _)| Symbol::intern(feature)) + .flat_map(|(base_feature, _, _)| { + // Expand the direct base feature into all transitively-implied features. Note that we + // cannot simply use the `implied` field of the tuple since that only contains + // directly-implied features. + // + // Iteration order is irrelevant because we're collecting into an `UnordSet`. + #[allow(rustc::potential_query_instability)] + sess.target.implied_target_features(base_feature).into_iter().map(|f| Symbol::intern(f)) + }) .collect(); // Add enabled and remove disabled features. diff --git a/tests/ui/target-feature/implied-features-nvptx.rs b/tests/ui/target-feature/implied-features-nvptx.rs new file mode 100644 index 00000000000..1550c99f67a --- /dev/null +++ b/tests/ui/target-feature/implied-features-nvptx.rs @@ -0,0 +1,28 @@ +//@ assembly-output: ptx-linker +//@ compile-flags: --crate-type cdylib -C target-cpu=sm_80 -Z unstable-options -Clinker-flavor=llbc +//@ only-nvptx64 +//@ build-pass +#![no_std] +#![allow(dead_code)] + +#[panic_handler] +pub fn panic(_info: &core::panic::PanicInfo) -> ! { + loop {} +} + +// -Ctarget-cpu=sm_80 directly enables sm_80 and ptx70 +#[cfg(not(all(target_feature = "sm_80", target_feature = "ptx70")))] +compile_error!("direct target features not enabled"); + +// -Ctarget-cpu=sm_80 implies all earlier sm_* and ptx* features. +#[cfg(not(all( + target_feature = "sm_60", + target_feature = "sm_70", + target_feature = "ptx50", + target_feature = "ptx60", +)))] +compile_error!("implied target features not enabled"); + +// -Ctarget-cpu=sm_80 implies all earlier sm_* and ptx* features. +#[cfg(target_feature = "ptx71")] +compile_error!("sm_80 requires only ptx70, but ptx71 enabled"); -- cgit 1.4.1-3-g733a5