diff options
author | Duncan P. N. Exon Smith <dexonsmith@apple.com> | 2014-07-28 21:19:41 +0000 |
---|---|---|
committer | Duncan P. N. Exon Smith <dexonsmith@apple.com> | 2014-07-28 21:19:41 +0000 |
commit | 1f66c856b54e32e6590d1333fc8a60d56979edb8 (patch) | |
tree | 768875d352946ca33ca6773c03aada1ebb4f3c24 /llvm/lib/Bitcode/Reader/BitcodeReader.cpp | |
parent | f59b735a80004aa951e6f5e250231eb4b6fb18c8 (diff) | |
download | llvm-1f66c856b54e32e6590d1333fc8a60d56979edb8.zip llvm-1f66c856b54e32e6590d1333fc8a60d56979edb8.tar.gz llvm-1f66c856b54e32e6590d1333fc8a60d56979edb8.tar.bz2 |
Bitcode: Serialize (and recover) use-list order
Predict and serialize use-list order in bitcode. This makes the option
`-preserve-bc-use-list-order` work *most* of the time, but this is still
experimental.
- Builds a full value-table up front in the writer, sets up a list of
use-list orders to write out, and discards the table. This is a
simpler first step than determining the order from the various
overlapping IDs of values on-the-fly.
- The shuffles stored in the use-list order list have an unnecessarily
large memory footprint.
- `blockaddress` expressions cause functions to be materialized
out-of-order. For now I've ignored this problem, so use-list orders
will be wrong for constants used by functions that have block
addresses taken. There are a couple of ways to fix this, but I
don't have a concrete plan yet.
- When materializing functions lazily, the use-lists for constants
will not be correct. This use case is out of scope: what should the
use-list order be, if it's incomplete?
This is part of PR5680.
llvm-svn: 214125
Diffstat (limited to 'llvm/lib/Bitcode/Reader/BitcodeReader.cpp')
-rw-r--r-- | llvm/lib/Bitcode/Reader/BitcodeReader.cpp | 43 |
1 files changed, 37 insertions, 6 deletions
diff --git a/llvm/lib/Bitcode/Reader/BitcodeReader.cpp b/llvm/lib/Bitcode/Reader/BitcodeReader.cpp index 47a3953..806a8a9 100644 --- a/llvm/lib/Bitcode/Reader/BitcodeReader.cpp +++ b/llvm/lib/Bitcode/Reader/BitcodeReader.cpp @@ -1620,9 +1620,8 @@ std::error_code BitcodeReader::ParseUseLists() { if (Stream.EnterSubBlock(bitc::USELIST_BLOCK_ID)) return Error(InvalidRecord); - SmallVector<uint64_t, 64> Record; - // Read all the records. + SmallVector<uint64_t, 64> Record; while (1) { BitstreamEntry Entry = Stream.advanceSkippingSubblocks(); @@ -1639,14 +1638,42 @@ std::error_code BitcodeReader::ParseUseLists() { // Read a use list record. Record.clear(); + bool IsBB = false; switch (Stream.readRecord(Entry.ID, Record)) { default: // Default behavior: unknown type. break; - case bitc::USELIST_CODE_ENTRY: { // USELIST_CODE_ENTRY: TBD. + case bitc::USELIST_CODE_BB: + IsBB = true; + // fallthrough + case bitc::USELIST_CODE_DEFAULT: { unsigned RecordLength = Record.size(); - if (RecordLength < 1) - return Error(InvalidRecord); - UseListRecords.push_back(Record); + if (RecordLength < 3) + // Records should have at least an ID and two indexes. + return Error(InvalidRecord); + unsigned ID = Record.back(); + Record.pop_back(); + + Value *V; + if (IsBB) { + assert(ID < FunctionBBs.size() && "Basic block not found"); + V = FunctionBBs[ID]; + } else + V = ValueList[ID]; + unsigned NumUses = 0; + SmallDenseMap<const Use *, unsigned, 16> Order; + for (const Use &U : V->uses()) { + if (NumUses > Record.size()) + break; + Order[&U] = Record[NumUses++]; + } + if (Order.size() != Record.size() || NumUses > Record.size()) + // Mismatches can happen if the functions are being materialized lazily + // (out-of-order), or a value has been upgraded. + break; + + V->sortUseList([&](const Use &L, const Use &R) { + return Order.lookup(&L) < Order.lookup(&R); + }); break; } } @@ -2298,6 +2325,10 @@ std::error_code BitcodeReader::ParseFunctionBody(Function *F) { if (std::error_code EC = ParseMetadata()) return EC; break; + case bitc::USELIST_BLOCK_ID: + if (std::error_code EC = ParseUseLists()) + return EC; + break; } continue; |