Skip to content

cg_llvm: Use fewer FFI calls to check the target CPU's features - #163143

Merged
rust-bors[bot] merged 1 commit into
rust-lang:mainfrom
Zalathar:check-features
Sep 24, 2026
Merged

rust-bors[bot] merged 1 commit into
rust-lang:mainfrom
Zalathar:check-features

Conversation

@Zalathar

@Zalathar Zalathar commented Sep 22, 2026 •

Copy link
Copy Markdown
Member

The existing code makes a separate FFI call to MCSubtargetInfo::checkFeatures for each feature-dependency of the feature being checked, and also performs string-manipulation on the C++ side to add a leading + to each feature name.

What we can do instead is prepare a single string on the Rust side in the form "+foo,+bar,+baz," for each Rust target feature, and pass that to LLVM as a pointer/length string. LLVM already knows how to check that all of the listed features are present.

This change makes the code simpler overall. All of the string manipulation now takes place either in Rust code or in LLVM itself, and not in our C++ wrapper.

There should be no change to compiler output.

@rustbot rustbot added A-LLVM Area: Code generation parts specific to LLVM. Both correctness bugs and optimization-related issues. S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. labels Sep 22, 2026
@Zalathar

Copy link
Copy Markdown
Member Author

@bors try @rust-timer queue

@rust-timer

This comment has been minimized.

@rust-bors

This comment has been minimized.

rust-bors Bot pushed a commit that referenced this pull request Sep 22, 2026
cg_llvm: Use fewer FFI calls to check the target CPU's features
@rustbot rustbot added the S-waiting-on-perf Status: Waiting on a perf run to be completed. label Sep 22, 2026
@rust-bors

rust-bors Bot commented Sep 22, 2026

Copy link
Copy Markdown
Contributor

☀️ Try build successful (CI)
Build commit: e047fe3 (e047fe3142fe7f4c66385c976f3c4b7b1e5b8b15)
Base parent: 88638df (88638df1e741778019e42fcdf307072865d19501)

@rust-timer

This comment has been minimized.

@rust-timer

Copy link
Copy Markdown
Collaborator

Finished benchmarking commit (e047fe3): comparison URL.

Overall result: no relevant changes - no action needed

Benchmarking means the PR may be perf-sensitive. Consider adding rollup=never if this change is not fit for rolling up.

@rustbot label: -S-waiting-on-perf -perf-regression

Instruction count

This perf run didn't have relevant results for this metric.

Max RSS (memory usage)

Results (secondary 2.7%)

A less reliable metric. May be of interest, but not used to determine the overall result above.

mean range count
Regressions ❌
(primary)
- - 0
Regressions ❌
(secondary)
2.7% [2.7%, 2.7%] 1
Improvements ✅
(primary)
- - 0
Improvements ✅
(secondary)
- - 0
All ❌✅ (primary) - - 0

Cycles

Results (primary 2.8%, secondary 0.1%)

A less reliable metric. May be of interest, but not used to determine the overall result above.

mean range count
Regressions ❌
(primary)
2.8% [2.8%, 2.8%] 1
Regressions ❌
(secondary)
2.3% [2.3%, 2.3%] 1
Improvements ✅
(primary)
- - 0
Improvements ✅
(secondary)
-2.1% [-2.1%, -2.1%] 1
All ❌✅ (primary) 2.8% [2.8%, 2.8%] 1

Binary size

Results (primary 0.0%, secondary 0.0%)

A less reliable metric. May be of interest, but not used to determine the overall result above.

mean range count
Regressions ❌
(primary)
0.0% [0.0%, 0.1%] 11
Regressions ❌
(secondary)
0.0% [0.0%, 0.1%] 6
Improvements ✅
(primary)
- - 0
Improvements ✅
(secondary)
- - 0
All ❌✅ (primary) 0.0% [0.0%, 0.1%] 11

Bootstrap: 487.826s -> 488.235s (0.08%)
Artifact size: 406.29 MiB -> 406.39 MiB (0.03%)

@rustbot rustbot removed the S-waiting-on-perf Status: Waiting on a perf run to be completed. label Sep 22, 2026
@Zalathar

Copy link
Copy Markdown
Member Author

No measurable perf effect, but I think this still makes sense on its own, as the Rust-side and C++-side code are both simpler.

Comment on lines -368 to -370
// `has_feature` 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.

@Zalathar Zalathar Sep 22, 2026 •

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

I believe this comment was made obsolete by llvm/llvm-project#130936, which is included in LLVM 21.

View changes since the review

@Zalathar
Zalathar marked this pull request as ready for review September 22, 2026 05:48
@rustbot rustbot added the S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. label Sep 22, 2026
@rustbot rustbot removed the S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. label Sep 22, 2026
@rustbot

rustbot commented Sep 22, 2026

Copy link
Copy Markdown
Collaborator

r? @davidtwco

rustbot has assigned @davidtwco.
They will have a look at your PR within the next two weeks and either review your PR or reassign to another reviewer.

Use r? to explicitly pick a reviewer

Why was this reviewer chosen?

The reviewer was selected based on:

  • Owners of files modified in this PR: compiler
  • compiler expanded to 77 candidates
  • Random selection from 19 candidates

@davidtwco davidtwco left a comment •

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

r=me after checking comment

View changes since this review

pub(crate) fn has_features(&self, features: llvm_util::LLVMFeature<'_>) -> bool {
// Convert to a feature string expected by LLVM's `SubtargetFeatures`.
// All of the required LLVM features must be enabled.
let features = features.into_iter().flat_map(|feat| ["+", feat, ","]).collect::<String>();

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I assume there's no issues with the trailing comma here at the end?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Yeah, the split-on-commas in LLVM's SubtargetFeatures::Split sets KeepEmpty=false, so the empty segment after the trailing comma is safely discarded.

I added a comment to mention this.

The existing code makes a separate FFI call to `MCSubtargetInfo::checkFeatures`
for each feature-dependency of the feature being checked, and also performs
string-manipulation on the C++ side to add a leading '+' to each feature name.

What we can do instead is prepare a single string on the Rust side in the form
`"+foo,+bar,+baz,"` for each Rust target feature, and pass that string to LLVM.
LLVM already knows how to check that all of the listed features are present.

(The trailing comma is not a problem, because `SubtargetFeatures::Split` will
automatically discard empty substrings after splitting on commas.)
@rustbot

rustbot commented Sep 24, 2026

Copy link
Copy Markdown
Collaborator

This PR was rebased onto a different main commit. Here's a range-diff highlighting what actually changed.

Rebasing is a normal part of keeping PRs up to date, so no action is needed—this note is just to help reviewers.

@Zalathar

Copy link
Copy Markdown
Member Author

Added a comment about the trailing comma being OK.

@bors r=davidtwco

@rust-bors

rust-bors Bot commented Sep 24, 2026

Copy link
Copy Markdown
Contributor

📌 Commit 733daee has been approved by davidtwco

It is now in the queue for this repository.

@rust-bors rust-bors Bot added S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion. and removed S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. labels Sep 24, 2026
rust-bors Bot pushed a commit that referenced this pull request Sep 24, 2026
…uwer

Rollup of 14 pull requests

Successful merges:

 - #162976 (fix quadratic naming of duplicate sidebar links)
 - #161275 (Refactor `core::cmp::{smallest, largest}` & add `mir-opt` test)
 - #163143 (cg_llvm: Use fewer FFI calls to check the target CPU's features)
 - #163188 (Adjust for Arm64EC name mangling when checking for exported symbols)
 - #163211 (`rustc_builtin_macros` cleanup, part 6)
 - #161386 (Don't merge distinct impl candidates)
 - #162942 (Remove `StashKey::AssociatedTypeSuggestion`)
 - #163096 (Don't suggest `std::` rustfix paths in `#![no_std]` crates)
 - #163110 (Mark `std::os::wasip2` with correct doc-cfgs, mark as unstable)
 - #163185 (properly decrement available_depth on cycles and provisional cache hits)
 - #163214 (revert r14 register names for arm)
 - #163226 (miri subtree update)
 - #163228 (Add regression test for trait predicate with escaping bounds)
 - #163234 (`rustc_dump_symbol_name`: add demangling information as a note instead)
@rust-bors
rust-bors Bot merged commit 5c845c6 into rust-lang:main Sep 24, 2026
13 checks passed
@rustbot rustbot added this to the 1.100.0 milestone Sep 24, 2026
rust-bors Bot pushed a commit that referenced this pull request Sep 24, 2026
Rollup merge of #163143 - Zalathar:check-features, r=davidtwco

cg_llvm: Use fewer FFI calls to check the target CPU's features

The existing code makes a separate FFI call to `MCSubtargetInfo::checkFeatures` for each feature-dependency of the feature being checked, and also performs string-manipulation on the C++ side to add a leading `+` to each feature name.

What we can do instead is prepare a single string on the Rust side in the form `"+foo,+bar,+baz,"` for each Rust target feature, and pass that to LLVM as a pointer/length string. LLVM already knows how to check that all of the listed features are present.

This change makes the code simpler overall. All of the string manipulation now takes place either in Rust code or in LLVM itself, and not in our C++ wrapper.

There should be no change to compiler output.
@Zalathar
Zalathar deleted the check-features branch September 24, 2026 23:25
pull Bot pushed a commit to xtqqczze/rust-lang-miri that referenced this pull request Sep 25, 2026
…uwer

Rollup of 14 pull requests

Successful merges:

 - rust-lang/rust#162976 (fix quadratic naming of duplicate sidebar links)
 - rust-lang/rust#161275 (Refactor `core::cmp::{smallest, largest}` & add `mir-opt` test)
 - rust-lang/rust#163143 (cg_llvm: Use fewer FFI calls to check the target CPU's features)
 - rust-lang/rust#163188 (Adjust for Arm64EC name mangling when checking for exported symbols)
 - rust-lang/rust#163211 (`rustc_builtin_macros` cleanup, part 6)
 - rust-lang/rust#161386 (Don't merge distinct impl candidates)
 - rust-lang/rust#162942 (Remove `StashKey::AssociatedTypeSuggestion`)
 - rust-lang/rust#163096 (Don't suggest `std::` rustfix paths in `#![no_std]` crates)
 - rust-lang/rust#163110 (Mark `std::os::wasip2` with correct doc-cfgs, mark as unstable)
 - rust-lang/rust#163185 (properly decrement available_depth on cycles and provisional cache hits)
 - rust-lang/rust#163214 (revert r14 register names for arm)
 - rust-lang/rust#163226 (miri subtree update)
 - rust-lang/rust#163228 (Add regression test for trait predicate with escaping bounds)
 - rust-lang/rust#163234 (`rustc_dump_symbol_name`: add demangling information as a note instead)
@panstromek

panstromek commented Sep 29, 2026 •

Copy link
Copy Markdown
Contributor

perf triage:

Looks like this caused a small compile time regression for CTFE stress test in #163244. This can also be just noise (well, it definitely is at least partially), but some part of the increase persisted. Does that make sense for this PR? Do we know where this could come from?

@Zalathar

Zalathar commented Sep 29, 2026 •

Copy link
Copy Markdown
Member Author

This PR had an earlier perf run at #163143 (comment) that gave sub-threshold improvement in ctfe-stress, so it would be weird for that to suddenly turn into a measurable regression.

In terms of the actual changes, it would also be surprising for this PR to only affect one benchmark, as I believe it’s touching code that only runs once per session and doesn’t scale with input size.

@panstromek

Copy link
Copy Markdown
Contributor

Yea, this is probably just noise. As I went through the rest of the PRs in the rollup, I encountered the same regression again on ~4 of them.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

A-LLVM Area: Code generation parts specific to LLVM. Both correctness bugs and optimization-related issues. S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants