Skip to content

[MC] Speed up checkFeatures() (NFCI) #130936

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Mar 12, 2025
Merged

[MC] Speed up checkFeatures() (NFCI) #130936

merged 2 commits into from
Mar 12, 2025

Conversation

nikic
Copy link
Contributor

@nikic nikic commented Mar 12, 2025

checkFeatures() currently goes through ApplyFeatureFlag(), which will also handle implied features. This is very slow -- just querying every feature once takes up 10% of a Rust hello world compile.

However, if we only want to query whether certain features are set/unset, we can do so directly -- implied features have already been handled when the FeatureBitset was constructed.

checkFeatures() currently goes through ApplyFeatureFlag(), which
will also handle implied features. This is very slow -- just
querying every feature once takes up 10% of a Rust hello world
compile.

However, if we only want to query whether certain features are
set/unset, we can do so directly -- implied features have already
been handled when the FeatureBitset was constructed.

I've retained the existing handling for unrecognized features
(print an error and ignore them).
@nikic nikic requested review from arsenm, MaskRay and topperc March 12, 2025 09:44
@llvmbot llvmbot added the mc Machine (object) code label Mar 12, 2025
@llvmbot
Copy link
Member

llvmbot commented Mar 12, 2025

@llvm/pr-subscribers-mc

Author: Nikita Popov (nikic)

Changes

checkFeatures() currently goes through ApplyFeatureFlag(), which will also handle implied features. This is very slow -- just querying every feature once takes up 10% of a Rust hello world compile.

However, if we only want to query whether certain features are set/unset, we can do so directly -- implied features have already been handled when the FeatureBitset was constructed.

I've retained the existing handling for unrecognized features (print an error and ignore them), though I find it somewhat dubious...


Full diff: https://github.com/llvm/llvm-project/pull/130936.diff

1 Files Affected:

  • (modified) llvm/lib/MC/MCSubtargetInfo.cpp (+14-8)
diff --git a/llvm/lib/MC/MCSubtargetInfo.cpp b/llvm/lib/MC/MCSubtargetInfo.cpp
index f59ec2f7c2602..815e092deef22 100644
--- a/llvm/lib/MC/MCSubtargetInfo.cpp
+++ b/llvm/lib/MC/MCSubtargetInfo.cpp
@@ -317,14 +317,20 @@ FeatureBitset MCSubtargetInfo::ApplyFeatureFlag(StringRef FS) {
 
 bool MCSubtargetInfo::checkFeatures(StringRef FS) const {
   SubtargetFeatures T(FS);
-  FeatureBitset Set, All;
-  for (std::string F : T.getFeatures()) {
-    ::ApplyFeatureFlag(Set, F, ProcFeatures);
-    if (F[0] == '-')
-      F[0] = '+';
-    ::ApplyFeatureFlag(All, F, ProcFeatures);
-  }
-  return (FeatureBits & All) == Set;
+  return all_of(T.getFeatures(), [this](const std::string &F) {
+    assert(SubtargetFeatures::hasFlag(F) &&
+           "Feature flags should start with '+' or '-'");
+    const SubtargetFeatureKV *FeatureEntry =
+        Find(SubtargetFeatures::StripFlag(F), ProcFeatures);
+    if (!FeatureEntry) {
+      errs() << "'" << F << "' is not a recognized feature for this target"
+             << " (ignoring feature)\n";
+      return true;
+    }
+
+    return FeatureBits.test(FeatureEntry->Value) ==
+           SubtargetFeatures::isEnabled(F);
+  });
 }
 
 const MCSchedModel &MCSubtargetInfo::getSchedModelForCPU(StringRef CPU) const {

Comment on lines 326 to 327
errs() << "'" << F << "' is not a recognized feature for this target"
<< " (ignoring feature)\n";
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is ApplyFeatureFlag dead now? Or is it used during the construction of the bitset? Can the warning be left for that? We should migrate this to using DiagnosticInfo at least

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ApplyFeatureFlag is still used during construction.

I've changed this code to report a fatal error on invalid feature now. I don't think there's a good reason to make this a warning in checkFeatures().

@nikic nikic merged commit 1900634 into llvm:main Mar 12, 2025
9 of 10 checks passed
@nikic nikic deleted the check-features-opt branch March 12, 2025 14:16
topperc added a commit to topperc/llvm-project that referenced this pull request Mar 14, 2025
Until recently checkFeature was quite slow. llvm#130936

I was curious where we use checkFeature and noticed these. I thought
we could use hasFeature instead of going through strings.
topperc added a commit that referenced this pull request Mar 17, 2025
…131401)

Until recently checkFeature was quite slow. #130936

I was curious where we use checkFeature and noticed these. I thought we
could use hasFeature instead of going through strings.
frederik-h pushed a commit to frederik-h/llvm-project that referenced this pull request Mar 18, 2025
checkFeatures() currently goes through ApplyFeatureFlag(), which will
also handle implied features. This is very slow -- just querying every
feature once takes up 10% of a Rust hello world compile.

However, if we only want to query whether certain features are
set/unset, we can do so directly -- implied features have already been
handled when the FeatureBitset was constructed.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
mc Machine (object) code
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants