Skip to content

Commit

Permalink
[tablegen] Improve performance of -gen-register-info by replacing bar…
Browse files Browse the repository at this point in the history
…ely-necessary std::map with a sorted vector

Summary:
This particular map is hardly ever queried and has a phased usage pattern (insert,
iterate, query, insert, iterate) so it's a good candidate for a sorted vector and
std::lower_bound.

This significantly reduces the run time of runTargetDesc() in some circumstances.
One llvm-tblgen invocation in my build improves the time spent in runTargetDesc()
from 9.86s down to 0.80s (~92%) without changing the output. The same invocation
also has 2GB less allocation churn.

Reviewers: bogner, rtereshin, aditya_nandakumar, volkan

Reviewed By: rtereshin

Subscribers: mgrang, dexonsmith, llvm-commits

Differential Revision: https://reviews.llvm.org/D50272

llvm-svn: 339208
  • Loading branch information
dsandersllvm committed Aug 8, 2018
1 parent 749e828 commit 944fbb1
Show file tree
Hide file tree
Showing 2 changed files with 64 additions and 11 deletions.
13 changes: 13 additions & 0 deletions llvm/include/llvm/ADT/STLExtras.h
Expand Up @@ -824,6 +824,19 @@ struct less_second {
}
};

/// \brief Function object to apply a binary function to the first component of
/// a std::pair.
template<typename FuncTy>
struct on_first {
FuncTy func;

template <typename T>
auto operator()(const T &lhs, const T &rhs) const
-> decltype(func(lhs.first, rhs.first)) {
return func(lhs.first, rhs.first);
}
};

// A subset of N3658. More stuff can be added as-needed.

/// Represents a compile-time sequence of integers.
Expand Down
62 changes: 51 additions & 11 deletions llvm/utils/TableGen/RegisterInfoEmitter.cpp
Expand Up @@ -340,30 +340,56 @@ EmitRegUnitPressure(raw_ostream &OS, const CodeGenRegBank &RegBank,
<< "}\n\n";
}

using DwarfRegNumsMapPair = std::pair<Record*, std::vector<int64_t>>;
using DwarfRegNumsVecTy = std::vector<DwarfRegNumsMapPair>;

void finalizeDwarfRegNumsKeys(DwarfRegNumsVecTy &DwarfRegNums) {
// Sort and unique to get a map-like vector. We want the last assignment to
// match previous behaviour.
std::stable_sort(DwarfRegNums.begin(), DwarfRegNums.end(),
on_first<LessRecordRegister>());
// Warn about duplicate assignments.
const Record *LastSeenReg = nullptr;
for (const auto &X : DwarfRegNums) {
const auto &Reg = X.first;
// The only way LessRecordRegister can return equal is if they're the same
// string. Use simple equality instead.
if (LastSeenReg && Reg->getName() == LastSeenReg->getName())
PrintWarning(Reg->getLoc(), Twine("DWARF numbers for register ") +
getQualifiedName(Reg) +
"specified multiple times");
LastSeenReg = Reg;
}
auto Last = std::unique(
DwarfRegNums.begin(), DwarfRegNums.end(),
[](const DwarfRegNumsMapPair &A, const DwarfRegNumsMapPair &B) {
return A.first->getName() == B.first->getName();
});
DwarfRegNums.erase(Last, DwarfRegNums.end());
}

void RegisterInfoEmitter::EmitRegMappingTables(
raw_ostream &OS, const std::deque<CodeGenRegister> &Regs, bool isCtor) {
// Collect all information about dwarf register numbers
typedef std::map<Record*, std::vector<int64_t>, LessRecordRegister> DwarfRegNumsMapTy;
DwarfRegNumsMapTy DwarfRegNums;
DwarfRegNumsVecTy DwarfRegNums;

// First, just pull all provided information to the map
unsigned maxLength = 0;
for (auto &RE : Regs) {
Record *Reg = RE.TheDef;
std::vector<int64_t> RegNums = Reg->getValueAsListOfInts("DwarfNumbers");
maxLength = std::max((size_t)maxLength, RegNums.size());
if (DwarfRegNums.count(Reg))
PrintWarning(Reg->getLoc(), Twine("DWARF numbers for register ") +
getQualifiedName(Reg) + "specified multiple times");
DwarfRegNums[Reg] = RegNums;
DwarfRegNums.emplace_back(Reg, std::move(RegNums));
}
finalizeDwarfRegNumsKeys(DwarfRegNums);

if (!maxLength)
return;

// Now we know maximal length of number list. Append -1's, where needed
for (DwarfRegNumsMapTy::iterator
I = DwarfRegNums.begin(), E = DwarfRegNums.end(); I != E; ++I)
for (DwarfRegNumsVecTy::iterator I = DwarfRegNums.begin(),
E = DwarfRegNums.end();
I != E; ++I)
for (unsigned i = I->second.size(), e = maxLength; i != e; ++i)
I->second.push_back(-1);

Expand All @@ -384,7 +410,7 @@ void RegisterInfoEmitter::EmitRegMappingTables(
// Store the mapping sorted by the LLVM reg num so lookup can be done
// with a binary search.
std::map<uint64_t, Record*> Dwarf2LMap;
for (DwarfRegNumsMapTy::iterator
for (DwarfRegNumsVecTy::iterator
I = DwarfRegNums.begin(), E = DwarfRegNums.end(); I != E; ++I) {
int DwarfRegNo = I->second[i];
if (DwarfRegNo < 0)
Expand Down Expand Up @@ -423,7 +449,21 @@ void RegisterInfoEmitter::EmitRegMappingTables(

DefInit *DI = cast<DefInit>(V->getValue());
Record *Alias = DI->getDef();
DwarfRegNums[Reg] = DwarfRegNums[Alias];
const auto &AliasIter =
std::lower_bound(DwarfRegNums.begin(), DwarfRegNums.end(), Alias,
[](const DwarfRegNumsMapPair &A, const Record *B) {
return LessRecordRegister()(A.first, B);
});
assert(AliasIter != DwarfRegNums.end() && AliasIter->first == Alias &&
"Expected Alias to be present in map");
const auto &RegIter =
std::lower_bound(DwarfRegNums.begin(), DwarfRegNums.end(), Reg,
[](const DwarfRegNumsMapPair &A, const Record *B) {
return LessRecordRegister()(A.first, B);
});
assert(RegIter != DwarfRegNums.end() && RegIter->first == Reg &&
"Expected Reg to be present in map");
RegIter->second = AliasIter->second;
}

// Emit information about the dwarf register numbers.
Expand All @@ -436,7 +476,7 @@ void RegisterInfoEmitter::EmitRegMappingTables(
OS << " = {\n";
// Store the mapping sorted by the Dwarf reg num so lookup can be done
// with a binary search.
for (DwarfRegNumsMapTy::iterator
for (DwarfRegNumsVecTy::iterator
I = DwarfRegNums.begin(), E = DwarfRegNums.end(); I != E; ++I) {
int RegNo = I->second[i];
if (RegNo == -1) // -1 is the default value, don't emit a mapping.
Expand Down

0 comments on commit 944fbb1

Please sign in to comment.