mirror of
https://github.com/RPCSX/llvm.git
synced 2024-12-01 07:30:31 +00:00
llvm-dwp: Improve performance (N^2 to amortized N) by using a MapVector instead of linear searches through a vector
Figured this would be a problem, but didn't want to jump the gun - large inputs demonstrate it pretty easily (mostly for type units, but might as well do the same for CUs too). A random sample 6m27s -> 27s change. Also, by checking this up-front for CUs (rather than when building the cu_index) we can probably provide better error messages (see FIXMEs), hopefully providing the name of the CUs rather than just their signature. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@261364 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
af4a98fed6
commit
ff94d6e4ff
@ -1,3 +1,4 @@
|
|||||||
|
#include "llvm/ADT/MapVector.h"
|
||||||
#include "llvm/ADT/STLExtras.h"
|
#include "llvm/ADT/STLExtras.h"
|
||||||
#include "llvm/ADT/StringSet.h"
|
#include "llvm/ADT/StringSet.h"
|
||||||
#include "llvm/CodeGen/AsmPrinter.h"
|
#include "llvm/CodeGen/AsmPrinter.h"
|
||||||
@ -24,8 +25,8 @@
|
|||||||
#include "llvm/Target/TargetMachine.h"
|
#include "llvm/Target/TargetMachine.h"
|
||||||
#include <list>
|
#include <list>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <unordered_set>
|
|
||||||
#include <system_error>
|
#include <system_error>
|
||||||
|
#include <unordered_set>
|
||||||
|
|
||||||
using namespace llvm;
|
using namespace llvm;
|
||||||
using namespace llvm::object;
|
using namespace llvm::object;
|
||||||
@ -136,27 +137,22 @@ static uint64_t getCUSignature(StringRef Abbrev, StringRef Info) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
struct UnitIndexEntry {
|
struct UnitIndexEntry {
|
||||||
uint64_t Signature;
|
|
||||||
DWARFUnitIndex::Entry::SectionContribution Contributions[8];
|
DWARFUnitIndex::Entry::SectionContribution Contributions[8];
|
||||||
};
|
};
|
||||||
|
|
||||||
static void addAllTypesFromDWP(MCStreamer &Out,
|
static void addAllTypesFromDWP(
|
||||||
std::vector<UnitIndexEntry> &TypeIndexEntries,
|
MCStreamer &Out, MapVector<uint64_t, UnitIndexEntry> &TypeIndexEntries,
|
||||||
const DWARFUnitIndex &TUIndex,
|
const DWARFUnitIndex &TUIndex, MCSection *OutputTypes, StringRef Types,
|
||||||
MCSection *OutputTypes, StringRef Types,
|
const UnitIndexEntry &TUEntry, uint32_t &TypesOffset) {
|
||||||
const UnitIndexEntry &TUEntry,
|
|
||||||
uint32_t &TypesOffset) {
|
|
||||||
Out.SwitchSection(OutputTypes);
|
Out.SwitchSection(OutputTypes);
|
||||||
for (const DWARFUnitIndex::Entry &E : TUIndex.getRows()) {
|
for (const DWARFUnitIndex::Entry &E : TUIndex.getRows()) {
|
||||||
auto *I = E.getOffsets();
|
auto *I = E.getOffsets();
|
||||||
if (!I)
|
if (!I)
|
||||||
continue;
|
continue;
|
||||||
if (any_of(TypeIndexEntries, [&](const UnitIndexEntry &OldEntry) {
|
auto P = TypeIndexEntries.insert(std::make_pair(E.getSignature(), TUEntry));
|
||||||
return OldEntry.Signature == E.getSignature();
|
if (!P.second)
|
||||||
}))
|
|
||||||
continue;
|
continue;
|
||||||
auto Entry = TUEntry;
|
auto &Entry = P.first->second;
|
||||||
Entry.Signature = E.getSignature();
|
|
||||||
// Zero out the debug_info contribution
|
// Zero out the debug_info contribution
|
||||||
Entry.Contributions[0] = {};
|
Entry.Contributions[0] = {};
|
||||||
for (auto Kind : TUIndex.getColumnKinds()) {
|
for (auto Kind : TUIndex.getColumnKinds()) {
|
||||||
@ -171,12 +167,11 @@ static void addAllTypesFromDWP(MCStreamer &Out,
|
|||||||
C.Length));
|
C.Length));
|
||||||
C.Offset = TypesOffset;
|
C.Offset = TypesOffset;
|
||||||
TypesOffset += C.Length;
|
TypesOffset += C.Length;
|
||||||
TypeIndexEntries.push_back(Entry);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void addAllTypes(MCStreamer &Out,
|
static void addAllTypes(MCStreamer &Out,
|
||||||
std::vector<UnitIndexEntry> &TypeIndexEntries,
|
MapVector<uint64_t, UnitIndexEntry> &TypeIndexEntries,
|
||||||
MCSection *OutputTypes, StringRef Types,
|
MCSection *OutputTypes, StringRef Types,
|
||||||
const UnitIndexEntry &CUEntry, uint32_t &TypesOffset) {
|
const UnitIndexEntry &CUEntry, uint32_t &TypesOffset) {
|
||||||
if (Types.empty())
|
if (Types.empty())
|
||||||
@ -198,34 +193,32 @@ static void addAllTypes(MCStreamer &Out,
|
|||||||
Data.getU16(&Offset); // Version
|
Data.getU16(&Offset); // Version
|
||||||
Data.getU32(&Offset); // Abbrev offset
|
Data.getU32(&Offset); // Abbrev offset
|
||||||
Data.getU8(&Offset); // Address size
|
Data.getU8(&Offset); // Address size
|
||||||
Entry.Signature = Data.getU64(&Offset);
|
auto Signature = Data.getU64(&Offset);
|
||||||
Offset = PrevOffset + C.Length;
|
Offset = PrevOffset + C.Length;
|
||||||
|
|
||||||
if (any_of(TypeIndexEntries, [&](const UnitIndexEntry &E) {
|
auto P = TypeIndexEntries.insert(std::make_pair(Signature, Entry));
|
||||||
return E.Signature == Entry.Signature;
|
if (!P.second)
|
||||||
}))
|
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
Out.EmitBytes(Types.substr(PrevOffset, C.Length));
|
Out.EmitBytes(Types.substr(PrevOffset, C.Length));
|
||||||
TypesOffset += C.Length;
|
TypesOffset += C.Length;
|
||||||
|
|
||||||
TypeIndexEntries.push_back(Entry);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
writeIndexTable(MCStreamer &Out, ArrayRef<unsigned> ContributionOffsets,
|
writeIndexTable(MCStreamer &Out, ArrayRef<unsigned> ContributionOffsets,
|
||||||
ArrayRef<UnitIndexEntry> IndexEntries,
|
const MapVector<uint64_t, UnitIndexEntry> &IndexEntries,
|
||||||
uint32_t DWARFUnitIndex::Entry::SectionContribution::*Field) {
|
uint32_t DWARFUnitIndex::Entry::SectionContribution::*Field) {
|
||||||
for (const auto &E : IndexEntries)
|
for (const auto &E : IndexEntries)
|
||||||
for (size_t i = 0; i != array_lengthof(E.Contributions); ++i)
|
for (size_t i = 0; i != array_lengthof(E.second.Contributions); ++i)
|
||||||
if (ContributionOffsets[i])
|
if (ContributionOffsets[i])
|
||||||
Out.EmitIntValue(E.Contributions[i].*Field, 4);
|
Out.EmitIntValue(E.second.Contributions[i].*Field, 4);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void writeIndex(MCStreamer &Out, MCSection *Section,
|
static void
|
||||||
ArrayRef<unsigned> ContributionOffsets,
|
writeIndex(MCStreamer &Out, MCSection *Section,
|
||||||
ArrayRef<UnitIndexEntry> IndexEntries) {
|
ArrayRef<unsigned> ContributionOffsets,
|
||||||
|
const MapVector<uint64_t, UnitIndexEntry> &IndexEntries) {
|
||||||
unsigned Columns = 0;
|
unsigned Columns = 0;
|
||||||
for (auto &C : ContributionOffsets)
|
for (auto &C : ContributionOffsets)
|
||||||
if (C)
|
if (C)
|
||||||
@ -233,15 +226,17 @@ static void writeIndex(MCStreamer &Out, MCSection *Section,
|
|||||||
|
|
||||||
std::vector<unsigned> Buckets(NextPowerOf2(3 * IndexEntries.size() / 2));
|
std::vector<unsigned> Buckets(NextPowerOf2(3 * IndexEntries.size() / 2));
|
||||||
uint64_t Mask = Buckets.size() - 1;
|
uint64_t Mask = Buckets.size() - 1;
|
||||||
for (size_t i = 0; i != IndexEntries.size(); ++i) {
|
size_t i = 0;
|
||||||
auto S = IndexEntries[i].Signature;
|
for (const auto &P : IndexEntries) {
|
||||||
|
auto S = P.first;
|
||||||
auto H = S & Mask;
|
auto H = S & Mask;
|
||||||
while (Buckets[H]) {
|
while (Buckets[H]) {
|
||||||
assert(S != IndexEntries[Buckets[H] - 1].Signature &&
|
assert(S != IndexEntries.begin()[Buckets[H] - 1].first &&
|
||||||
"Duplicate unit");
|
"Duplicate unit");
|
||||||
H = (H + (((S >> 32) & Mask) | 1)) % Buckets.size();
|
H = (H + (((S >> 32) & Mask) | 1)) % Buckets.size();
|
||||||
}
|
}
|
||||||
Buckets[H] = i + 1;
|
Buckets[H] = i + 1;
|
||||||
|
++i;
|
||||||
}
|
}
|
||||||
|
|
||||||
Out.SwitchSection(Section);
|
Out.SwitchSection(Section);
|
||||||
@ -252,7 +247,7 @@ static void writeIndex(MCStreamer &Out, MCSection *Section,
|
|||||||
|
|
||||||
// Write the signatures.
|
// Write the signatures.
|
||||||
for (const auto &I : Buckets)
|
for (const auto &I : Buckets)
|
||||||
Out.EmitIntValue(I ? IndexEntries[I - 1].Signature : 0, 8);
|
Out.EmitIntValue(I ? IndexEntries.begin()[I - 1].first : 0, 8);
|
||||||
|
|
||||||
// Write the indexes.
|
// Write the indexes.
|
||||||
for (const auto &I : Buckets)
|
for (const auto &I : Buckets)
|
||||||
@ -305,8 +300,8 @@ static std::error_code write(MCStreamer &Out, ArrayRef<std::string> Inputs) {
|
|||||||
{"debug_cu_index", {CUIndexSection, static_cast<DWARFSectionKind>(0)}},
|
{"debug_cu_index", {CUIndexSection, static_cast<DWARFSectionKind>(0)}},
|
||||||
{"debug_tu_index", {TUIndexSection, static_cast<DWARFSectionKind>(0)}}};
|
{"debug_tu_index", {TUIndexSection, static_cast<DWARFSectionKind>(0)}}};
|
||||||
|
|
||||||
std::vector<UnitIndexEntry> IndexEntries;
|
MapVector<uint64_t, UnitIndexEntry> IndexEntries;
|
||||||
std::vector<UnitIndexEntry> TypeIndexEntries;
|
MapVector<uint64_t, UnitIndexEntry> TypeIndexEntries;
|
||||||
|
|
||||||
StringMap<uint32_t> Strings;
|
StringMap<uint32_t> Strings;
|
||||||
uint32_t StringOffset = 0;
|
uint32_t StringOffset = 0;
|
||||||
@ -412,18 +407,19 @@ static std::error_code write(MCStreamer &Out, ArrayRef<std::string> Inputs) {
|
|||||||
return make_error_code(std::errc::invalid_argument);
|
return make_error_code(std::errc::invalid_argument);
|
||||||
|
|
||||||
for (const DWARFUnitIndex::Entry &E : CUIndex.getRows()) {
|
for (const DWARFUnitIndex::Entry &E : CUIndex.getRows()) {
|
||||||
auto NewEntry = CurEntry;
|
|
||||||
auto *I = E.getOffsets();
|
auto *I = E.getOffsets();
|
||||||
if (!I)
|
if (!I)
|
||||||
continue;
|
continue;
|
||||||
NewEntry.Signature = E.getSignature();
|
auto P =
|
||||||
|
IndexEntries.insert(std::make_pair(E.getSignature(), CurEntry));
|
||||||
|
// FIXME: Check P.second and error for duplicate CU signatures
|
||||||
|
auto &NewEntry = P.first->second;
|
||||||
for (auto Kind : CUIndex.getColumnKinds()) {
|
for (auto Kind : CUIndex.getColumnKinds()) {
|
||||||
auto &C = NewEntry.Contributions[Kind - DW_SECT_INFO];
|
auto &C = NewEntry.Contributions[Kind - DW_SECT_INFO];
|
||||||
C.Offset += I->Offset;
|
C.Offset += I->Offset;
|
||||||
C.Length = I->Length;
|
C.Length = I->Length;
|
||||||
++I;
|
++I;
|
||||||
}
|
}
|
||||||
IndexEntries.push_back(NewEntry);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!CurTypesSection.empty()) {
|
if (!CurTypesSection.empty()) {
|
||||||
@ -439,11 +435,11 @@ static std::error_code write(MCStreamer &Out, ArrayRef<std::string> Inputs) {
|
|||||||
ContributionOffsets[DW_SECT_TYPES - DW_SECT_INFO]);
|
ContributionOffsets[DW_SECT_TYPES - DW_SECT_INFO]);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
CurEntry.Signature = getCUSignature(AbbrevSection, InfoSection);
|
IndexEntries.insert(
|
||||||
|
std::make_pair(getCUSignature(AbbrevSection, InfoSection), CurEntry));
|
||||||
|
// FIXME: Check P.second and error for duplicate CU signatures
|
||||||
addAllTypes(Out, TypeIndexEntries, TypesSection, CurTypesSection,
|
addAllTypes(Out, TypeIndexEntries, TypesSection, CurTypesSection,
|
||||||
CurEntry, ContributionOffsets[DW_SECT_TYPES - DW_SECT_INFO]);
|
CurEntry, ContributionOffsets[DW_SECT_TYPES - DW_SECT_INFO]);
|
||||||
|
|
||||||
IndexEntries.push_back(CurEntry);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (auto Err = writeStringsAndOffsets(Out, Strings, StringOffset,
|
if (auto Err = writeStringsAndOffsets(Out, Strings, StringOffset,
|
||||||
|
Loading…
Reference in New Issue
Block a user