-
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
Building with LTO should skip "compilation" #43212
Comments
Yes, this is one of the cases where MIR-only RLIBs would help. |
I'll think some more about this next week. Maybe there's something we can do already with the compiler's current capabilities. |
So this is not entirely true. The rlib's metadata also contains optimized LLVM bitcode and when building the main crate, this bitcode is linked into the main LLVM module for that crate. After all bitcode from all rlib dependencies is linked together into one humongous module, we let LLVM run another set of optimizations on it. This is what the LTO linker plugin would normally do. Consequently, the optimization passes for intermediate rlibs are not really "lost", only the codegen passes, which are not cheap but also generally not as expensive as the LLVM passes before. There is a different way of going about code generation and optimization for Rust code though. We call it MIR-only RLIBs and in this model we would generate neither LLVM IR nor machine code for RLIBs. Only when building an actual binary would the compiler instantiate the things from RLIB dependencies. Compiling RLIBs would be massively sped up in this model, however, building the binary would also be that much slower. So it's not entirely clear that this is a win in overall build times, especially if one is mostly working on leaf crates and doesn't have to rebuild intermediate RLIBs often. However, it's still possible that this is a win because right now we are not sharing instantiations of generic functions between crates, potentially asking the compiler to optimize the exact same code over and over again. In the MIR-only RLIB model, there would always only be one instance per leaf crate. Also, there's more room for dead code elimination because at the moment, when building an RLIB, the compiler has to assume that it will later be linked into a Rust Dylib which would export/instantiate a lot more things than an executable, staticlib, or cdylib. @glandium When building with LTO enabled, are you mostly interested in reducing the build times for Rust developers or rather scenarios where Rust code is largely unmodified between builds? |
I'm debating whether it makes sense to have kind of a "soft launch" for MIR-only RLIBs:
One would be able to opt into the new model in a backwards compatible way. What do you think, @alexcrichton, @brson? |
Sounds reasonable to me! |
I guess both, but it's hard to have it both ways. |
See #43211 for some horrorifying timings from doing LTO builds in Firefox.
Please correct me where I'm wrong, but here is my understanding of the situation wrt building with LTO (and more or less confirmed by @alexcrichton and @mbrubeck on irc):
In simplified and C/C++ terms, this is my understanding of what's happening:
test.c
that is built in a libtest library, and linked withfoo.c
into a foo binary.gcc -o test.o -c test.c -O3
that's the compiled code partgcc -o test.lto.o -c test.c -O3 -flto
that's the metadata used for LTOgcc-ar cr libtest.a test.lto.o test.o
gcc -o foo.lto.o -c foo.c -O3 -flto
gcc -o foo.o -c foo.c -O3
)gcc -flto -o foo foo.lto.o libtest.a
In the above, the fact is, if libtest.a only contained test.lto.o, the foo binary would still compile fine, because the compiled code is not used. Which means we've spent time generating that test.o for nothing.
Now, consider a crate like geckoservo, which, while it contains 3Kloc, you wouldn't expect to require the time it takes to build (it's well above a minute). @mbrubeck suggested that compiling the crate inlines a bunch of stuff. Which is probably what is happening. Except that seems completely irrelevant and wasted time, considering it will have to do it all again when linking the entire project.
FWIW, the -Ztime-passes output with last 1.20 nightly, for geckoservo looks like:
e.g. most of the time is in llvm module and codegen passes.
Cc: @froydnj @rillian
The text was updated successfully, but these errors were encountered: