This is an archive of the discontinued LLVM Phabricator instance.

[ThinLTO] Add support for emitting minimized bitcode for thin link
ClosedPublic

Authored by tejohnson on Mar 16 2017, 5:39 AM.

Details

Summary

The cumulative size of the bitcode files for a very large application
can be huge, particularly with -g. In a distributed build environment,
all of these files must be sent to the remote build node that performs
the thin link step, and this can exceed size limits.

The thin link actually only needs the summary along with a bitcode
symbol table. Until we have a proper bitcode symbol table, simply
stripping the debug metadata results in significant size reduction.

Add support for an option to additionally emit minimized bitcode
modules, just for use in the thin link step, which for now just strips
all debug metadata. I plan to add a cc1 option so this can be invoked
easily during the compile step.

However, care must be taken to ensure that these minimized thin link
bitcode files produce the same index as with the original bitcode files,
as these original bitcode files will be used in the backends.

Specifically:

  1. The module hash used for caching is typically produced by hashing the

written bitcode, and we want to include the hash that would correspond
to the original bitcode file. This is because we want to ensure that
changes in the stripped portions affect caching. Added plumbing to emit
the same module hash in the minimized thin link bitcode file.

  1. The module paths in the index are constructed from the module ID of

each thin linked bitcode, and typically is automatically generated from
the input file path. This is the path used for finding the modules to
import from, and obviously we need this to point to the original bitcode
files. Added support (to gold-plugin, as well as llvm-lto and llvm-lto2
for testing) to supply a suffix replacement during the thin link, that
is used to override the identifier on the MemoryBufferRef constructed
from the loaded thin link bitcode file. The assumption is that the build
system can specify that the minimized bitcode file has a name that is
similar but just as a different suffix (e.g. out.thinlink.bc instead of
out.o).

Added various tests to ensure that we get identical index files out of
the thin link step.

Diff Detail

Repository
rL LLVM

Event Timeline

tejohnson created this revision.Mar 16 2017, 5:39 AM
pcc added inline comments.Mar 16 2017, 2:15 PM
lib/Transforms/IPO/ThinLTOBitcodeWriter.cpp
351 ↗(On Diff #91985)

Will this cause us to write uninitialized memory as the module hash for the full module?

tejohnson added inline comments.Mar 16 2017, 2:32 PM
lib/Transforms/IPO/ThinLTOBitcodeWriter.cpp
351 ↗(On Diff #91985)

Gah, I should have 0 initialized this above! Ditto for the other location in this file. Must be getting lucky in my tests. Will fix

tejohnson updated this revision to Diff 92073.Mar 16 2017, 3:17 PM

Fix uninitialized variables

I did some testing with this change. The cumulative size of the bitcode files that need to be sent to the remote node performing the thin link drops from 20G to 2.5G. I also did a sanity check that all 20K+ individual index files and .imports files produced when thin linking with the original .o files and with the minimized thin link files were identical (also tested here in the new gold test, but I wanted an additional sanity check).

mehdi_amini edited edge metadata.Mar 20 2017, 10:33 AM

I did some testing with this change. The cumulative size of the bitcode files that need to be sent to the remote node performing the thin link drops from 20G to 2.5G.

Neat!

pcc added inline comments.Mar 20 2017, 11:13 AM
lib/Bitcode/Writer/BitcodeWriter.cpp
3786 ↗(On Diff #92073)

I found it a little confusing that the behaviour is conditioned on ModHash having a specific value. I wonder whether something like this would be better?

if (GenerateHash) {
 // generate hash
 if (ModHash)
    // copy hash to ModHash
} else if (ModHash)
 // write out hash in ModHash
lib/Transforms/IPO/ThinLTOBitcodeWriter.cpp
262 ↗(On Diff #92073)

Do we also need to write the module to ThinLinkOS in this case?

test/Transforms/ThinLTOBitcodeWriter/split.ll
23 ↗(On Diff #92073)

Can we not expect the file contents to be the same, and compare them directly? (same for other test cases)

tools/llvm-lto/llvm-lto.cpp
120 ↗(On Diff #92073)

Do you really need to add support for this feature to llvm-lto and llvm-lto2? It seems that this is just performing a sed operation on the file names. Can you achieve the same result by copying the .thinlink.bc files over the .bc files in your test cases?

tejohnson added inline comments.Mar 20 2017, 12:58 PM
lib/Bitcode/Writer/BitcodeWriter.cpp
3786 ↗(On Diff #92073)

I like the idea of changing GenerateHash to guard just the computation of a new hash value. Will do.

lib/Transforms/IPO/ThinLTOBitcodeWriter.cpp
262 ↗(On Diff #92073)

That's a good question. I think it is simplest to emit it to the ThinLinkOS as well, will add that. In this case there is no summary index, and the thin link will produce a native .o file. But for simplicity in the build system where we want to be able to know what output files to expect, and how to feed those into the thin link action, yes, it would be best to emit that.

test/Transforms/ThinLTOBitcodeWriter/split.ll
23 ↗(On Diff #92073)

True, will do that instead.

tools/llvm-lto/llvm-lto.cpp
120 ↗(On Diff #92073)

Technically it isn't needed here, but I do need it in gold-plugin, and I was trying to mirror that in these tools. It is being tested in the new gold test I added, so maybe not. Should I go ahead and remove this from llvm-lto and llvm-lto2?

tejohnson updated this revision to Diff 92487.Mar 21 2017, 7:30 AM

Addressed review comments and added test for unsplittable case. Did not
remove llvm-lto/llvm-lto2 handling of suffix replacement since I wanted to
be able to simulate the handling that we need for the thin link (see my
response and question to your review comment).

pcc added inline comments.Mar 21 2017, 3:31 PM
lib/Transforms/IPO/ThinLTOBitcodeWriter.cpp
470 ↗(On Diff #92487)

It's a little odd that this takes a stream for one output and a path for the other. I think I would prefer both to be streams so that the client can handle any errors opening the thin link bitcode file.

tools/llvm-lto/llvm-lto.cpp
120 ↗(On Diff #92073)

I'd prefer to remove them. The tests aren't really testing anything other than the code in the testing tools, as opposed to the gold plugin tests which are presumably testing production code. If the distributed build functionality were a feature of lib/LTO we could test it via llvm-lto2, and from that perspective it could make some sense to leave the test code in llvm-lto2 only for a possible refactoring.

tejohnson marked 2 inline comments as done.Mar 22 2017, 9:42 AM
tejohnson updated this revision to Diff 92646.Mar 22 2017, 9:44 AM

Address review comments.

pcc accepted this revision.Mar 22 2017, 7:37 PM

LGTM

lib/Bitcode/Writer/BitcodeWriter.cpp
3802 ↗(On Diff #92646)

Unnecessary return statement.

This revision is now accepted and ready to land.Mar 22 2017, 7:37 PM
tejohnson marked an inline comment as done.Mar 23 2017, 12:59 PM
tejohnson updated this revision to Diff 92847.Mar 23 2017, 12:59 PM

Address last review comment

This revision was automatically updated to reflect the committed changes.