-
Notifications
You must be signed in to change notification settings - Fork 12.7k
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
Store LLVM bitcode in object files, not compressed #71528
Conversation
(rust_highfive has picked a reviewer for you, use r? to override) |
|
As an extra note, I've tested this on Windows/mac/linux and confirmed that where bytecode sections previously appeared they're now all gone by default. Additionally I've tested that the builders which originally failed on #70458 pass with this implementation. |
Nit: I'm not sure why the option name changed since it was approved in #70458. |
I'm not really sure, most of this bytecode embedding stuff has been driven by demand and it's hard to predict future demands. It's also not on stable yet, so if we want to switch up the name that's also fine. Given the fall out in #70458 though I would personally prefer to leave refactorings/etc to a future PR to make sure this actually can land first (and doesn't need to be backed out) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for doing this!
#70458 had a commit "Don't copy bytecode files into the incr. comp. cache." I think that could be applied here?
Can the -Zembed-bitcode
flag be removed now? Perhaps in a follow-up?
13852a7
to
ae4ebb0
Compare
Ah yeah I saw the extra patch, although I'm personally not very familiar with it. I was also hoping that given the hiccups we saw earlier we probably don't want to design too much around this until we're more sure that it works. WDYT about landing this first, making sure it doesn't wildly break everyone on nightly, and then we can land some cleanups which this unlocks? |
ae4ebb0
to
8dfceec
Compare
r? @nnethercote |
@@ -129,8 +129,8 @@ impl<'a> ArchiveBuilder<'a> for LlvmArchiveBuilder<'a> { | |||
let obj_start = name.to_owned(); | |||
|
|||
self.add_archive(rlib, move |fname: &str| { | |||
// Ignore bytecode/metadata files, no matter the name. | |||
if fname.ends_with(RLIB_BYTECODE_EXTENSION) || fname == METADATA_FILENAME { | |||
// Ignore metadata files, no matter the name. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
// Ignore metadata files, no matter the name. | |
// Ignore metadata files |
@@ -1829,7 +1811,7 @@ fn add_upstream_rust_crates<'a, B: ArchiveBuilder<'a>>( | |||
|
|||
let mut any_objects = false; | |||
for f in archive.src_files() { | |||
if f.ends_with(RLIB_BYTECODE_EXTENSION) || f == METADATA_FILENAME { | |||
if f == METADATA_FILENAME { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yay, one less reason to rewrite rlibs every time we link. I wonder if there is a way for the linker to skip the metadata file without having to remove it from the archive.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That is not true, rlibs are already passed directly to the linker. Only in situations like LTO where we want to remove object code or we're doing something -force_load
do we remove things from rlibs.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Missed the return above.
Sounds good. That way we can also see if the extra patch has any measurable perf impact. I will review in a bit. |
One more thing: |
da0af77
to
95fd968
Compare
Ok updated! |
Follow-ups required:
@bors r+ |
📌 Commit 95fd968d9c95e1e5d872f2f0d5378f38ff658f86 has been approved by |
@bors p=1 Because follow-ups to beta will be necessary if this lands successfully. |
☀️ Test successful - checks-azure |
📣 Toolstate changed by #71528! Tested on commit 1357af3. 🎉 rustc-dev-guide on linux: test-fail → test-pass (cc @JohnTitor @amanjeev @spastorino @mark-i-m). |
Tested on commit rust-lang/rust@1357af3. Direct link to PR: <rust-lang/rust#71528> 🎉 rustc-dev-guide on linux: test-fail → test-pass (cc @JohnTitor @amanjeev @spastorino @mark-i-m).
This commit finishes work first pioneered in rust-lang#70458 and started in rust-lang#71528. The `-C bitcode-in-rlib` option, which has not yet reached stable, is renamed to `-C embed-bitcode` since that more accurately reflects what it does now anyway. Various tests and such are updated along the way as well. This'll also need to be backported to the beta channel to ensure we don't accidentally stabilize `-Cbitcode-in-rlib` as well.
…thercote Rename `bitcode-in-rlib` option to `embed-bitcode` This commit finishes work first pioneered in rust-lang#70458 and started in rust-lang#71528. The `-C bitcode-in-rlib` option, which has not yet reached stable, is renamed to `-C embed-bitcode` since that more accurately reflects what it does now anyway. Various tests and such are updated along the way as well. This'll also need to be backported to the beta channel to ensure we don't accidentally stabilize `-Cbitcode-in-rlib` as well.
…nethercote Don't copy bytecode files into the incr. comp. cache. It's no longer necessary now that bitcode is embedded into object files. This change meant that `WorkProductFileKind::Bytecode` is no longer necessary, which means that type is no longer necessary, which allowed several places in the code to become simpler. This commit was written by @nnethercote in rust-lang#70458 but that didn't land. In the meantime though we managed to land it in rust-lang#71528 and that doesn't seem to be causing too many fires, so I'm re-sending this patch!
This commit updates Cargo's implementation of LTO builds to do less work and hopefully be faster when doing a cold build. Additionaly this should save space on disk! The general idea is that the compiler does not need object files if it's only going to perform LTO with some artifacts. In this case all rustc needs to do is load bitcode from dependencies. This means that if you're doing an LTO build generating object code for intermediate dependencies is just wasted time! Here Cargo is updated with more intrusive knowledge about LTO. Cargo will now analyze the dependency graph to figure out which crates are being compiled with LTO, and then it will figure out which dependencies only need to have bitcode in them. Pure-bitcode artifacts are emitted with the `-Clinker-plugin-lto` flag. Some artifacts are still used in multiple scenarios (such as those shared between build scripts and final artifacts), so those are not compiled with `-Clinker-plugin-lto` since the linker is not guaranteed to know how to perform LTO. This functionality was recently implemented in rust-lang/rust#71528 where rustc is now capable of reading bitcode from `-Clinker-plugin-lto` rlibs. Previously rustc would only read its own format of bitcode, but this has now been extended! This support is now on nightly, hence this PR.
Don't force rustc to do codegen for LTO builds This commit updates Cargo's implementation of LTO builds to do less work and hopefully be faster when doing a cold build. Additionaly this should save space on disk! The general idea is that the compiler does not need object files if it's only going to perform LTO with some artifacts. In this case all rustc needs to do is load bitcode from dependencies. This means that if you're doing an LTO build generating object code for intermediate dependencies is just wasted time! Here Cargo is updated with more intrusive knowledge about LTO. Cargo will now analyze the dependency graph to figure out which crates are being compiled with LTO, and then it will figure out which dependencies only need to have bitcode in them. Pure-bitcode artifacts are emitted with the `-Clinker-plugin-lto` flag. Some artifacts are still used in multiple scenarios (such as those shared between build scripts and final artifacts), so those are not compiled with `-Clinker-plugin-lto` since the linker is not guaranteed to know how to perform LTO. This functionality was recently implemented in rust-lang/rust#71528 where rustc is now capable of reading bitcode from `-Clinker-plugin-lto` rlibs. Previously rustc would only read its own format of bitcode, but this has now been extended! This support is now on nightly, hence this PR.
This commit is an attempted resurrection of #70458 where LLVM bitcode
emitted by rustc into rlibs is stored into object file sections rather
than in a separate file. The main rationale for doing this is that when
rustc emits bitcode it will no longer use a custom compression scheme
which makes it both easier to interoperate with existing tools and also
cuts down on compile time since this compression isn't happening.
The blocker for this in #70458 turned out to be that native linkers
didn't handle the new sections well, causing the sections to either
trigger bugs in the linker or actually end up in the final linked
artifact. This commit attempts to address these issues by ensuring that
native linkers ignore the new sections by inserting custom flags with
module-level inline assembly.
Note that this does not currently change the API of the compiler at all.
The pre-existing
-C bitcode-in-rlib
flag is co-opted to indicatewhether the bitcode should be present in the object file or not.
Finally, note that an important consequence of this commit, which is also
one of its primary purposes, is to enable rustc's
-Clto
bitcodeloading to load rlibs produced with
-Clinker-plugin-lto
. The goal hereis that when you're building with LTO Cargo will tell rustc to skip
codegen of all intermediate crates and only generate LLVM IR. Today
rustc will generate both object code and LLVM IR, but the object code is
later simply thrown away, wastefully.