Skip to content

Commit b526d2b

Browse files
Removing dependency of the SPE BasicAggregation
This commit aim is to uncouple the SPE BRStack and SPE BasicAggregation approaches based on the decision in issue #115333. BRStack change relies on the unit test logic which was introduced by Paschalis Mpeis (ARM) in #120741. Since it is a common part of the two aggregation type technique, needs to retain an essential part of it. All relevant tests to BasicAggregation is removed. Co-Authored-By: Paschalis Mpeis <[email protected]>
1 parent ffd2f26 commit b526d2b

File tree

4 files changed

+8
-234
lines changed

4 files changed

+8
-234
lines changed

bolt/include/bolt/Profile/DataAggregator.h

Lines changed: 0 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -288,15 +288,6 @@ class DataAggregator : public DataReader {
288288
/// and a PC
289289
ErrorOr<PerfBasicSample> parseBasicSample();
290290

291-
/// Parse an Arm SPE entry into the non-lbr format by generating two basic
292-
/// samples. The format of an input SPE entry is:
293-
/// ```
294-
/// PID EVENT-TYPE ADDR IP
295-
/// ```
296-
/// SPE branch events will have 'ADDR' set to a branch target address while
297-
/// other perf or SPE events will have it set to zero.
298-
ErrorOr<std::pair<PerfBasicSample, PerfBasicSample>> parseSpeAsBasicSamples();
299-
300291
/// Parse a single perf sample containing a PID associated with an IP and
301292
/// address.
302293
ErrorOr<PerfMemSample> parseMemSample();
@@ -343,9 +334,6 @@ class DataAggregator : public DataReader {
343334
/// Process non-LBR events.
344335
void processBasicEvents();
345336

346-
/// Parse Arm SPE events into the non-LBR format.
347-
std::error_code parseSpeAsBasicEvents();
348-
349337
/// Parse the full output generated by perf script to report memory events.
350338
std::error_code parseMemEvents();
351339

bolt/lib/Profile/DataAggregator.cpp

Lines changed: 8 additions & 123 deletions
Original file line numberDiff line numberDiff line change
@@ -181,17 +181,11 @@ void DataAggregator::start() {
181181
findPerfExecutable();
182182

183183
if (opts::ArmSPE) {
184-
if (!opts::BasicAggregation) {
185-
// pid from_ip to_ip predicted/missed not-taken?
186-
// 12345 0x123/0x456/PN/-/-/8/RET/-
187-
launchPerfProcess("SPE brstack events", MainEventsPPI,
188-
"script -F pid,brstack --itrace=bl",
189-
/*Wait = */ false);
190-
} else {
191-
launchPerfProcess("SPE branch events (non-lbr)", MainEventsPPI,
192-
"script -F pid,event,ip,addr --itrace=i1i",
193-
/*Wait = */ false);
194-
}
184+
// pid from_ip to_ip predicted/missed not-taken?
185+
// 12345 0x123/0x456/PN/-/-/8/RET/-
186+
launchPerfProcess("SPE brstack events", MainEventsPPI,
187+
"script -F pid,brstack --itrace=bl",
188+
/*Wait = */ false);
195189
} else if (opts::BasicAggregation) {
196190
launchPerfProcess("events without LBR", MainEventsPPI,
197191
"script -F pid,event,ip",
@@ -464,20 +458,14 @@ int DataAggregator::prepareToParse(StringRef Name, PerfProcessInfo &Process,
464458
Error DataAggregator::preprocessProfile(BinaryContext &BC) {
465459
this->BC = &BC;
466460

467-
const Regex NoData("Samples for '.*' event do not have ADDR attribute set. "
468-
"Cannot print 'addr' field.");
469-
470-
auto ErrorCallback = [&NoData](int ReturnCode, StringRef ErrBuf) {
471-
if (opts::ArmSPE && NoData.match(ErrBuf)) {
472-
errs() << "PERF2BOLT-ERROR: perf data are incompatible for Arm SPE mode "
473-
"consumption. ADDR attribute is unset.\n";
474-
exit(1);
475-
}
461+
auto ErrorCallback = [](int ReturnCode, StringRef ErrBuf) {
476462
errs() << "PERF-ERROR: return code " << ReturnCode << "\n" << ErrBuf;
477463
exit(1);
478464
};
479465

480466
auto MemEventsErrorCallback = [&](int ReturnCode, StringRef ErrBuf) {
467+
Regex NoData("Samples for '.*' event do not have ADDR attribute set. "
468+
"Cannot print 'addr' field.");
481469
if (!NoData.match(ErrBuf))
482470
ErrorCallback(ReturnCode, ErrBuf);
483471
};
@@ -524,7 +512,6 @@ Error DataAggregator::preprocessProfile(BinaryContext &BC) {
524512
prepareToParse("events", MainEventsPPI, ErrorCallback);
525513

526514
if ((!opts::BasicAggregation && parseBranchEvents()) ||
527-
(opts::BasicAggregation && opts::ArmSPE && parseSpeAsBasicEvents()) ||
528515
(opts::BasicAggregation && parseBasicEvents()))
529516
errs() << "PERF2BOLT: failed to parse samples\n";
530517

@@ -1163,68 +1150,6 @@ ErrorOr<DataAggregator::PerfBasicSample> DataAggregator::parseBasicSample() {
11631150
return PerfBasicSample{Event.get(), Address};
11641151
}
11651152

1166-
ErrorOr<
1167-
std::pair<DataAggregator::PerfBasicSample, DataAggregator::PerfBasicSample>>
1168-
DataAggregator::parseSpeAsBasicSamples() {
1169-
while (checkAndConsumeFS()) {
1170-
}
1171-
1172-
ErrorOr<int64_t> PIDRes = parseNumberField(FieldSeparator, true);
1173-
if (std::error_code EC = PIDRes.getError())
1174-
return EC;
1175-
1176-
constexpr PerfBasicSample EmptySample = PerfBasicSample{StringRef(), 0};
1177-
auto MMapInfoIter = BinaryMMapInfo.find(*PIDRes);
1178-
if (MMapInfoIter == BinaryMMapInfo.end()) {
1179-
consumeRestOfLine();
1180-
return std::make_pair(EmptySample, EmptySample);
1181-
}
1182-
1183-
while (checkAndConsumeFS()) {
1184-
}
1185-
1186-
ErrorOr<StringRef> Event = parseString(FieldSeparator);
1187-
if (std::error_code EC = Event.getError())
1188-
return EC;
1189-
1190-
while (checkAndConsumeFS()) {
1191-
}
1192-
1193-
ErrorOr<uint64_t> AddrResTo = parseHexField(FieldSeparator);
1194-
if (std::error_code EC = AddrResTo.getError())
1195-
return EC;
1196-
1197-
consumeAllRemainingFS();
1198-
1199-
ErrorOr<uint64_t> AddrResFrom = parseHexField(FieldSeparator, true);
1200-
if (std::error_code EC = AddrResFrom.getError())
1201-
return EC;
1202-
1203-
if (!checkAndConsumeNewLine()) {
1204-
reportError("expected end of line");
1205-
return make_error_code(llvm::errc::io_error);
1206-
}
1207-
1208-
auto genBasicSample = [&](uint64_t Address) {
1209-
// When fed with non SPE branch events the target address will be null.
1210-
// This is expected and ignored.
1211-
if (Address == 0x0)
1212-
return EmptySample;
1213-
1214-
if (!BC->HasFixedLoadAddress)
1215-
adjustAddress(Address, MMapInfoIter->second);
1216-
1217-
return PerfBasicSample{Event.get(), Address};
1218-
};
1219-
1220-
// Show more meaningful event names on boltdata.
1221-
if (Event->str() == "instructions:")
1222-
Event = *AddrResTo != 0x0 ? "branches-spe:" : "instructions-spe:";
1223-
1224-
return std::make_pair(genBasicSample(*AddrResFrom),
1225-
genBasicSample(*AddrResTo));
1226-
}
1227-
12281153
ErrorOr<DataAggregator::PerfMemSample> DataAggregator::parseMemSample() {
12291154
PerfMemSample Res{0, 0};
12301155

@@ -1734,46 +1659,6 @@ std::error_code DataAggregator::parseBasicEvents() {
17341659
return std::error_code();
17351660
}
17361661

1737-
std::error_code DataAggregator::parseSpeAsBasicEvents() {
1738-
outs() << "PERF2BOLT: parsing SPE data as basic events (no LBR)...\n";
1739-
NamedRegionTimer T("parseSPEBasic", "Parsing SPE as basic events",
1740-
TimerGroupName, TimerGroupDesc, opts::TimeAggregator);
1741-
uint64_t NumSpeBranchSamples = 0;
1742-
1743-
// Convert entries to one or two basic samples, depending on whether there is
1744-
// branch target information.
1745-
while (hasData()) {
1746-
auto SamplePair = parseSpeAsBasicSamples();
1747-
if (std::error_code EC = SamplePair.getError())
1748-
return EC;
1749-
1750-
auto registerSample = [this](const PerfBasicSample *Sample) {
1751-
if (!Sample->PC)
1752-
return;
1753-
1754-
if (BinaryFunction *BF = getBinaryFunctionContainingAddress(Sample->PC))
1755-
BF->setHasProfileAvailable();
1756-
1757-
++BasicSamples[Sample->PC];
1758-
EventNames.insert(Sample->EventName);
1759-
};
1760-
1761-
if (SamplePair->first.PC != 0x0 && SamplePair->second.PC != 0x0)
1762-
++NumSpeBranchSamples;
1763-
1764-
registerSample(&SamplePair->first);
1765-
registerSample(&SamplePair->second);
1766-
}
1767-
1768-
if (NumSpeBranchSamples == 0)
1769-
errs() << "PERF2BOLT-WARNING: no SPE branches found\n";
1770-
else
1771-
outs() << "PERF2BOLT: found " << NumSpeBranchSamples
1772-
<< " SPE branch sample pairs.\n";
1773-
1774-
return std::error_code();
1775-
}
1776-
17771662
void DataAggregator::processBasicEvents() {
17781663
outs() << "PERF2BOLT: processing basic events (without LBR)...\n";
17791664
NamedRegionTimer T("processBasic", "Processing basic events", TimerGroupName,

bolt/test/perf2bolt/AArch64/perf2bolt-spe.test

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,7 @@ REQUIRES: system-linux,perf,target=aarch64{{.*}}
44

55
RUN: perf record -e cycles -q -o %t.perf.data -- %t.exe 2> /dev/null
66

7-
RUN: (perf2bolt -p %t.perf.data -o %t.perf.boltdata --spe --nl %t.exe 2> /dev/null; exit 0) | FileCheck %s --check-prefix=CHECK-SPE-NO-LBR
8-
97
RUN: (perf2bolt -p %t.perf.data -o %t.perf.boltdata --spe %t.exe 2> /dev/null; exit 0) | FileCheck %s --check-prefix=CHECK-SPE-LBR
108

11-
CHECK-SPE-NO-LBR: PERF2BOLT: spawning perf job to read SPE branch events (non-lbr)
129
CHECK-SPE-LBR: PERF2BOLT: spawning perf job to read SPE brstack events
1310

bolt/unittests/Profile/PerfSpeEvents.cpp

Lines changed: 0 additions & 96 deletions
Original file line numberDiff line numberDiff line change
@@ -73,25 +73,6 @@ struct PerfSpeEventsTestHelper : public testing::Test {
7373
std::unique_ptr<ObjectFile> ObjFile;
7474
std::unique_ptr<BinaryContext> BC;
7575

76-
/// Return true when the expected \p SampleSize profile data are generated and
77-
/// contain all the \p ExpectedEventNames.
78-
bool checkEvents(uint64_t PID, size_t SampleSize,
79-
const StringSet<> &ExpectedEventNames) {
80-
DataAggregator DA("<pseudo input>");
81-
DA.ParsingBuf = opts::ReadPerfEvents;
82-
DA.BC = BC.get();
83-
DataAggregator::MMapInfo MMap;
84-
DA.BinaryMMapInfo.insert(std::make_pair(PID, MMap));
85-
86-
DA.parseSpeAsBasicEvents();
87-
88-
for (auto &EE : ExpectedEventNames)
89-
if (!DA.EventNames.contains(EE.first()))
90-
return false;
91-
92-
return SampleSize == DA.BasicSamples.size();
93-
}
94-
9576
/// Compare LBREntries
9677
bool checkLBREntry(const LBREntry &Lhs, const LBREntry &Rhs) {
9778
return Lhs.From == Rhs.From && Lhs.To == Rhs.To &&
@@ -135,26 +116,6 @@ struct PerfSpeEventsTestHelper : public testing::Test {
135116
} // namespace bolt
136117
} // namespace llvm
137118

138-
// Check that DataAggregator can parseSpeAsBasicEvents for branch events when
139-
// combined with other event types.
140-
141-
TEST_F(PerfSpeEventsTestHelper, SpeBranches) {
142-
// Check perf input with SPE branch events.
143-
// Example collection command:
144-
// ```
145-
// perf record -e 'arm_spe_0/branch_filter=1/u' -- BINARY
146-
// ```
147-
148-
opts::ReadPerfEvents =
149-
"1234 instructions: a002 a001\n"
150-
"1234 instructions: b002 b001\n"
151-
"1234 instructions: c002 c001\n"
152-
"1234 instructions: d002 d001\n"
153-
"1234 instructions: e002 e001\n";
154-
155-
EXPECT_TRUE(checkEvents(1234, 10, {"branches-spe:"}));
156-
}
157-
158119
TEST_F(PerfSpeEventsTestHelper, SpeBranchesWithBrstack) {
159120
// Check perf input with SPE branch events as brstack format.
160121
// Example collection command:
@@ -182,61 +143,4 @@ TEST_F(PerfSpeEventsTestHelper, SpeBranchesWithBrstack) {
182143
parseAndCheckBrstackEvents(1234, ExpectedSamples);
183144
}
184145

185-
TEST_F(PerfSpeEventsTestHelper, SpeBranchesAndCycles) {
186-
// Check perf input with SPE branch events and cycles.
187-
// Example collection command:
188-
// ```
189-
// perf record -e cycles:u -e 'arm_spe_0/branch_filter=1/u' -- BINARY
190-
// ```
191-
192-
opts::ReadPerfEvents =
193-
"1234 instructions: a002 a001\n"
194-
"1234 cycles:u: 0 b001\n"
195-
"1234 cycles:u: 0 c001\n"
196-
"1234 instructions: d002 d001\n"
197-
"1234 instructions: e002 e001\n";
198-
199-
EXPECT_TRUE(checkEvents(1234, 8, {"branches-spe:", "cycles:u:"}));
200-
}
201-
202-
TEST_F(PerfSpeEventsTestHelper, SpeAnyEventAndCycles) {
203-
// Check perf input with any SPE event type and cycles.
204-
// Example collection command:
205-
// ```
206-
// perf record -e cycles:u -e 'arm_spe_0//u' -- BINARY
207-
// ```
208-
209-
opts::ReadPerfEvents =
210-
"1234 cycles:u: 0 a001\n"
211-
"1234 cycles:u: 0 b001\n"
212-
"1234 instructions: 0 c001\n"
213-
"1234 instructions: 0 d001\n"
214-
"1234 instructions: e002 e001\n";
215-
216-
EXPECT_TRUE(checkEvents(1234, 6,
217-
{"cycles:u:", "instructions-spe:", "branches-spe:"}));
218-
}
219-
220-
TEST_F(PerfSpeEventsTestHelper, SpeNoBranchPairsRecorded) {
221-
// Check perf input that has no SPE branch pairs recorded.
222-
// Example collection command:
223-
// ```
224-
// perf record -e cycles:u -e 'arm_spe_0/load_filter=1,branch_filter=0/u' --
225-
// BINARY
226-
// ```
227-
228-
testing::internal::CaptureStderr();
229-
opts::ReadPerfEvents =
230-
"1234 instructions: 0 a001\n"
231-
"1234 cycles:u: 0 b001\n"
232-
"1234 instructions: 0 c001\n"
233-
"1234 cycles:u: 0 d001\n"
234-
"1234 instructions: 0 e001\n";
235-
236-
EXPECT_TRUE(checkEvents(1234, 5, {"instructions-spe:", "cycles:u:"}));
237-
238-
std::string Stderr = testing::internal::GetCapturedStderr();
239-
EXPECT_EQ(Stderr, "PERF2BOLT-WARNING: no SPE branches found\n");
240-
}
241-
242146
#endif

0 commit comments

Comments
 (0)