-
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
Add an option to omit LLVM bitcode from rlibs. #66598
Conversation
I originally tried disabling the compression of LLVM bitcode in rlibs. It gave a 1-5% speed-up for debug builds but increased rlib size by about 25%. @alexcrichton then observed that bitcode simply isn't necessary unless you are building with LTO. (And libstd is a special case.) He said if I implement a "no rlib bitcode" flag he could modify Cargo's invocations to use it where appropriate. I'm not 100% certain I've done everything correctly. In particular I left I measured a debug build of I also measured the speed of a debug build of the |
Because it's only needed when doing LTO, so including it all the time wastes time and disk space.
3cce33f
to
c808fbe
Compare
Local performance measurements are excellent. Here are instruction count results for "clean" debug and opt builds:
The wall-time improvements were not as high, but still good, up to 9% improvements. Unfortunately we can't do a CI perf run because the comparison requires changing the |
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.
Nice wins!
As proposed this is an instantly stable option, which means that I think we'll want to get buy-in from the compiler team before landing. As a mild amount of bikeshedding, how about -C rlib-bitcode=no
instead of -C no-rlib-bitcode
? That way if we ever wanted we'd have a way to to -C rlib-bitcode=uncompressed
or something like that.
Also can you add a test or two exercising this? It might be good to sanity check what the error message looks like for LTO as well, for example if you comiple an rlib without bitcode, and then attempt to LTO with it later, does rustc ICE or have an otherwise intelligible error message?
if need_crate_bitcode_for_rlib(sess) { | ||
modules_config.emit_bc_compressed = true; | ||
if !sess.opts.cg.no_rlib_bitcode { |
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.
Could this extra conditional be folded into the need_crate_bitcode_for_rlib
function? I think that would still work, although it'd be good to check.
I am happy to change the option name. I am also happy to write tests, but I need some help on that. What existing tests should I look at for guidance? Thanks. |
Oh, and how should I gain buy-in from the compiler team? |
For tests I think it'd be fine to add something in |
I would suggest referring to bitcode by its Bikeshedding aside, this is an impressive win, I'm a bit shocked we still had chunks this large of work that could be omitted (even if only in most cases, not all). |
Shouldn't this start as a |
Another idea I just had: since Cargo shouldn't care about LLVM being the backend, but rather is interested in controlling "does this That is, something like |
In general, I am very much for getting rid of LLVM bitcode in rlibs where possible! |
@@ -1222,6 +1222,8 @@ options! {CodegenOptions, CodegenSetter, basic_codegen_options, | |||
"compile the program with profiling instrumentation"), | |||
profile_use: Option<PathBuf> = (None, parse_opt_pathbuf, [TRACKED], | |||
"use the given `.profdata` file for profile-guided optimization"), | |||
no_rlib_bitcode: bool = (false, parse_bool, [TRACKED], | |||
"don't put LLVM bitcode in rlib files"), |
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.
Enabling this only requires the rlib itself to be rebuild, instead of throwing away the whole incr cache, right?
This might also interact with #64124. |
Before we go ahead and merge this I'd like to discuss a different approach: Clang handles LTO differently from So my proposal would be to make
I think it would be great if we followed Clang's model here in order to tap into existing toolchain support. It also does not waste space. And LLVM actually wants to do some things differently depending on whether a module is intended for being using with thin, fat, or no LTO. The only downsides I see are:
|
I'm definitely on board for your plan @michaelwoerister, that all sounds great to me. Cargo is paired with only one version of rustc, so we can handle any Cargo changes on our side of things. It may be necessary to do a small dance though to phase this in. For now I'd just focus on landing rustc changes and then we can fix any issues in Cargo if they arise. |
What about non cargo users of rustc? If I understand correctly you can currently compile using LTO by only compiling the executable using |
@michaelwoerister, the first two points of your proposal match something @alexcrichton and I had discussed on Zulip, which I was calling "bitcode XOR machine code". Your entire proposal sounds reasonable to me (a non-expert on this stuff). But it's also a much bigger change, and the next steps aren't clear to me, including who should work on this. (BTW, your "making libstd available to cross-language LTO" link is incorrect above; I'm not sure what the correct address should be.)
I'm not sure about the exact details and possibilities here. In general, I strongly suggest that the common case should be as optimized (in terms of speed and disk space) as possible. Which isn't currently the case -- non-LTO users have to endure the significant cost of adding bitcode even though they don't use it. |
(How) does @michaelwoerister's proposal impact having e.g. Cranelift as an alternative backend? |
When LTO is disabled nothing changes, as the bitcode wasn't used anyway. When LTO is enabled other backends can just ignore the fact and produce object files containing machine code like normally. In the worst case linking to rlibs generated by cg_llvm with LTO enabled is not possible. When using linker plugin LTO I think even that should work though. |
Yes, with my proposal one would already have to compile rlibs for use with LTO (like is the case with Clang).
The case where one forgets to compile RLIBs with @nnethercote I fixed the link. Off the top of my head, I'd say the next steps are:
Much of the infrastructure should already be in place. I'm not quite sure how to handle Rust dylibs. Probably make them "fat" by default. |
If I'm understanding you correctly, this doesn't sound "harmless" to me -- if I specify lto to Cargo/rustc, I would prefer that rustc or Cargo tell me that this isn't possible, rather than silently not perform it for some code in my dependency tree. |
If you go through Cargo then you wouldn't hit this problem because Cargo invokes |
This PR won't land. We should file a new issue for the new proposal. @michaelwoerister, could you do that? (I could do it, but I think you'll get the details more correct than I would.) |
I'll do that next week. |
Because it's only needed when doing LTO, so including it all the time
wastes time and disk space.
r? @michaelwoerister