Skip to content

Commit 1327b74

Browse files
committed
Merge branch 'main' into validation/descriptor-tables
2 parents 6a3c2ab + 5fd3aad commit 1327b74

File tree

1,263 files changed

+71422
-42796
lines changed

Some content is hidden

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

1,263 files changed

+71422
-42796
lines changed
Lines changed: 110 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,110 @@
1+
# This file defines a workflow that runs the libc++ benchmarks when a comment is added to the PR.
2+
#
3+
# The comment is of the form:
4+
#
5+
# /libcxx-bot benchmark <path-to-benchmarks-to-run>
6+
#
7+
# That will cause the specified benchmarks to be run on the PR and on the pull-request target, and
8+
# their results to be compared.
9+
10+
name: Benchmark libc++
11+
12+
permissions:
13+
contents: read
14+
15+
on:
16+
issue_comment:
17+
types:
18+
- created
19+
- edited
20+
21+
env:
22+
CC: clang-22
23+
CXX: clang++-22
24+
25+
jobs:
26+
run-benchmarks:
27+
permissions:
28+
pull-requests: write
29+
30+
if: >-
31+
github.event.issue.pull_request &&
32+
contains(github.event.comment.body, '/libcxx-bot benchmark')
33+
34+
runs-on: llvm-premerge-libcxx-next-runners # TODO: This should run on a dedicated set of machines
35+
steps:
36+
- uses: actions/setup-python@v6
37+
with:
38+
python-version: '3.10'
39+
40+
- name: Extract information from the PR
41+
id: vars
42+
run: |
43+
python3 -m venv .venv
44+
source .venv/bin/activate
45+
python -m pip install pygithub
46+
47+
cat <<EOF | python >> ${GITHUB_OUTPUT}
48+
import github
49+
repo = github.Github("${{ github.token }}").get_repo("${{ github.repository }}")
50+
pr = repo.get_pull(${{ github.event.issue.number }})
51+
print(f"pr_base={pr.base.sha}")
52+
print(f"pr_head={pr.head.sha}")
53+
EOF
54+
BENCHMARKS=$(echo "${{ github.event.comment.body }}" | sed -nE 's/\/libcxx-bot benchmark (.+)/\1/p')
55+
echo "benchmarks=${BENCHMARKS}" >> ${GITHUB_OUTPUT}
56+
57+
- uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
58+
with:
59+
ref: ${{ steps.vars.outputs.pr_head }}
60+
fetch-depth: 0
61+
fetch-tags: true # This job requires access to all the Git branches so it can diff against (usually) main
62+
path: repo # Avoid nuking the workspace, where we have the Python virtualenv
63+
64+
- name: Run baseline
65+
run: |
66+
source .venv/bin/activate && cd repo
67+
python -m pip install -r libcxx/utils/requirements.txt
68+
baseline_commit=$(git merge-base ${{ steps.vars.outputs.pr_base }} ${{ steps.vars.outputs.pr_head }})
69+
./libcxx/utils/test-at-commit --commit ${baseline_commit} -B build/baseline -- -sv -j1 --param optimization=speed ${{ steps.vars.outputs.benchmarks }}
70+
./libcxx/utils/consolidate-benchmarks build/baseline | tee baseline.lnt
71+
72+
- name: Run candidate
73+
run: |
74+
source .venv/bin/activate && cd repo
75+
./libcxx/utils/test-at-commit --commit ${{ steps.vars.outputs.pr_head }} -B build/candidate -- -sv -j1 --param optimization=speed ${{ steps.vars.outputs.benchmarks }}
76+
./libcxx/utils/consolidate-benchmarks build/candidate | tee candidate.lnt
77+
78+
- name: Compare baseline and candidate runs
79+
run: |
80+
source .venv/bin/activate && cd repo
81+
./libcxx/utils/compare-benchmarks baseline.lnt candidate.lnt | tee results.txt
82+
83+
- name: Update comment with results
84+
run: |
85+
source .venv/bin/activate && cd repo
86+
cat <<EOF | python
87+
import github
88+
repo = github.Github("${{ github.token }}").get_repo("${{ github.repository }}")
89+
pr = repo.get_pull(${{ github.event.issue.number }})
90+
comment = pr.get_issue_comment(${{ github.event.comment.id }})
91+
with open('results.txt', 'r') as f:
92+
benchmark_results = f.read()
93+
94+
new_comment_text = f"""
95+
{comment.body}
96+
97+
<details>
98+
<summary>
99+
Benchmark results:
100+
</summary>
101+
102+
\`\`\`
103+
{benchmark_results}
104+
\`\`\`
105+
106+
</details>
107+
"""
108+
109+
comment.edit(new_comment_text)
110+
EOF

bolt/include/bolt/Core/BinaryContext.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -288,6 +288,12 @@ class BinaryContext {
288288
/// overwritten, but it is okay to re-generate debug info for them.
289289
std::set<const DWARFUnit *> ProcessedCUs;
290290

291+
/// DWARF-related container to manage lifecycle of groups of rows from line
292+
/// tables associated with instructions. Since binary functions can span
293+
/// multiple compilation units, instructions may reference debug line
294+
/// information from multiple CUs.
295+
ClusteredRowsContainer ClusteredRows;
296+
291297
// Setup MCPlus target builder
292298
void initializeTarget(std::unique_ptr<MCPlusBuilder> TargetBuilder) {
293299
MIB = std::move(TargetBuilder);

bolt/include/bolt/Core/BinaryFunction.h

Lines changed: 17 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@
3535
#include "bolt/Core/JumpTable.h"
3636
#include "bolt/Core/MCPlus.h"
3737
#include "bolt/Utils/NameResolver.h"
38+
#include "llvm/ADT/DenseMap.h"
3839
#include "llvm/ADT/STLExtras.h"
3940
#include "llvm/ADT/SmallString.h"
4041
#include "llvm/ADT/StringRef.h"
@@ -423,8 +424,9 @@ class BinaryFunction {
423424
/// Original LSDA type encoding
424425
unsigned LSDATypeEncoding{dwarf::DW_EH_PE_omit};
425426

426-
/// Containing compilation unit for the function.
427-
DWARFUnit *DwarfUnit{nullptr};
427+
/// All compilation units this function belongs to.
428+
/// Maps DWARF unit offset to the unit pointer.
429+
DenseMap<uint64_t, DWARFUnit *> DwarfUnitMap;
428430

429431
/// Last computed hash value. Note that the value could be recomputed using
430432
/// different parameters by every pass.
@@ -2409,15 +2411,21 @@ class BinaryFunction {
24092411
void
24102412
computeBlockHashes(HashFunction HashFunction = HashFunction::Default) const;
24112413

2412-
void setDWARFUnit(DWARFUnit *Unit) { DwarfUnit = Unit; }
2414+
void addDWARFUnit(DWARFUnit *Unit) { DwarfUnitMap[Unit->getOffset()] = Unit; }
24132415

2414-
/// Return DWARF compile unit for this function.
2415-
DWARFUnit *getDWARFUnit() const { return DwarfUnit; }
2416+
void removeDWARFUnit(DWARFUnit *Unit) {
2417+
DwarfUnitMap.erase(Unit->getOffset());
2418+
}
2419+
2420+
/// Return DWARF compile units for this function.
2421+
/// Returns a reference to the map of DWARF unit offsets to units.
2422+
const DenseMap<uint64_t, DWARFUnit *> &getDWARFUnits() const {
2423+
return DwarfUnitMap;
2424+
}
24162425

2417-
/// Return line info table for this function.
2418-
const DWARFDebugLine::LineTable *getDWARFLineTable() const {
2419-
return getDWARFUnit() ? BC.DwCtx->getLineTableForUnit(getDWARFUnit())
2420-
: nullptr;
2426+
const DWARFDebugLine::LineTable *
2427+
getDWARFLineTableForUnit(DWARFUnit *Unit) const {
2428+
return BC.DwCtx->getLineTableForUnit(Unit);
24212429
}
24222430

24232431
/// Finalize profile for the function.

bolt/include/bolt/Core/DebugData.h

Lines changed: 92 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -135,8 +135,6 @@ struct DebugLineTableRowRef {
135135
uint32_t DwCompileUnitIndex;
136136
uint32_t RowIndex;
137137

138-
const static DebugLineTableRowRef NULL_ROW;
139-
140138
bool operator==(const DebugLineTableRowRef &Rhs) const {
141139
return DwCompileUnitIndex == Rhs.DwCompileUnitIndex &&
142140
RowIndex == Rhs.RowIndex;
@@ -145,24 +143,6 @@ struct DebugLineTableRowRef {
145143
bool operator!=(const DebugLineTableRowRef &Rhs) const {
146144
return !(*this == Rhs);
147145
}
148-
149-
static DebugLineTableRowRef fromSMLoc(const SMLoc &Loc) {
150-
union {
151-
decltype(Loc.getPointer()) Ptr;
152-
DebugLineTableRowRef Ref;
153-
} U;
154-
U.Ptr = Loc.getPointer();
155-
return U.Ref;
156-
}
157-
158-
SMLoc toSMLoc() const {
159-
union {
160-
decltype(SMLoc().getPointer()) Ptr;
161-
DebugLineTableRowRef Ref;
162-
} U;
163-
U.Ref = *this;
164-
return SMLoc::getFromPointer(U.Ptr);
165-
}
166146
};
167147

168148
/// Common buffer vector used for debug info handling.
@@ -210,7 +190,7 @@ class DebugRangesSectionWriter {
210190
static bool classof(const DebugRangesSectionWriter *Writer) {
211191
return Writer->getKind() == RangesWriterKind::DebugRangesWriter;
212192
}
213-
193+
214194
/// Append a range to the main buffer.
215195
void appendToRangeBuffer(const DebugBufferVector &CUBuffer);
216196

@@ -852,6 +832,97 @@ class DwarfLineTable {
852832
// Returns DWARF Version for this line table.
853833
uint16_t getDwarfVersion() const { return DwarfVersion; }
854834
};
835+
836+
/// ClusteredRows represents a collection of debug line table row references.
837+
///
838+
/// MEMORY LAYOUT AND DESIGN:
839+
/// This class uses a flexible array member pattern to store all
840+
/// DebugLineTableRowRef elements in a single contiguous memory allocation.
841+
/// The memory layout is:
842+
///
843+
/// +------------------+
844+
/// | ClusteredRows | <- Object header (Size + first element)
845+
/// | - Size |
846+
/// | - Rows (element) | <- First DebugLineTableRowRef element
847+
/// +------------------+
848+
/// | element[1] | <- Additional DebugLineTableRowRef elements
849+
/// | element[2] | stored immediately after the object
850+
/// | ... |
851+
/// | element[Size-1] |
852+
/// +------------------+
853+
///
854+
/// The 'Rows' member serves as both the first element storage and the base
855+
/// address for pointer arithmetic to access subsequent elements.
856+
class ClusteredRows {
857+
public:
858+
ArrayRef<DebugLineTableRowRef> getRows() const {
859+
return ArrayRef<DebugLineTableRowRef>(beginPtrConst(), Size);
860+
}
861+
862+
/// Returns the number of elements in the array.
863+
uint64_t size() const { return Size; }
864+
865+
/// We re-purpose SMLoc inside MCInst to store the pointer
866+
/// to ClusteredRows. fromSMLoc() and toSMLoc() are helper
867+
/// functions to convert between SMLoc and ClusteredRows.
868+
869+
static const ClusteredRows *fromSMLoc(const SMLoc &Loc) {
870+
return reinterpret_cast<const ClusteredRows *>(Loc.getPointer());
871+
}
872+
SMLoc toSMLoc() const {
873+
return SMLoc::getFromPointer(reinterpret_cast<const char *>(this));
874+
}
875+
876+
/// Given a vector of DebugLineTableRowRef, this method
877+
/// copies the elements into pre-allocated memory.
878+
template <typename T> void populate(const T Vec) {
879+
assert(Vec.size() == Size && "Sizes must match");
880+
DebugLineTableRowRef *CurRawPtr = beginPtr();
881+
for (DebugLineTableRowRef RowRef : Vec) {
882+
*CurRawPtr = RowRef;
883+
++CurRawPtr;
884+
}
885+
}
886+
887+
private:
888+
uint64_t Size;
889+
DebugLineTableRowRef Rows;
890+
891+
ClusteredRows(uint64_t Size) : Size(Size) {}
892+
893+
/// Total size of the object including the array.
894+
static uint64_t getTotalSize(uint64_t Size) {
895+
assert(Size > 0 && "Size must be greater than 0");
896+
return sizeof(ClusteredRows) + (Size - 1) * sizeof(DebugLineTableRowRef);
897+
}
898+
const DebugLineTableRowRef *beginPtrConst() const {
899+
return reinterpret_cast<const DebugLineTableRowRef *>(&Rows);
900+
}
901+
DebugLineTableRowRef *beginPtr() {
902+
return reinterpret_cast<DebugLineTableRowRef *>(&Rows);
903+
}
904+
905+
friend class ClusteredRowsContainer;
906+
};
907+
908+
/// ClusteredRowsContainer manages the lifecycle of ClusteredRows objects.
909+
class ClusteredRowsContainer {
910+
public:
911+
ClusteredRows *createClusteredRows(uint64_t Size) {
912+
auto *CR = new (std::malloc(ClusteredRows::getTotalSize(Size)))
913+
ClusteredRows(Size);
914+
Clusters.push_back(CR);
915+
return CR;
916+
}
917+
~ClusteredRowsContainer() {
918+
for (auto *CR : Clusters)
919+
std::free(CR);
920+
}
921+
922+
private:
923+
std::vector<ClusteredRows *> Clusters;
924+
};
925+
855926
} // namespace bolt
856927
} // namespace llvm
857928

bolt/include/bolt/Core/MCPlusBuilder.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2216,7 +2216,8 @@ class MCPlusBuilder {
22162216
}
22172217

22182218
/// Print each annotation attached to \p Inst.
2219-
void printAnnotations(const MCInst &Inst, raw_ostream &OS) const;
2219+
void printAnnotations(const MCInst &Inst, raw_ostream &OS,
2220+
bool PrintMemData = false) const;
22202221

22212222
/// Remove annotation with a given \p Index.
22222223
///

0 commit comments

Comments
 (0)