Skip to content

Commit 3d30433

Browse files
run 'git merge main'
2 parents 9df09b3 + ccae7b4 commit 3d30433

File tree

641 files changed

+21181
-5652
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

641 files changed

+21181
-5652
lines changed

bolt/include/bolt/Core/BinaryContext.h

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
#include "bolt/RuntimeLibs/RuntimeLibrary.h"
2424
#include "llvm/ADT/AddressRanges.h"
2525
#include "llvm/ADT/ArrayRef.h"
26+
#include "llvm/ADT/EquivalenceClasses.h"
2627
#include "llvm/ADT/StringMap.h"
2728
#include "llvm/ADT/iterator.h"
2829
#include "llvm/BinaryFormat/Dwarf.h"
@@ -241,6 +242,10 @@ class BinaryContext {
241242
/// Function fragments to skip.
242243
std::unordered_set<BinaryFunction *> FragmentsToSkip;
243244

245+
/// Fragment equivalence classes to query belonging to the same "family" in
246+
/// presence of multiple fragments/multiple parents.
247+
EquivalenceClasses<const BinaryFunction *> FragmentClasses;
248+
244249
/// The runtime library.
245250
std::unique_ptr<RuntimeLibrary> RtLibrary;
246251

@@ -1032,7 +1037,15 @@ class BinaryContext {
10321037
/// fragment_name == parent_name.cold(.\d+)?
10331038
/// True if the Function is registered, false if the check failed.
10341039
bool registerFragment(BinaryFunction &TargetFunction,
1035-
BinaryFunction &Function) const;
1040+
BinaryFunction &Function);
1041+
1042+
/// Return true if two functions belong to the same "family": are fragments
1043+
/// of one another, or fragments of the same parent, or transitively fragment-
1044+
/// related.
1045+
bool areRelatedFragments(const BinaryFunction *LHS,
1046+
const BinaryFunction *RHS) const {
1047+
return FragmentClasses.isEquivalent(LHS, RHS);
1048+
}
10361049

10371050
/// Add interprocedural reference for \p Function to \p Address
10381051
void addInterproceduralReference(BinaryFunction *Function, uint64_t Address) {

bolt/include/bolt/Core/BinaryFunction.h

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1793,11 +1793,6 @@ class BinaryFunction {
17931793
return ParentFragments.contains(&Other);
17941794
}
17951795

1796-
/// Returns if this function is a parent of \p Other function.
1797-
bool isParentOf(const BinaryFunction &Other) const {
1798-
return Fragments.contains(&Other);
1799-
}
1800-
18011796
/// Return the child fragment form parent function
18021797
iterator_range<FragmentsSetTy::const_iterator> getFragments() const {
18031798
return iterator_range<FragmentsSetTy::const_iterator>(Fragments.begin(),
@@ -1807,11 +1802,6 @@ class BinaryFunction {
18071802
/// Return the parent function for split function fragments.
18081803
FragmentsSetTy *getParentFragments() { return &ParentFragments; }
18091804

1810-
/// Returns if this function is a parent or child of \p Other function.
1811-
bool isParentOrChildOf(const BinaryFunction &Other) const {
1812-
return isChildOf(Other) || isParentOf(Other);
1813-
}
1814-
18151805
/// Set the profile data for the number of times the function was called.
18161806
BinaryFunction &setExecutionCount(uint64_t Count) {
18171807
ExecutionCount = Count;

bolt/lib/Core/BinaryContext.cpp

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -646,7 +646,7 @@ bool BinaryContext::analyzeJumpTable(const uint64_t Address,
646646
const BinaryFunction *TargetBF = getBinaryFunctionContainingAddress(Value);
647647
const bool DoesBelongToFunction =
648648
BF.containsAddress(Value) ||
649-
(TargetBF && TargetBF->isParentOrChildOf(BF));
649+
(TargetBF && areRelatedFragments(TargetBF, &BF));
650650
if (!DoesBelongToFunction) {
651651
LLVM_DEBUG({
652652
if (!BF.containsAddress(Value)) {
@@ -839,9 +839,11 @@ BinaryContext::getOrCreateJumpTable(BinaryFunction &Function, uint64_t Address,
839839
assert(Address == JT->getAddress() && "unexpected non-empty jump table");
840840

841841
// Prevent associating a jump table to a specific fragment twice.
842-
// This simple check arises from the assumption: no more than 2 fragments.
843-
if (JT->Parents.size() == 1 && JT->Parents[0] != &Function) {
844-
assert(JT->Parents[0]->isParentOrChildOf(Function) &&
842+
if (!llvm::is_contained(JT->Parents, &Function)) {
843+
assert(llvm::all_of(JT->Parents,
844+
[&](const BinaryFunction *BF) {
845+
return areRelatedFragments(&Function, BF);
846+
}) &&
845847
"cannot re-use jump table of a different function");
846848
// Duplicate the entry for the parent function for easy access
847849
JT->Parents.push_back(&Function);
@@ -852,8 +854,8 @@ BinaryContext::getOrCreateJumpTable(BinaryFunction &Function, uint64_t Address,
852854
JT->print(this->outs());
853855
}
854856
Function.JumpTables.emplace(Address, JT);
855-
JT->Parents[0]->setHasIndirectTargetToSplitFragment(true);
856-
JT->Parents[1]->setHasIndirectTargetToSplitFragment(true);
857+
for (BinaryFunction *Parent : JT->Parents)
858+
Parent->setHasIndirectTargetToSplitFragment(true);
857859
}
858860

859861
bool IsJumpTableParent = false;
@@ -1209,12 +1211,13 @@ void BinaryContext::generateSymbolHashes() {
12091211
}
12101212

12111213
bool BinaryContext::registerFragment(BinaryFunction &TargetFunction,
1212-
BinaryFunction &Function) const {
1214+
BinaryFunction &Function) {
12131215
assert(TargetFunction.isFragment() && "TargetFunction must be a fragment");
12141216
if (TargetFunction.isChildOf(Function))
12151217
return true;
12161218
TargetFunction.addParentFragment(Function);
12171219
Function.addFragment(TargetFunction);
1220+
FragmentClasses.unionSets(&TargetFunction, &Function);
12181221
if (!HasRelocations) {
12191222
TargetFunction.setSimple(false);
12201223
Function.setSimple(false);
@@ -1336,7 +1339,7 @@ void BinaryContext::processInterproceduralReferences() {
13361339

13371340
if (TargetFunction) {
13381341
if (TargetFunction->isFragment() &&
1339-
!TargetFunction->isChildOf(Function)) {
1342+
!areRelatedFragments(TargetFunction, &Function)) {
13401343
this->errs()
13411344
<< "BOLT-WARNING: interprocedural reference between unrelated "
13421345
"fragments: "

bolt/lib/Core/Exceptions.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -207,7 +207,7 @@ Error BinaryFunction::parseLSDA(ArrayRef<uint8_t> LSDASectionData,
207207
"BOLT-ERROR: cannot find landing pad fragment");
208208
BC.addInterproceduralReference(this, Fragment->getAddress());
209209
BC.processInterproceduralReferences();
210-
assert(isParentOrChildOf(*Fragment) &&
210+
assert(BC.areRelatedFragments(this, Fragment) &&
211211
"BOLT-ERROR: cannot have landing pads in different functions");
212212
setHasIndirectTargetToSplitFragment(true);
213213
BC.addFragmentsToSkip(this);

bolt/lib/Profile/DataAggregator.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,7 @@ MaxSamples("max-samples",
8888
cl::cat(AggregatorCategory));
8989

9090
extern cl::opt<opts::ProfileFormatKind> ProfileFormat;
91+
extern cl::opt<bool> ProfileUsePseudoProbes;
9192
extern cl::opt<std::string> SaveProfile;
9293

9394
cl::opt<bool> ReadPreAggregated(
@@ -2298,7 +2299,8 @@ std::error_code DataAggregator::writeBATYAML(BinaryContext &BC,
22982299

22992300
yaml::bolt::BinaryProfile BP;
23002301

2301-
const MCPseudoProbeDecoder *PseudoProbeDecoder = BC.getPseudoProbeDecoder();
2302+
const MCPseudoProbeDecoder *PseudoProbeDecoder =
2303+
opts::ProfileUsePseudoProbes ? BC.getPseudoProbeDecoder() : nullptr;
23022304

23032305
// Fill out the header info.
23042306
BP.Header.Version = 1;

bolt/lib/Profile/YAMLProfileReader.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,11 @@ llvm::cl::opt<bool>
4949
llvm::cl::opt<bool> ProfileUseDFS("profile-use-dfs",
5050
cl::desc("use DFS order for YAML profile"),
5151
cl::Hidden, cl::cat(BoltOptCategory));
52+
53+
llvm::cl::opt<bool> ProfileUsePseudoProbes(
54+
"profile-use-pseudo-probes",
55+
cl::desc("Use pseudo probes for profile generation and matching"),
56+
cl::Hidden, cl::cat(BoltOptCategory));
5257
} // namespace opts
5358

5459
namespace llvm {

bolt/lib/Profile/YAMLProfileWriter.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222

2323
namespace opts {
2424
extern llvm::cl::opt<bool> ProfileUseDFS;
25+
extern llvm::cl::opt<bool> ProfileUsePseudoProbes;
2526
} // namespace opts
2627

2728
namespace llvm {
@@ -57,7 +58,8 @@ YAMLProfileWriter::convert(const BinaryFunction &BF, bool UseDFS,
5758
const BoltAddressTranslation *BAT) {
5859
yaml::bolt::BinaryFunctionProfile YamlBF;
5960
const BinaryContext &BC = BF.getBinaryContext();
60-
const MCPseudoProbeDecoder *PseudoProbeDecoder = BC.getPseudoProbeDecoder();
61+
const MCPseudoProbeDecoder *PseudoProbeDecoder =
62+
opts::ProfileUsePseudoProbes ? BC.getPseudoProbeDecoder() : nullptr;
6163

6264
const uint16_t LBRProfile = BF.getProfileFlags() & BinaryFunction::PF_LBR;
6365

bolt/lib/Rewrite/DWARFRewriter.cpp

Lines changed: 75 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -620,8 +620,8 @@ void DWARFRewriter::updateDebugInfo() {
620620
uint32_t CUIndex = 0;
621621
std::mutex AccessMutex;
622622
// Needs to be invoked in the same order as CUs are processed.
623-
auto createRangeLocListAddressWriters =
624-
[&](DWARFUnit &CU) -> DebugLocWriter * {
623+
llvm::DenseMap<uint64_t, uint64_t> LocListWritersIndexByCU;
624+
auto createRangeLocListAddressWriters = [&](DWARFUnit &CU) {
625625
std::lock_guard<std::mutex> Lock(AccessMutex);
626626
const uint16_t DwarfVersion = CU.getVersion();
627627
if (DwarfVersion >= 5) {
@@ -641,7 +641,6 @@ void DWARFRewriter::updateDebugInfo() {
641641
RangeListsWritersByCU[*DWOId] = std::move(DWORangeListsSectionWriter);
642642
}
643643
AddressWritersByCU[CU.getOffset()] = std::move(AddrW);
644-
645644
} else {
646645
auto AddrW =
647646
std::make_unique<DebugAddrWriter>(&BC, CU.getAddressByteSize());
@@ -657,7 +656,7 @@ void DWARFRewriter::updateDebugInfo() {
657656
std::move(LegacyRangesSectionWriterByCU);
658657
}
659658
}
660-
return LocListWritersByCU[CUIndex++].get();
659+
LocListWritersIndexByCU[CU.getOffset()] = CUIndex++;
661660
};
662661

663662
DWARF5AcceleratorTable DebugNamesTable(opts::CreateDebugNames, BC,
@@ -666,74 +665,62 @@ void DWARFRewriter::updateDebugInfo() {
666665
DWPState State;
667666
if (opts::WriteDWP)
668667
initDWPState(State);
669-
auto processUnitDIE = [&](DWARFUnit *Unit, DIEBuilder *DIEBlder) {
670-
// Check if the unit is a skeleton and we need special updates for it and
671-
// its matching split/DWO CU.
668+
auto processSplitCU = [&](DWARFUnit &Unit, DWARFUnit &SplitCU,
669+
DIEBuilder &DIEBlder,
670+
DebugRangesSectionWriter &TempRangesSectionWriter,
671+
DebugAddrWriter &AddressWriter,
672+
const std::string &DWOName,
673+
const std::optional<std::string> &DwarfOutputPath) {
674+
DIEBuilder DWODIEBuilder(BC, &(SplitCU).getContext(), DebugNamesTable,
675+
&Unit);
676+
DWODIEBuilder.buildDWOUnit(SplitCU);
677+
DebugStrOffsetsWriter DWOStrOffstsWriter(BC);
678+
DebugStrWriter DWOStrWriter((SplitCU).getContext(), true);
679+
DWODIEBuilder.updateDWONameCompDirForTypes(
680+
DWOStrOffstsWriter, DWOStrWriter, SplitCU, DwarfOutputPath, DWOName);
681+
DebugLoclistWriter DebugLocDWoWriter(Unit, Unit.getVersion(), true,
682+
AddressWriter);
683+
684+
updateUnitDebugInfo(SplitCU, DWODIEBuilder, DebugLocDWoWriter,
685+
TempRangesSectionWriter, AddressWriter);
686+
DebugLocDWoWriter.finalize(DWODIEBuilder,
687+
*DWODIEBuilder.getUnitDIEbyUnit(SplitCU));
688+
if (Unit.getVersion() >= 5)
689+
TempRangesSectionWriter.finalizeSection();
690+
691+
emitDWOBuilder(DWOName, DWODIEBuilder, *this, SplitCU, Unit, State,
692+
DebugLocDWoWriter, DWOStrOffstsWriter, DWOStrWriter,
693+
GDBIndexSection);
694+
};
695+
auto processMainBinaryCU = [&](DWARFUnit &Unit, DIEBuilder &DIEBlder) {
672696
std::optional<DWARFUnit *> SplitCU;
673697
std::optional<uint64_t> RangesBase;
674-
std::optional<uint64_t> DWOId = Unit->getDWOId();
698+
std::optional<uint64_t> DWOId = Unit.getDWOId();
675699
if (DWOId)
676700
SplitCU = BC.getDWOCU(*DWOId);
677-
DebugLocWriter *DebugLocWriter = createRangeLocListAddressWriters(*Unit);
678-
DebugRangesSectionWriter *RangesSectionWriter =
679-
Unit->getVersion() >= 5 ? RangeListsSectionWriter.get()
680-
: LegacyRangesSectionWriter.get();
681-
DebugAddrWriter *AddressWriter =
682-
AddressWritersByCU[Unit->getOffset()].get();
683-
// Skipping CUs that failed to load.
684-
if (SplitCU) {
685-
DIEBuilder DWODIEBuilder(BC, &(*SplitCU)->getContext(), DebugNamesTable,
686-
Unit);
687-
DWODIEBuilder.buildDWOUnit(**SplitCU);
688-
std::string DWOName = "";
689-
std::optional<std::string> DwarfOutputPath =
690-
opts::DwarfOutputPath.empty()
691-
? std::nullopt
692-
: std::optional<std::string>(opts::DwarfOutputPath.c_str());
693-
{
694-
std::lock_guard<std::mutex> Lock(AccessMutex);
695-
DWOName = DIEBlder->updateDWONameCompDir(
696-
*StrOffstsWriter, *StrWriter, *Unit, DwarfOutputPath, std::nullopt);
697-
}
698-
DebugStrOffsetsWriter DWOStrOffstsWriter(BC);
699-
DebugStrWriter DWOStrWriter((*SplitCU)->getContext(), true);
700-
DWODIEBuilder.updateDWONameCompDirForTypes(DWOStrOffstsWriter,
701-
DWOStrWriter, **SplitCU,
702-
DwarfOutputPath, DWOName);
703-
DebugLoclistWriter DebugLocDWoWriter(*Unit, Unit->getVersion(), true,
704-
*AddressWriter);
705-
DebugRangesSectionWriter *TempRangesSectionWriter = RangesSectionWriter;
706-
if (Unit->getVersion() >= 5) {
707-
TempRangesSectionWriter = RangeListsWritersByCU[*DWOId].get();
708-
} else {
709-
TempRangesSectionWriter = LegacyRangesWritersByCU[*DWOId].get();
710-
RangesBase = RangesSectionWriter->getSectionOffset();
711-
}
712-
713-
updateUnitDebugInfo(*(*SplitCU), DWODIEBuilder, DebugLocDWoWriter,
714-
*TempRangesSectionWriter, *AddressWriter);
715-
DebugLocDWoWriter.finalize(DWODIEBuilder,
716-
*DWODIEBuilder.getUnitDIEbyUnit(**SplitCU));
717-
if (Unit->getVersion() >= 5)
718-
TempRangesSectionWriter->finalizeSection();
719-
720-
emitDWOBuilder(DWOName, DWODIEBuilder, *this, **SplitCU, *Unit, State,
721-
DebugLocDWoWriter, DWOStrOffstsWriter, DWOStrWriter,
722-
GDBIndexSection);
723-
}
724-
725-
if (Unit->getVersion() >= 5) {
726-
RangesBase = RangesSectionWriter->getSectionOffset() +
701+
DebugLocWriter &DebugLocWriter =
702+
*LocListWritersByCU[LocListWritersIndexByCU[Unit.getOffset()]].get();
703+
DebugRangesSectionWriter &RangesSectionWriter =
704+
Unit.getVersion() >= 5 ? *RangeListsSectionWriter.get()
705+
: *LegacyRangesSectionWriter.get();
706+
DebugAddrWriter &AddressWriter =
707+
*AddressWritersByCU[Unit.getOffset()].get();
708+
if (Unit.getVersion() >= 5)
709+
RangeListsSectionWriter->setAddressWriter(&AddressWriter);
710+
if (Unit.getVersion() >= 5) {
711+
RangesBase = RangesSectionWriter.getSectionOffset() +
727712
getDWARF5RngListLocListHeaderSize();
728-
RangesSectionWriter->initSection(*Unit);
729-
StrOffstsWriter->finalizeSection(*Unit, *DIEBlder);
713+
RangesSectionWriter.initSection(Unit);
714+
StrOffstsWriter->finalizeSection(Unit, DIEBlder);
715+
} else if (SplitCU) {
716+
RangesBase = LegacyRangesSectionWriter.get()->getSectionOffset();
730717
}
731718

732-
updateUnitDebugInfo(*Unit, *DIEBlder, *DebugLocWriter, *RangesSectionWriter,
733-
*AddressWriter, RangesBase);
734-
DebugLocWriter->finalize(*DIEBlder, *DIEBlder->getUnitDIEbyUnit(*Unit));
735-
if (Unit->getVersion() >= 5)
736-
RangesSectionWriter->finalizeSection();
719+
updateUnitDebugInfo(Unit, DIEBlder, DebugLocWriter, RangesSectionWriter,
720+
AddressWriter, RangesBase);
721+
DebugLocWriter.finalize(DIEBlder, *DIEBlder.getUnitDIEbyUnit(Unit));
722+
if (Unit.getVersion() >= 5)
723+
RangesSectionWriter.finalizeSection();
737724
};
738725

739726
DIEBuilder DIEBlder(BC, BC.DwCtx.get(), DebugNamesTable);
@@ -751,8 +738,30 @@ void DWARFRewriter::updateDebugInfo() {
751738
CUPartitionVector PartVec = partitionCUs(*BC.DwCtx);
752739
for (std::vector<DWARFUnit *> &Vec : PartVec) {
753740
DIEBlder.buildCompileUnits(Vec);
741+
for (DWARFUnit *CU : DIEBlder.getProcessedCUs()) {
742+
createRangeLocListAddressWriters(*CU);
743+
std::optional<DWARFUnit *> SplitCU;
744+
std::optional<uint64_t> DWOId = CU->getDWOId();
745+
if (DWOId)
746+
SplitCU = BC.getDWOCU(*DWOId);
747+
if (!SplitCU)
748+
continue;
749+
DebugAddrWriter &AddressWriter =
750+
*AddressWritersByCU[CU->getOffset()].get();
751+
DebugRangesSectionWriter *TempRangesSectionWriter =
752+
CU->getVersion() >= 5 ? RangeListsWritersByCU[*DWOId].get()
753+
: LegacyRangesWritersByCU[*DWOId].get();
754+
std::optional<std::string> DwarfOutputPath =
755+
opts::DwarfOutputPath.empty()
756+
? std::nullopt
757+
: std::optional<std::string>(opts::DwarfOutputPath.c_str());
758+
std::string DWOName = DIEBlder.updateDWONameCompDir(
759+
*StrOffstsWriter, *StrWriter, *CU, DwarfOutputPath, std::nullopt);
760+
processSplitCU(*CU, **SplitCU, DIEBlder, *TempRangesSectionWriter,
761+
AddressWriter, DWOName, DwarfOutputPath);
762+
}
754763
for (DWARFUnit *CU : DIEBlder.getProcessedCUs())
755-
processUnitDIE(CU, &DIEBlder);
764+
processMainBinaryCU(*CU, DIEBlder);
756765
finalizeCompileUnits(DIEBlder, *Streamer, OffsetMap,
757766
DIEBlder.getProcessedCUs(), *FinalAddrWriter);
758767
}

bolt/lib/Rewrite/PseudoProbeRewriter.cpp

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ static cl::opt<PrintPseudoProbesOptions> PrintPseudoProbes(
4949
clEnumValN(PPP_All, "all", "enable all debugging printout")),
5050
cl::Hidden, cl::cat(BoltCategory));
5151

52+
extern cl::opt<bool> ProfileUsePseudoProbes;
5253
} // namespace opts
5354

5455
namespace {
@@ -89,12 +90,15 @@ class PseudoProbeRewriter final : public MetadataRewriter {
8990
};
9091

9192
Error PseudoProbeRewriter::preCFGInitializer() {
92-
parsePseudoProbe();
93+
if (opts::ProfileUsePseudoProbes)
94+
parsePseudoProbe();
9395

9496
return Error::success();
9597
}
9698

9799
Error PseudoProbeRewriter::postEmitFinalizer() {
100+
if (!opts::ProfileUsePseudoProbes)
101+
parsePseudoProbe();
98102
updatePseudoProbes();
99103

100104
return Error::success();

0 commit comments

Comments
 (0)