Skip to content

Commit 1c10eb2

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 llvm#115333. BRStack change relies on the unit test logic which was introduced by Paschalis Mpeis (ARM) in llvm#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 84b35a3 commit 1c10eb2

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
@@ -297,15 +297,6 @@ class DataAggregator : public DataReader {
297297
/// and a PC
298298
ErrorOr<PerfBasicSample> parseBasicSample();
299299

300-
/// Parse an Arm SPE entry into the non-lbr format by generating two basic
301-
/// samples. The format of an input SPE entry is:
302-
/// ```
303-
/// PID EVENT-TYPE ADDR IP
304-
/// ```
305-
/// SPE branch events will have 'ADDR' set to a branch target address while
306-
/// other perf or SPE events will have it set to zero.
307-
ErrorOr<std::pair<PerfBasicSample, PerfBasicSample>> parseSpeAsBasicSamples();
308-
309300
/// Parse a single perf sample containing a PID associated with an IP and
310301
/// address.
311302
ErrorOr<PerfMemSample> parseMemSample();
@@ -352,9 +343,6 @@ class DataAggregator : public DataReader {
352343
/// Process non-LBR events.
353344
void processBasicEvents();
354345

355-
/// Parse Arm SPE events into the non-LBR format.
356-
std::error_code parseSpeAsBasicEvents();
357-
358346
/// Parse the full output generated by perf script to report memory events.
359347
std::error_code parseMemEvents();
360348

bolt/lib/Profile/DataAggregator.cpp

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

189189
if (opts::ArmSPE) {
190-
if (!opts::BasicAggregation) {
191-
// pid from_ip to_ip predicted/missed not-taken?
192-
// 12345 0x123/0x456/PN/-/-/8/RET/-
193-
launchPerfProcess("SPE brstack events", MainEventsPPI,
194-
"script -F pid,brstack --itrace=bl",
195-
/*Wait = */ false);
196-
} else {
197-
launchPerfProcess("SPE branch events (non-lbr)", MainEventsPPI,
198-
"script -F pid,event,ip,addr --itrace=i1i",
199-
/*Wait = */ false);
200-
}
190+
// pid from_ip to_ip predicted/missed not-taken?
191+
// 12345 0x123/0x456/PN/-/-/8/RET/-
192+
launchPerfProcess("SPE brstack events", MainEventsPPI,
193+
"script -F pid,brstack --itrace=bl",
194+
/*Wait = */ false);
201195
} else if (opts::BasicAggregation) {
202196
launchPerfProcess("events without LBR", MainEventsPPI,
203197
"script -F pid,event,ip",
@@ -472,20 +466,14 @@ int DataAggregator::prepareToParse(StringRef Name, PerfProcessInfo &Process,
472466
Error DataAggregator::preprocessProfile(BinaryContext &BC) {
473467
this->BC = &BC;
474468

475-
const Regex NoData("Samples for '.*' event do not have ADDR attribute set. "
476-
"Cannot print 'addr' field.");
477-
478-
auto ErrorCallback = [&NoData](int ReturnCode, StringRef ErrBuf) {
479-
if (opts::ArmSPE && NoData.match(ErrBuf)) {
480-
errs() << "PERF2BOLT-ERROR: perf data are incompatible for Arm SPE mode "
481-
"consumption. ADDR attribute is unset.\n";
482-
exit(1);
483-
}
469+
auto ErrorCallback = [](int ReturnCode, StringRef ErrBuf) {
484470
errs() << "PERF-ERROR: return code " << ReturnCode << "\n" << ErrBuf;
485471
exit(1);
486472
};
487473

488474
auto MemEventsErrorCallback = [&](int ReturnCode, StringRef ErrBuf) {
475+
Regex NoData("Samples for '.*' event do not have ADDR attribute set. "
476+
"Cannot print 'addr' field.");
489477
if (!NoData.match(ErrBuf))
490478
ErrorCallback(ReturnCode, ErrBuf);
491479
};
@@ -532,7 +520,6 @@ Error DataAggregator::preprocessProfile(BinaryContext &BC) {
532520
prepareToParse("events", MainEventsPPI, ErrorCallback);
533521

534522
if ((!opts::BasicAggregation && parseBranchEvents()) ||
535-
(opts::BasicAggregation && opts::ArmSPE && parseSpeAsBasicEvents()) ||
536523
(opts::BasicAggregation && parseBasicEvents()))
537524
errs() << "PERF2BOLT: failed to parse samples\n";
538525

@@ -1155,68 +1142,6 @@ ErrorOr<DataAggregator::PerfBasicSample> DataAggregator::parseBasicSample() {
11551142
return PerfBasicSample{Event.get(), Address};
11561143
}
11571144

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

@@ -1708,46 +1633,6 @@ std::error_code DataAggregator::parseBasicEvents() {
17081633
return std::error_code();
17091634
}
17101635

1711-
std::error_code DataAggregator::parseSpeAsBasicEvents() {
1712-
outs() << "PERF2BOLT: parsing SPE data as basic events (no LBR)...\n";
1713-
NamedRegionTimer T("parseSPEBasic", "Parsing SPE as basic events",
1714-
TimerGroupName, TimerGroupDesc, opts::TimeAggregator);
1715-
uint64_t NumSpeBranchSamples = 0;
1716-
1717-
// Convert entries to one or two basic samples, depending on whether there is
1718-
// branch target information.
1719-
while (hasData()) {
1720-
auto SamplePair = parseSpeAsBasicSamples();
1721-
if (std::error_code EC = SamplePair.getError())
1722-
return EC;
1723-
1724-
auto registerSample = [this](const PerfBasicSample *Sample) {
1725-
if (!Sample->PC)
1726-
return;
1727-
1728-
if (BinaryFunction *BF = getBinaryFunctionContainingAddress(Sample->PC))
1729-
BF->setHasProfileAvailable();
1730-
1731-
++BasicSamples[Sample->PC];
1732-
EventNames.insert(Sample->EventName);
1733-
};
1734-
1735-
if (SamplePair->first.PC != 0x0 && SamplePair->second.PC != 0x0)
1736-
++NumSpeBranchSamples;
1737-
1738-
registerSample(&SamplePair->first);
1739-
registerSample(&SamplePair->second);
1740-
}
1741-
1742-
if (NumSpeBranchSamples == 0)
1743-
errs() << "PERF2BOLT-WARNING: no SPE branches found\n";
1744-
else
1745-
outs() << "PERF2BOLT: found " << NumSpeBranchSamples
1746-
<< " SPE branch sample pairs.\n";
1747-
1748-
return std::error_code();
1749-
}
1750-
17511636
void DataAggregator::processBasicEvents() {
17521637
outs() << "PERF2BOLT: processing basic events (without LBR)...\n";
17531638
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)