Run findSubprograms in preprocessDebugInfo in parallel

Summary:
While reading debug info the function findSubprograms
runs on each compilation unit. This diff parallelize that loop
reducing its runtime duration by 70%.

(cherry picked from FBD16362867)
This commit is contained in:
laith sakka 2019-07-17 20:54:53 -07:00 committed by Maksim Panchenko
parent b50500893d
commit 744a2417dd
2 changed files with 40 additions and 6 deletions

View File

@ -12,11 +12,12 @@
#include "BinaryContext.h"
#include "BinaryFunction.h"
#include "DataReader.h"
#include "ParallelUtilities.h"
#include "llvm/ADT/Twine.h"
#include "llvm/DebugInfo/DWARF/DWARFFormValue.h"
#include "llvm/DebugInfo/DWARF/DWARFUnit.h"
#include "llvm/MC/MCAssembler.h"
#include "llvm/MC/MCAsmLayout.h"
#include "llvm/MC/MCAssembler.h"
#include "llvm/MC/MCContext.h"
#include "llvm/MC/MCELFStreamer.h"
#include "llvm/MC/MCObjectStreamer.h"
@ -1101,7 +1102,7 @@ void findSubprograms(const DWARFDie DIE,
if (DIE.getLowAndHighPC(LowPC, HighPC, SectionIndex)) {
auto It = BinaryFunctions.find(LowPC);
if (It != BinaryFunctions.end()) {
It->second.addSubprogramDIE(DIE);
It->second.addSubprogramDIE(DIE);
} else {
// The function must have been optimized away by GC.
}
@ -1110,7 +1111,7 @@ void findSubprograms(const DWARFDie DIE,
for (const auto Range : DIE.getAddressRanges()) {
auto It = BinaryFunctions.find(Range.LowPC);
if (It != BinaryFunctions.end()) {
It->second.addSubprogramDIE(DIE);
It->second.addSubprogramDIE(DIE);
}
}
}
@ -1198,8 +1199,39 @@ void BinaryContext::preprocessDebugInfo() {
// For each CU, iterate over its children DIEs and match subprogram DIEs to
// BinaryFunctions.
for (auto &CU : DwCtx->compile_units()) {
findSubprograms(CU->getUnitDIE(false), BinaryFunctions);
// Run findSubprograms on a range of compilation units
auto processBlock = [&](auto BlockBegin, auto BlockEnd) {
for (auto It = BlockBegin; It != BlockEnd; ++It) {
findSubprograms((*It)->getUnitDIE(false), BinaryFunctions);
}
};
if (opts::NoThreads) {
processBlock(DwCtx->compile_units().begin(), DwCtx->compile_units().end());
} else {
auto &ThreadPool = ParallelUtilities::getThreadPool();
// Divide compilation units uniformally into tasks.
unsigned BlockCost =
DwCtx->getNumCompileUnits() / (opts::TaskCount * opts::ThreadCount);
if (BlockCost == 0)
BlockCost = 1;
auto BlockBegin = DwCtx->compile_units().begin();
unsigned CurrentCost = 0;
for (auto It = DwCtx->compile_units().begin();
It != DwCtx->compile_units().end(); It++) {
CurrentCost++;
if (CurrentCost >= BlockCost) {
ThreadPool.async(processBlock, BlockBegin, std::next(It));
BlockBegin = std::next(It);
CurrentCost = 0;
}
}
ThreadPool.async(processBlock, BlockBegin, DwCtx->compile_units().end());
ThreadPool.wait();
}
// Some functions may not have a corresponding subprogram DIE
@ -1236,7 +1268,7 @@ void BinaryContext::preprocessDebugInfo() {
}
#endif
}
}
}
void BinaryContext::printCFI(raw_ostream &OS, const MCCFIInstruction &Inst) {
uint32_t Operation = Inst.getOperation();

View File

@ -2186,6 +2186,8 @@ public:
/// Sets the associated .debug_info entry.
void addSubprogramDIE(const DWARFDie DIE) {
static std::mutex CriticalSectionMutex;
std::lock_guard<std::mutex> Lock(CriticalSectionMutex);
SubprogramDIEs.emplace_back(DIE);
if (!UnitLineTable.first) {
if (const auto *LineTable =