[llvm] [BOLT][DWARF][NFC] Add support for multithreading (PR #99068)
Sayhaan Siddiqui via llvm-commits
llvm-commits at lists.llvm.org
Tue Jul 16 11:04:15 PDT 2024
https://github.com/sayhaan updated https://github.com/llvm/llvm-project/pull/99068
>From e405e19129cf5972f6d651f0d189c1ffe560dfe7 Mon Sep 17 00:00:00 2001
From: Sayhaan Siddiqui <sayhaan at meta.com>
Date: Fri, 12 Jul 2024 17:12:51 -0700
Subject: [PATCH 1/2] [BOLT][DWARF][NFC] Add support for multithreading
Summary:
Test Plan:
Reviewers:
Subscribers:
Tasks:
Tags:
Differential Revision: https://phabricator.intern.facebook.com/D59708134
---
bolt/include/bolt/Core/DebugData.h | 9 -
bolt/include/bolt/Rewrite/DWARFRewriter.h | 5 -
bolt/lib/Core/DebugData.cpp | 7 -
bolt/lib/Rewrite/DWARFRewriter.cpp | 247 ++++++++++++----------
4 files changed, 136 insertions(+), 132 deletions(-)
diff --git a/bolt/include/bolt/Core/DebugData.h b/bolt/include/bolt/Core/DebugData.h
index 5935ffaa46af7..ebe684d7e821e 100644
--- a/bolt/include/bolt/Core/DebugData.h
+++ b/bolt/include/bolt/Core/DebugData.h
@@ -24,7 +24,6 @@
#include <cstdint>
#include <map>
#include <memory>
-#include <mutex>
#include <string>
#include <unordered_map>
#include <utility>
@@ -234,8 +233,6 @@ class DebugRangesSectionWriter {
std::unique_ptr<raw_svector_ostream> RangesStream;
- std::mutex WriterMutex;
-
/// Offset of an empty address ranges list.
static constexpr uint64_t EmptyRangesOffset{0};
@@ -325,8 +322,6 @@ class DebugARangesSectionWriter {
/// to that compile unit. Each interval is a pair
/// (first address, interval size).
CUAddressRangesType CUAddressRanges;
-
- std::mutex CUAddressRangesMutex;
};
using IndexAddressPair = std::pair<uint32_t, uint64_t>;
@@ -425,8 +420,6 @@ class DebugAddrWriter {
/// Address for the DWO CU associated with the address writer.
AddressForDWOCU Map;
uint8_t AddressByteSize;
- /// Mutex used for parallel processing of debug info.
- std::mutex WriterMutex;
std::unique_ptr<AddressSectionBuffer> Buffer;
std::unique_ptr<raw_svector_ostream> AddressStream;
/// Used to track sections that were not modified so that they can be re-used.
@@ -535,8 +528,6 @@ class DebugStrWriter {
void initialize();
private:
- /// Mutex used for parallel processing of debug info.
- std::mutex WriterMutex;
/// Creates internal data structures.
void create();
std::unique_ptr<DebugStrBufferVector> StrBuffer;
diff --git a/bolt/include/bolt/Rewrite/DWARFRewriter.h b/bolt/include/bolt/Rewrite/DWARFRewriter.h
index abd18b56113b6..d6a71e9b02fbb 100644
--- a/bolt/include/bolt/Rewrite/DWARFRewriter.h
+++ b/bolt/include/bolt/Rewrite/DWARFRewriter.h
@@ -20,7 +20,6 @@
#include "llvm/Support/ToolOutputFile.h"
#include <cstdint>
#include <memory>
-#include <mutex>
#include <optional>
#include <unordered_map>
#include <vector>
@@ -52,8 +51,6 @@ class DWARFRewriter {
private:
BinaryContext &BC;
- std::mutex DWARFRewriterMutex;
-
/// Stores and serializes information that will be put into the
/// .debug_ranges DWARF section.
std::unique_ptr<DebugRangesSectionWriter> LegacyRangesSectionWriter;
@@ -93,8 +90,6 @@ class DWARFRewriter {
std::unordered_map<uint64_t, std::unique_ptr<DebugAddrWriter>>
AddressWritersByCU;
- std::mutex LocListDebugInfoPatchesMutex;
-
/// Dwo id specific its RangesBase.
std::unordered_map<uint64_t, uint64_t> DwoRangesBase;
diff --git a/bolt/lib/Core/DebugData.cpp b/bolt/lib/Core/DebugData.cpp
index 002f58c474346..c8a50f787e7e9 100644
--- a/bolt/lib/Core/DebugData.cpp
+++ b/bolt/lib/Core/DebugData.cpp
@@ -167,7 +167,6 @@ uint64_t DebugRangesSectionWriter::addRanges(DebugAddressRangesVector &Ranges) {
// Reading the SectionOffset and updating it should be atomic to guarantee
// unique and correct offsets in patches.
- std::lock_guard<std::mutex> Lock(WriterMutex);
const uint32_t EntryOffset = RangesBuffer->size();
writeAddressRanges(*RangesStream.get(), Ranges);
@@ -175,7 +174,6 @@ uint64_t DebugRangesSectionWriter::addRanges(DebugAddressRangesVector &Ranges) {
}
uint64_t DebugRangesSectionWriter::getSectionOffset() {
- std::lock_guard<std::mutex> Lock(WriterMutex);
return RangesBuffer->size();
}
@@ -276,8 +274,6 @@ static bool emitWithBase(raw_ostream &OS, const DebugVector &Entries,
uint64_t
DebugRangeListsSectionWriter::addRanges(DebugAddressRangesVector &Ranges) {
- std::lock_guard<std::mutex> Lock(WriterMutex);
-
RangeEntries.push_back(CurrentOffset);
std::sort(
Ranges.begin(), Ranges.end(),
@@ -338,7 +334,6 @@ void DebugRangeListsSectionWriter::initSection(DWARFUnit &Unit) {
void DebugARangesSectionWriter::addCURanges(uint64_t CUOffset,
DebugAddressRangesVector &&Ranges) {
- std::lock_guard<std::mutex> Lock(CUAddressRangesMutex);
CUAddressRanges.emplace(CUOffset, std::move(Ranges));
}
@@ -404,7 +399,6 @@ void DebugAddrWriter::AddressForDWOCU::dump() {
dbgs() << Twine::utohexstr(Pair.second) << "\t" << Pair.first << "\n";
}
uint32_t DebugAddrWriter::getIndexFromAddress(uint64_t Address, DWARFUnit &CU) {
- std::lock_guard<std::mutex> Lock(WriterMutex);
auto Entry = Map.find(Address);
if (Entry == Map.end()) {
auto Index = Map.getNextIndex();
@@ -924,7 +918,6 @@ void DebugStrWriter::initialize() {
}
uint32_t DebugStrWriter::addString(StringRef Str) {
- std::lock_guard<std::mutex> Lock(WriterMutex);
if (StrBuffer->empty())
initialize();
auto Offset = StrBuffer->size();
diff --git a/bolt/lib/Rewrite/DWARFRewriter.cpp b/bolt/lib/Rewrite/DWARFRewriter.cpp
index 042c39a574561..b719669edfeae 100644
--- a/bolt/lib/Rewrite/DWARFRewriter.cpp
+++ b/bolt/lib/Rewrite/DWARFRewriter.cpp
@@ -40,6 +40,8 @@
#include "llvm/Support/Error.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/LEB128.h"
+#include "llvm/Support/Mutex.h"
+#include "llvm/Support/Parallel.h"
#include "llvm/Support/ThreadPool.h"
#include "llvm/Support/raw_ostream.h"
#include <algorithm>
@@ -629,47 +631,47 @@ void DWARFRewriter::updateDebugInfo() {
}
uint32_t CUIndex = 0;
- std::mutex AccessMutex;
// Needs to be invoked in the same order as CUs are processed.
auto createRangeLocListAddressWriters =
- [&](DWARFUnit &CU) -> DebugLocWriter * {
- std::lock_guard<std::mutex> Lock(AccessMutex);
- const uint16_t DwarfVersion = CU.getVersion();
- if (DwarfVersion >= 5) {
- auto AddrW = std::make_unique<DebugAddrWriterDwarf5>(
- &BC, CU.getAddressByteSize(), CU.getAddrOffsetSectionBase());
- RangeListsSectionWriter->setAddressWriter(AddrW.get());
- LocListWritersByCU[CUIndex] =
- std::make_unique<DebugLoclistWriter>(CU, DwarfVersion, false, *AddrW);
-
- if (std::optional<uint64_t> DWOId = CU.getDWOId()) {
- assert(RangeListsWritersByCU.count(*DWOId) == 0 &&
- "RangeLists writer for DWO unit already exists.");
- auto DWORangeListsSectionWriter =
- std::make_unique<DebugRangeListsSectionWriter>();
- DWORangeListsSectionWriter->initSection(CU);
- DWORangeListsSectionWriter->setAddressWriter(AddrW.get());
- RangeListsWritersByCU[*DWOId] = std::move(DWORangeListsSectionWriter);
- }
- AddressWritersByCU[CU.getOffset()] = std::move(AddrW);
+ [&](DWARFUnit &CU,
+ llvm::DenseMap<uint64_t, unsigned long> &LocListWritersIndexByCU) {
+ const uint16_t DwarfVersion = CU.getVersion();
+ if (DwarfVersion >= 5) {
+ auto AddrW = std::make_unique<DebugAddrWriterDwarf5>(
+ &BC, CU.getAddressByteSize(), CU.getAddrOffsetSectionBase());
+ RangeListsSectionWriter->setAddressWriter(AddrW.get());
+ LocListWritersByCU[CUIndex] = std::make_unique<DebugLoclistWriter>(
+ CU, DwarfVersion, false, *AddrW);
+
+ if (std::optional<uint64_t> DWOId = CU.getDWOId()) {
+ assert(RangeListsWritersByCU.count(*DWOId) == 0 &&
+ "RangeLists writer for DWO unit already exists.");
+ auto DWORangeListsSectionWriter =
+ std::make_unique<DebugRangeListsSectionWriter>();
+ DWORangeListsSectionWriter->initSection(CU);
+ DWORangeListsSectionWriter->setAddressWriter(AddrW.get());
+ RangeListsWritersByCU[*DWOId] =
+ std::move(DWORangeListsSectionWriter);
+ }
+ AddressWritersByCU[CU.getOffset()] = std::move(AddrW);
- } else {
- auto AddrW =
- std::make_unique<DebugAddrWriter>(&BC, CU.getAddressByteSize());
- AddressWritersByCU[CU.getOffset()] = std::move(AddrW);
- LocListWritersByCU[CUIndex] = std::make_unique<DebugLocWriter>();
- if (std::optional<uint64_t> DWOId = CU.getDWOId()) {
- assert(LegacyRangesWritersByCU.count(*DWOId) == 0 &&
- "LegacyRangeLists writer for DWO unit already exists.");
- auto LegacyRangesSectionWriterByCU =
- std::make_unique<DebugRangesSectionWriter>();
- LegacyRangesSectionWriterByCU->initSection(CU);
- LegacyRangesWritersByCU[*DWOId] =
- std::move(LegacyRangesSectionWriterByCU);
- }
- }
- return LocListWritersByCU[CUIndex++].get();
- };
+ } else {
+ auto AddrW =
+ std::make_unique<DebugAddrWriter>(&BC, CU.getAddressByteSize());
+ AddressWritersByCU[CU.getOffset()] = std::move(AddrW);
+ LocListWritersByCU[CUIndex] = std::make_unique<DebugLocWriter>();
+ if (std::optional<uint64_t> DWOId = CU.getDWOId()) {
+ assert(LegacyRangesWritersByCU.count(*DWOId) == 0 &&
+ "LegacyRangeLists writer for DWO unit already exists.");
+ auto LegacyRangesSectionWriterByCU =
+ std::make_unique<DebugRangesSectionWriter>();
+ LegacyRangesSectionWriterByCU->initSection(CU);
+ LegacyRangesWritersByCU[*DWOId] =
+ std::move(LegacyRangesSectionWriterByCU);
+ }
+ }
+ LocListWritersIndexByCU[CU.getOffset()] = CUIndex++;
+ };
DWARF5AcceleratorTable DebugNamesTable(opts::CreateDebugNames, BC,
*StrWriter);
@@ -677,75 +679,77 @@ void DWARFRewriter::updateDebugInfo() {
DWPState State;
if (opts::WriteDWP)
initDWPState(State);
- auto processUnitDIE = [&](DWARFUnit *Unit, DIEBuilder *DIEBlder) {
- // Check if the unit is a skeleton and we need special updates for it and
- // its matching split/DWO CU.
+
+ auto processSplitCU = [&](DWARFUnit *Unit, DIEBuilder *DIEBlder,
+ std::optional<uint64_t> &RangesBase) {
std::optional<DWARFUnit *> SplitCU;
- std::optional<uint64_t> RangesBase;
std::optional<uint64_t> DWOId = Unit->getDWOId();
if (DWOId)
SplitCU = BC.getDWOCU(*DWOId);
- DebugLocWriter *DebugLocWriter = createRangeLocListAddressWriters(*Unit);
- DebugRangesSectionWriter *RangesSectionWriter =
- Unit->getVersion() >= 5 ? RangeListsSectionWriter.get()
- : LegacyRangesSectionWriter.get();
- DebugAddrWriter *AddressWriter =
- AddressWritersByCU[Unit->getOffset()].get();
- // Skipping CUs that failed to load.
- if (SplitCU) {
- DIEBuilder DWODIEBuilder(BC, &(*SplitCU)->getContext(), DebugNamesTable,
- Unit);
- DWODIEBuilder.buildDWOUnit(**SplitCU);
- std::string DWOName = "";
- std::optional<std::string> DwarfOutputPath =
- opts::DwarfOutputPath.empty()
- ? std::nullopt
- : std::optional<std::string>(opts::DwarfOutputPath.c_str());
- {
- std::lock_guard<std::mutex> Lock(AccessMutex);
- DWOName = DIEBlder->updateDWONameCompDir(
- *StrOffstsWriter, *StrWriter, *Unit, DwarfOutputPath, std::nullopt);
- }
- DebugStrOffsetsWriter DWOStrOffstsWriter(BC);
- DebugStrWriter DWOStrWriter((*SplitCU)->getContext(), true);
- DWODIEBuilder.updateDWONameCompDirForTypes(DWOStrOffstsWriter,
- DWOStrWriter, **SplitCU,
- DwarfOutputPath, DWOName);
- DebugLoclistWriter DebugLocDWoWriter(*Unit, Unit->getVersion(), true,
- *AddressWriter);
- DebugRangesSectionWriter *TempRangesSectionWriter = RangesSectionWriter;
- if (Unit->getVersion() >= 5) {
- TempRangesSectionWriter = RangeListsWritersByCU[*DWOId].get();
- } else {
- TempRangesSectionWriter = LegacyRangesWritersByCU[*DWOId].get();
- RangesBase = RangesSectionWriter->getSectionOffset();
- setDwoRangesBase(*DWOId, *RangesBase);
- }
-
- updateUnitDebugInfo(*(*SplitCU), DWODIEBuilder, DebugLocDWoWriter,
- *TempRangesSectionWriter, *AddressWriter);
- DebugLocDWoWriter.finalize(DWODIEBuilder,
- *DWODIEBuilder.getUnitDIEbyUnit(**SplitCU));
- if (Unit->getVersion() >= 5)
- TempRangesSectionWriter->finalizeSection();
-
- emitDWOBuilder(DWOName, DWODIEBuilder, *this, **SplitCU, *Unit, State,
- DebugLocDWoWriter, DWOStrOffstsWriter, DWOStrWriter,
- GDBIndexSection);
+ if (!SplitCU)
+ return;
+ DebugAddrWriter &AddressWriter =
+ *AddressWritersByCU[Unit->getOffset()].get();
+ DIEBuilder DWODIEBuilder(BC, &(*SplitCU)->getContext(), DebugNamesTable,
+ Unit);
+ DWODIEBuilder.buildDWOUnit(**SplitCU);
+ std::string DWOName = "";
+ std::optional<std::string> DwarfOutputPath =
+ opts::DwarfOutputPath.empty()
+ ? std::nullopt
+ : std::optional<std::string>(opts::DwarfOutputPath.c_str());
+ {
+ DWOName = DIEBlder->updateDWONameCompDir(
+ *StrOffstsWriter, *StrWriter, *Unit, DwarfOutputPath, std::nullopt);
}
+ DebugStrOffsetsWriter DWOStrOffstsWriter(BC);
+ DebugStrWriter DWOStrWriter((*SplitCU)->getContext(), true);
+ DWODIEBuilder.updateDWONameCompDirForTypes(
+ DWOStrOffstsWriter, DWOStrWriter, **SplitCU, DwarfOutputPath, DWOName);
+ DebugLoclistWriter DebugLocDWoWriter(*Unit, Unit->getVersion(), true,
+ AddressWriter);
+ DebugRangesSectionWriter *TempRangesSectionWriter;
+ if (Unit->getVersion() >= 5) {
+ TempRangesSectionWriter = RangeListsWritersByCU[*DWOId].get();
+ } else {
+ TempRangesSectionWriter = LegacyRangesWritersByCU[*DWOId].get();
+ RangesBase = Unit->getVersion() >= 5
+ ? RangeListsSectionWriter.get()->getSectionOffset()
+ : LegacyRangesSectionWriter.get()->getSectionOffset();
+ setDwoRangesBase(*DWOId, *RangesBase);
+ }
+
+ updateUnitDebugInfo(*(*SplitCU), DWODIEBuilder, DebugLocDWoWriter,
+ *TempRangesSectionWriter, AddressWriter);
+ DebugLocDWoWriter.finalize(DWODIEBuilder,
+ *DWODIEBuilder.getUnitDIEbyUnit(**SplitCU));
+ if (Unit->getVersion() >= 5)
+ TempRangesSectionWriter->finalizeSection();
+ emitDWOBuilder(DWOName, DWODIEBuilder, *this, **SplitCU, *Unit, State,
+ DebugLocDWoWriter, DWOStrOffstsWriter, DWOStrWriter,
+ GDBIndexSection);
+ };
+ auto processMainBinaryCU = [&](DWARFUnit *Unit, DIEBuilder *DIEBlder,
+ DebugLocWriter *DebugLocWriter,
+ std::optional<uint64_t> &RangesBase) {
+ DebugAddrWriter &AddressWriter =
+ *AddressWritersByCU[Unit->getOffset()].get();
+ DebugRangesSectionWriter &RangesSectionWriter =
+ Unit->getVersion() >= 5 ? *RangeListsSectionWriter.get()
+ : *LegacyRangesSectionWriter.get();
if (Unit->getVersion() >= 5) {
- RangesBase = RangesSectionWriter->getSectionOffset() +
+ RangesBase = RangesSectionWriter.getSectionOffset() +
getDWARF5RngListLocListHeaderSize();
- RangesSectionWriter->initSection(*Unit);
+ RangesSectionWriter.initSection(*Unit);
StrOffstsWriter->finalizeSection(*Unit, *DIEBlder);
}
- updateUnitDebugInfo(*Unit, *DIEBlder, *DebugLocWriter, *RangesSectionWriter,
- *AddressWriter, RangesBase);
+ updateUnitDebugInfo(*Unit, *DIEBlder, *DebugLocWriter, RangesSectionWriter,
+ AddressWriter, RangesBase);
DebugLocWriter->finalize(*DIEBlder, *DIEBlder->getUnitDIEbyUnit(*Unit));
if (Unit->getVersion() >= 5)
- RangesSectionWriter->finalizeSection();
+ RangesSectionWriter.finalizeSection();
};
DIEBuilder DIEBlder(BC, BC.DwCtx.get(), DebugNamesTable);
@@ -762,23 +766,45 @@ void DWARFRewriter::updateDebugInfo() {
const bool SingleThreadedMode =
opts::NoThreads || opts::DeterministicDebugInfo;
- if (!SingleThreadedMode)
- DIEBlder.buildCompileUnits();
- if (SingleThreadedMode) {
- CUPartitionVector PartVec = partitionCUs(*BC.DwCtx);
- for (std::vector<DWARFUnit *> &Vec : PartVec) {
- DIEBlder.buildCompileUnits(Vec);
- for (DWARFUnit *CU : DIEBlder.getProcessedCUs())
- processUnitDIE(CU, &DIEBlder);
- finalizeCompileUnits(DIEBlder, *Streamer, OffsetMap,
- DIEBlder.getProcessedCUs(), *FinalAddrWriter);
+ CUPartitionVector PartVec = partitionCUs(*BC.DwCtx);
+ for (std::vector<DWARFUnit *> &Vec : PartVec) {
+ DIEBlder.buildCompileUnits(Vec);
+ llvm::SmallVector<DWARFUnit *> CompileUnits(
+ std::begin(DIEBlder.getProcessedCUs()),
+ std::end(DIEBlder.getProcessedCUs()));
+ llvm::DenseMap<uint64_t, uint64_t> RangesBaseByCU;
+ llvm::DenseMap<uint64_t, uint64_t> LocListWritersIndexByCU;
+ if (SingleThreadedMode) {
+ for (DWARFUnit *CU : CompileUnits) {
+ createRangeLocListAddressWriters(*CU, LocListWritersIndexByCU);
+ std::optional<uint64_t> RangesBase;
+ processSplitCU(CU, &DIEBlder, RangesBase);
+ if (RangesBase)
+ RangesBaseByCU[CU->getOffset()] = *RangesBase;
+ }
+ } else {
+ ThreadPoolInterface &ThreadPool = ParallelUtilities::getThreadPool();
+ for (DWARFUnit *CU : CompileUnits) {
+ createRangeLocListAddressWriters(*CU, LocListWritersIndexByCU);
+ ThreadPool.async([&, CU] {
+ std::optional<uint64_t> RangesBase;
+ processSplitCU(CU, &DIEBlder, RangesBase);
+ if (RangesBase)
+ RangesBaseByCU[CU->getOffset()] = *RangesBase;
+ });
+ }
+ ThreadPool.wait();
}
- } else {
- // Update unit debug info in parallel
- ThreadPoolInterface &ThreadPool = ParallelUtilities::getThreadPool();
- for (std::unique_ptr<DWARFUnit> &CU : BC.DwCtx->compile_units())
- ThreadPool.async(processUnitDIE, CU.get(), &DIEBlder);
- ThreadPool.wait();
+ for (DWARFUnit *CU : CompileUnits) {
+ std::optional<uint64_t> RangesBase;
+ if (RangesBaseByCU.count(CU->getOffset()))
+ RangesBase = RangesBaseByCU[CU->getOffset()];
+ DebugLocWriter *DebugLocWriter =
+ LocListWritersByCU[LocListWritersIndexByCU[CU->getOffset()]].get();
+ processMainBinaryCU(CU, &DIEBlder, DebugLocWriter, RangesBase);
+ }
+ finalizeCompileUnits(DIEBlder, *Streamer, OffsetMap,
+ DIEBlder.getProcessedCUs(), *FinalAddrWriter);
}
DebugNamesTable.emitAccelTable();
@@ -1259,7 +1285,6 @@ void DWARFRewriter::updateUnitDebugInfo(
dwarf::Form Form = LowPCAttrInfo.getForm();
assert(Form != dwarf::DW_FORM_LLVM_addrx_offset &&
"DW_FORM_LLVM_addrx_offset is not supported");
- std::lock_guard<std::mutex> Lock(DWARFRewriterMutex);
if (Form == dwarf::DW_FORM_addrx ||
Form == dwarf::DW_FORM_GNU_addr_index) {
const uint32_t Index = AddressWriter.getIndexFromAddress(
>From 16c7c384ed5e71377a97f78f51f669d81d410329 Mon Sep 17 00:00:00 2001
From: Sayhaan Siddiqui <sayhaan at meta.com>
Date: Tue, 16 Jul 2024 11:04:00 -0700
Subject: [PATCH 2/2] Remove redundant header
---
bolt/lib/Rewrite/DWARFRewriter.cpp | 1 -
1 file changed, 1 deletion(-)
diff --git a/bolt/lib/Rewrite/DWARFRewriter.cpp b/bolt/lib/Rewrite/DWARFRewriter.cpp
index b719669edfeae..bb3c400f73a5f 100644
--- a/bolt/lib/Rewrite/DWARFRewriter.cpp
+++ b/bolt/lib/Rewrite/DWARFRewriter.cpp
@@ -40,7 +40,6 @@
#include "llvm/Support/Error.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/LEB128.h"
-#include "llvm/Support/Mutex.h"
#include "llvm/Support/Parallel.h"
#include "llvm/Support/ThreadPool.h"
#include "llvm/Support/raw_ostream.h"
More information about the llvm-commits
mailing list