Skip to content

Commit 1e9b006

Browse files
committed
[BOLT] Speedup symbol table sort
Memoize SymbolRef::getAddress() for sorting symbol table entries by their address. Saves about 10 seconds of processing time on large binaries with over 2 million symbols. NFCI. Reviewed By: jobnoorman, Amir Differential Revision: https://reviews.llvm.org/D159524
1 parent 15c9376 commit 1e9b006

File tree

1 file changed

+49
-54
lines changed

1 file changed

+49
-54
lines changed

bolt/lib/Rewrite/RewriteInstance.cpp

Lines changed: 49 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -799,7 +799,12 @@ void RewriteInstance::discoverFileObjects() {
799799
}
800800

801801
// Sort symbols in the file by value. Ignore symbols from non-allocatable
802-
// sections.
802+
// sections. We memoize getAddress(), as it has rather high overhead.
803+
struct SymbolInfo {
804+
uint64_t Address;
805+
SymbolRef Symbol;
806+
};
807+
std::vector<SymbolInfo> SortedSymbols;
803808
auto isSymbolInMemory = [this](const SymbolRef &Sym) {
804809
if (cantFail(Sym.getType()) == SymbolRef::ST_File)
805810
return false;
@@ -810,37 +815,33 @@ void RewriteInstance::discoverFileObjects() {
810815
BinarySection Section(*BC, *cantFail(Sym.getSection()));
811816
return Section.isAllocatable();
812817
};
813-
std::vector<SymbolRef> SortedFileSymbols;
814-
llvm::copy_if(InputFile->symbols(), std::back_inserter(SortedFileSymbols),
815-
isSymbolInMemory);
816-
auto CompareSymbols = [this](const SymbolRef &A, const SymbolRef &B) {
817-
// Marker symbols have the highest precedence, while
818-
// SECTIONs have the lowest.
819-
auto AddressA = cantFail(A.getAddress());
820-
auto AddressB = cantFail(B.getAddress());
821-
if (AddressA != AddressB)
822-
return AddressA < AddressB;
823-
824-
bool AMarker = BC->isMarker(A);
825-
bool BMarker = BC->isMarker(B);
818+
for (const SymbolRef &Symbol : InputFile->symbols())
819+
if (isSymbolInMemory(Symbol))
820+
SortedSymbols.push_back({cantFail(Symbol.getAddress()), Symbol});
821+
822+
auto CompareSymbols = [this](const SymbolInfo &A, const SymbolInfo &B) {
823+
if (A.Address != B.Address)
824+
return A.Address < B.Address;
825+
826+
const bool AMarker = BC->isMarker(A.Symbol);
827+
const bool BMarker = BC->isMarker(B.Symbol);
826828
if (AMarker || BMarker) {
827829
return AMarker && !BMarker;
828830
}
829831

830-
auto AType = cantFail(A.getType());
831-
auto BType = cantFail(B.getType());
832+
const auto AType = cantFail(A.Symbol.getType());
833+
const auto BType = cantFail(B.Symbol.getType());
832834
if (AType == SymbolRef::ST_Function && BType != SymbolRef::ST_Function)
833835
return true;
834836
if (BType == SymbolRef::ST_Debug && AType != SymbolRef::ST_Debug)
835837
return true;
836838

837839
return false;
838840
};
841+
llvm::stable_sort(SortedSymbols, CompareSymbols);
839842

840-
llvm::stable_sort(SortedFileSymbols, CompareSymbols);
841-
842-
auto LastSymbol = SortedFileSymbols.end();
843-
if (!SortedFileSymbols.empty())
843+
auto LastSymbol = SortedSymbols.end();
844+
if (!SortedSymbols.empty())
844845
--LastSymbol;
845846

846847
// For aarch64, the ABI defines mapping symbols so we identify data in the
@@ -855,39 +856,34 @@ void RewriteInstance::discoverFileObjects() {
855856
};
856857

857858
std::vector<MarkerSym> SortedMarkerSymbols;
858-
auto addExtraDataMarkerPerSymbol =
859-
[this](const std::vector<SymbolRef> &SortedFileSymbols,
860-
std::vector<MarkerSym> &SortedMarkerSymbols) {
861-
bool IsData = false;
862-
uint64_t LastAddr = 0;
863-
for (auto Sym = SortedFileSymbols.begin();
864-
Sym < SortedFileSymbols.end(); ++Sym) {
865-
uint64_t Address = cantFail(Sym->getAddress());
866-
if (LastAddr == Address) // don't repeat markers
867-
continue;
859+
auto addExtraDataMarkerPerSymbol = [&]() {
860+
bool IsData = false;
861+
uint64_t LastAddr = 0;
862+
for (const auto &SymInfo : SortedSymbols) {
863+
if (LastAddr == SymInfo.Address) // don't repeat markers
864+
continue;
868865

869-
MarkerSymType MarkerType = BC->getMarkerType(*Sym);
870-
if (MarkerType != MarkerSymType::NONE) {
871-
SortedMarkerSymbols.push_back(MarkerSym{Address, MarkerType});
872-
LastAddr = Address;
873-
IsData = MarkerType == MarkerSymType::DATA;
874-
continue;
875-
}
866+
MarkerSymType MarkerType = BC->getMarkerType(SymInfo.Symbol);
867+
if (MarkerType != MarkerSymType::NONE) {
868+
SortedMarkerSymbols.push_back(MarkerSym{SymInfo.Address, MarkerType});
869+
LastAddr = SymInfo.Address;
870+
IsData = MarkerType == MarkerSymType::DATA;
871+
continue;
872+
}
876873

877-
if (IsData) {
878-
SortedMarkerSymbols.push_back(
879-
MarkerSym{cantFail(Sym->getAddress()), MarkerSymType::DATA});
880-
LastAddr = Address;
881-
}
882-
}
883-
};
874+
if (IsData) {
875+
SortedMarkerSymbols.push_back({SymInfo.Address, MarkerSymType::DATA});
876+
LastAddr = SymInfo.Address;
877+
}
878+
}
879+
};
884880

885881
if (BC->isAArch64() || BC->isRISCV()) {
886-
addExtraDataMarkerPerSymbol(SortedFileSymbols, SortedMarkerSymbols);
882+
addExtraDataMarkerPerSymbol();
887883
LastSymbol = std::stable_partition(
888-
SortedFileSymbols.begin(), SortedFileSymbols.end(),
889-
[this](const SymbolRef &Symbol) { return !BC->isMarker(Symbol); });
890-
if (!SortedFileSymbols.empty())
884+
SortedSymbols.begin(), SortedSymbols.end(),
885+
[this](const SymbolInfo &S) { return !BC->isMarker(S.Symbol); });
886+
if (!SortedSymbols.empty())
891887
--LastSymbol;
892888
}
893889

@@ -897,12 +893,11 @@ void RewriteInstance::discoverFileObjects() {
897893
// Regex object for matching cold fragments.
898894
Regex ColdFragment(".*\\.cold(\\.[0-9]+)?");
899895

900-
const auto SortedSymbolsEnd = LastSymbol == SortedFileSymbols.end()
901-
? LastSymbol
902-
: std::next(LastSymbol);
903-
for (auto ISym = SortedFileSymbols.begin(); ISym != SortedSymbolsEnd;
904-
++ISym) {
905-
const SymbolRef &Symbol = *ISym;
896+
const auto SortedSymbolsEnd =
897+
LastSymbol == SortedSymbols.end() ? LastSymbol : std::next(LastSymbol);
898+
for (auto Iter = SortedSymbols.begin(); Iter != SortedSymbolsEnd; ++Iter) {
899+
const SymbolRef &Symbol = Iter->Symbol;
900+
906901
// Keep undefined symbols for pretty printing?
907902
if (cantFail(Symbol.getFlags()) & SymbolRef::SF_Undefined)
908903
continue;

0 commit comments

Comments
 (0)