about summary refs log tree commit diff
path: root/compiler/rustc_codegen_llvm/src/llvm_util.rs
diff options
context:
space:
mode:
authorJamie Cunliffe <Jamie.Cunliffe@arm.com>2023-01-23 13:15:53 +0000
committerJamie Cunliffe <Jamie.Cunliffe@arm.com>2023-05-22 14:27:14 +0100
commitaab0757c666504f36c5a382304ec5390fc4f7454 (patch)
treeb0440fae8488de45359d4fb775bfe49117f5ff99 /compiler/rustc_codegen_llvm/src/llvm_util.rs
parent4cca436e300db5e6429aa8f041f4dbbcfdecf1b1 (diff)
downloadrust-aab0757c666504f36c5a382304ec5390fc4f7454.tar.gz
rust-aab0757c666504f36c5a382304ec5390fc4f7454.zip
Only disable folded features when it makes sense.
Some features that are tied together only make sense to be folded
together when enabling the feature. For example on AArch64 sve and
neon are tied together, however it doesn't make sense to disable neon
when disabling sve.
Diffstat (limited to 'compiler/rustc_codegen_llvm/src/llvm_util.rs')
-rw-r--r--compiler/rustc_codegen_llvm/src/llvm_util.rs36
1 files changed, 31 insertions, 5 deletions
diff --git a/compiler/rustc_codegen_llvm/src/llvm_util.rs b/compiler/rustc_codegen_llvm/src/llvm_util.rs
index abf46b914b7..a75c15ee4be 100644
--- a/compiler/rustc_codegen_llvm/src/llvm_util.rs
+++ b/compiler/rustc_codegen_llvm/src/llvm_util.rs
@@ -147,6 +147,9 @@ pub fn time_trace_profiler_finish(file_name: &Path) {
 // 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
+//
+// Note: The first feature in the list that is returned is the mapping to the feature that is
+// provided from the `s` parameter.
 pub fn to_llvm_features<'a>(sess: &Session, s: &'a str) -> SmallVec<[&'a str; 2]> {
     let arch = if sess.target.arch == "x86_64" { "x86" } else { &*sess.target.arch };
     match (arch, s) {
@@ -182,6 +185,23 @@ pub fn to_llvm_features<'a>(sess: &Session, s: &'a str) -> SmallVec<[&'a str; 2]
     }
 }
 
+pub enum TargetFeatureFoldStrength {
+    // The feature is only tied when enabling the feature, disabling
+    // this feature shouldn't disable the tied feature.
+    EnableOnly,
+    // The feature is tied for both enabling and disabling this feature.
+    Both,
+}
+
+// Determines how the features are folded together, some features are
+// linked a lot more than some others.
+pub fn feature_fold_strength<'a>(feats: &SmallVec<[&'a str; 2]>) -> TargetFeatureFoldStrength {
+    match (feats.get(0), feats.get(1)) {
+        (Some(&"neon"), Some(&"fp-armv8")) => TargetFeatureFoldStrength::Both,
+        _ => TargetFeatureFoldStrength::EnableOnly,
+    }
+}
+
 /// Given a map from target_features to whether they are enabled or disabled,
 /// ensure only valid combinations are allowed.
 pub fn check_tied_features(
@@ -471,11 +491,17 @@ pub(crate) fn global_llvm_features(sess: &Session, diagnostics: bool) -> Vec<Str
             // 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(
-                to_llvm_features(sess, feature)
-                    .into_iter()
-                    .map(move |f| format!("{}{}", enable_disable, f)),
-            )
+            let llvm_features = to_llvm_features(sess, feature);
+            Some(to_llvm_features(sess, feature).into_iter().enumerate().filter_map(
+                move |(idx, f)| match (enable_disable, feature_fold_strength(&llvm_features)) {
+                    ('-' | '+', TargetFeatureFoldStrength::Both)
+                    | ('+', TargetFeatureFoldStrength::EnableOnly) => {
+                        Some(format!("{}{}", enable_disable, f))
+                    }
+                    _ if idx == 0 => Some(format!("{}{}", enable_disable, f)),
+                    _ => None,
+                },
+            ))
         })
         .flatten();
     features.extend(feats);