https://github.com/aaupov updated https://github.com/llvm/llvm-project/pull/202813
>From 42df186d47af9dfe2b985b2a174163abe57da110 Mon Sep 17 00:00:00 2001 From: Amir Ayupov <[email protected]> Date: Tue, 9 Jun 2026 16:36:50 -0700 Subject: [PATCH 1/2] =?UTF-8?q?[=F0=9D=98=80=F0=9D=97=BD=F0=9D=97=BF]=20in?= =?UTF-8?q?itial=20version?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Created using spr 1.3.8-beta.1 --- bolt/include/bolt/Profile/DataAggregator.h | 1 + bolt/lib/Profile/DataAggregator.cpp | 28 ++++++++++++++++++---- 2 files changed, 25 insertions(+), 4 deletions(-) diff --git a/bolt/include/bolt/Profile/DataAggregator.h b/bolt/include/bolt/Profile/DataAggregator.h index 1757d3aa56c65..8b432126f5ca0 100644 --- a/bolt/include/bolt/Profile/DataAggregator.h +++ b/bolt/include/bolt/Profile/DataAggregator.h @@ -88,6 +88,7 @@ class DataAggregator : public DataReader { uint64_t From; uint64_t To; bool Mispred; + bool IsReturn; }; friend raw_ostream &operator<<(raw_ostream &OS, const LBREntry &); diff --git a/bolt/lib/Profile/DataAggregator.cpp b/bolt/lib/Profile/DataAggregator.cpp index 0c879d1646b27..fbe9f316166f7 100644 --- a/bolt/lib/Profile/DataAggregator.cpp +++ b/bolt/lib/Profile/DataAggregator.cpp @@ -1292,7 +1292,10 @@ DataAggregator::getFallthroughsInTrace(BinaryFunction &BF, const Trace &Trace, } ErrorOr<DataAggregator::LBREntry> DataAggregator::parseLBREntry() { + /// perf script -F brstack entry format: + /// FROM/TO/EVENT/INTX/ABORT/CYCLES/TYPE/SPEC LBREntry Res; + // From ErrorOr<StringRef> FromStrRes = parseString('/'); if (std::error_code EC = FromStrRes.getError()) return EC; @@ -1303,6 +1306,7 @@ ErrorOr<DataAggregator::LBREntry> DataAggregator::parseLBREntry() { return make_error_code(llvm::errc::io_error); } + // To ErrorOr<StringRef> ToStrRes = parseString('/'); if (std::error_code EC = ToStrRes.getError()) return EC; @@ -1313,10 +1317,11 @@ ErrorOr<DataAggregator::LBREntry> DataAggregator::parseLBREntry() { return make_error_code(llvm::errc::io_error); } - ErrorOr<StringRef> MispredStrRes = parseString('/'); - if (std::error_code EC = MispredStrRes.getError()) + // Event: M: mispredicted, P: predicted, N: not taken + ErrorOr<StringRef> EventStrRes = parseString('/'); + if (std::error_code EC = EventStrRes.getError()) return EC; - StringRef MispredStr = MispredStrRes.get(); + StringRef MispredStr = EventStrRes.get(); // SPE brstack mispredicted flags might be up to two characters long: // 'PN' or 'MN'. Where 'N' optionally appears. bool ValidStrSize = opts::ArmSPE @@ -1344,10 +1349,24 @@ ErrorOr<DataAggregator::LBREntry> DataAggregator::parseLBREntry() { MispredWarning = false; } + // Transaction, abort, cycles + for (unsigned I = 0; I < 3; ++I) { + ErrorOr<StringRef> IgnoredStr = parseString('/'); + if (std::error_code EC = IgnoredStr.getError()) + return EC; + } + + // Type: COND/UNCOND/IND/CALL/IND_CALL/RET + ErrorOr<StringRef> TypeStr = parseString('/'); + if (std::error_code EC = TypeStr.getError()) + return EC; + Res.IsReturn = TypeStr.get() == "RET"; + + // Branch speculation ErrorOr<StringRef> Rest = parseString(FieldSeparator, true); if (std::error_code EC = Rest.getError()) return EC; - if (Rest.get().size() < 5) { + if (Rest.get().size() < 3) { reportError("expected rest of brstack entry"); Diag << "Found: " << Rest.get() << "\n"; return make_error_code(llvm::errc::io_error); @@ -1789,6 +1808,7 @@ void DataAggregator::parseLBRSample(const PerfBranchSample &Sample, TakenBranchInfo &Info = TraceMap[Trace{LBR.From, LBR.To, TraceTo}]; ++Info.TakenCount; Info.MispredCount += LBR.Mispred; + Returns.emplace(LBR.From, LBR.IsReturn); } // Record LBR addresses not covered by fallthroughs (bottom-of-stack source // and top-of-stack target) as basic samples for heatmap. >From 111488ee225cc32ac9f785c68e333750d390b8b5 Mon Sep 17 00:00:00 2001 From: Amir Ayupov <[email protected]> Date: Tue, 9 Jun 2026 21:33:06 -0700 Subject: [PATCH 2/2] return Created using spr 1.3.8-beta.1 --- bolt/docs/profiles.md | 2 +- bolt/include/bolt/Profile/DataAggregator.h | 15 ++++++++-- bolt/lib/Profile/DataAggregator.cpp | 32 ++++++++++------------ bolt/test/perf2bolt/perf_brstack.test | 2 +- 4 files changed, 29 insertions(+), 22 deletions(-) diff --git a/bolt/docs/profiles.md b/bolt/docs/profiles.md index 4900c2fb008d0..d8cf7289b6115 100644 --- a/bolt/docs/profiles.md +++ b/bolt/docs/profiles.md @@ -62,7 +62,7 @@ without going through `perf.data`. ``` E <event> S <start> <count> -[TR] <branch> <ft_start> <ft_end> <count> +[TR] <branch> <ft_start> <ft_end> <count> [<mispred_count>] B <start> <end> <count> <mispred_count> [Ff] <start> <end> <count> r <start> <end> <count> diff --git a/bolt/include/bolt/Profile/DataAggregator.h b/bolt/include/bolt/Profile/DataAggregator.h index 8b432126f5ca0..3816904c8e8e6 100644 --- a/bolt/include/bolt/Profile/DataAggregator.h +++ b/bolt/include/bolt/Profile/DataAggregator.h @@ -143,6 +143,7 @@ class DataAggregator : public DataReader { uint64_t TakenCount{0}; uint64_t MispredCount{0}; }; + friend raw_ostream &operator<<(raw_ostream &OS, const TakenBranchInfo &TBI); /// Intermediate storage for profile data. We save the results of parsing /// and use them later for processing and assigning profile. @@ -434,7 +435,7 @@ class DataAggregator : public DataReader { /// File format syntax: /// E <event> /// S <start> <count> - /// [TR] <start> <end> <ft_end> <count> + /// [TR] <start> <end> <ft_end> <count> [<mispred_count>] /// B <start> <end> <count> <mispred_count> /// [Ffr] <start> <end> <count> /// @@ -473,6 +474,7 @@ class DataAggregator : public DataReader { /// /// Trace profile combining branches and fall-throughs: /// T 4b196f 4b19e0 4b19ef 2 + /// T 4b196f 4b19e0 4b19ef 2 1 /// /// Legacy branch profile with separate branches and fall-throughs: /// F 41be50 41be50 3 @@ -669,13 +671,20 @@ class DataAggregator : public DataReader { inline raw_ostream &operator<<(raw_ostream &OS, const DataAggregator::LBREntry &L) { - OS << formatv("{0:x} -> {1:x}/{2}", L.From, L.To, L.Mispred ? 'M' : 'P'); + OS << formatv("{0:x} -> {1:x}/{2}/{3}", L.From, L.To, L.Mispred ? 'M' : 'P', + L.IsReturn ? "RET" : "-"); return OS; } inline raw_ostream &operator<<(raw_ostream &OS, const DataAggregator::Trace &T) { - OS << formatv("T {0:x-} {1:x-} {2:x-}", T.Branch, T.From, T.To); + OS << formatv("{0:x-} {1:x-} {2:x-}", T.Branch, T.From, T.To); + return OS; +} + +inline raw_ostream &operator<<(raw_ostream &OS, + const DataAggregator::TakenBranchInfo &TBI) { + OS << TBI.TakenCount << " " << TBI.MispredCount; return OS; } diff --git a/bolt/lib/Profile/DataAggregator.cpp b/bolt/lib/Profile/DataAggregator.cpp index fbe9f316166f7..2052b91dc342d 100644 --- a/bolt/lib/Profile/DataAggregator.cpp +++ b/bolt/lib/Profile/DataAggregator.cpp @@ -1366,7 +1366,7 @@ ErrorOr<DataAggregator::LBREntry> DataAggregator::parseLBREntry() { ErrorOr<StringRef> Rest = parseString(FieldSeparator, true); if (std::error_code EC = Rest.getError()) return EC; - if (Rest.get().size() < 3) { + if (Rest.get().size() < 1) { reportError("expected rest of brstack entry"); Diag << "Found: " << Rest.get() << "\n"; return make_error_code(llvm::errc::io_error); @@ -1569,9 +1569,7 @@ std::error_code DataAggregator::parseAggregatedLBREntry() { /// The number of fields to parse, set based on \p Type. int AddrNum = 0; - int CounterNum = 0; /// Storage for parsed fields. - StringRef EventName; std::optional<Location> Addr[3]; int64_t Counters[2] = {0}; @@ -1586,8 +1584,8 @@ std::error_code DataAggregator::parseAggregatedLBREntry() { StringRef Str = StrOrErr.get(); if (Type == EVENT_NAME) { - EventName = Str; - break; + EventNames.insert(Str); + return std::error_code(); } Type = StringSwitch<AggregatedLBREntry>(Str) @@ -1607,9 +1605,7 @@ std::error_code DataAggregator::parseAggregatedLBREntry() { } using SSI = StringSwitch<int>; - AddrNum = - SSI(Str).Cases({"T", "R"}, 3).Case("S", 1).Case("E", 0).Default(2); - CounterNum = SSI(Str).Case("B", 2).Case("E", 0).Default(1); + AddrNum = SSI(Str).Cases({"T", "R"}, 3).Case("S", 1).Default(2); } /// Parse locations depending on entry type, recording them in \p Addr array. @@ -1628,6 +1624,10 @@ std::error_code DataAggregator::parseAggregatedLBREntry() { } /// Parse counters depending on entry type. + const bool HasMispreds = + (Type == BRANCH || Type == TRACE || Type == RETURN) && + ParsingBuf.split('\n').first.contains(FieldSeparator); + const int CounterNum = 1 + HasMispreds; for (int I = 0; I < CounterNum; ++I) { while (checkAndConsumeFS()) { } @@ -1648,12 +1648,6 @@ std::error_code DataAggregator::parseAggregatedLBREntry() { int64_t Mispreds = Counters[1]; switch (Type) { - /// Record event name into \p EventNames and return. - case EVENT_NAME: { - EventNames.insert(EventName); - return std::error_code(); - } - /// Record basic IP sample into \p BasicSamples and return. case SAMPLE: { const uint64_t FromOffset = Addr[0]->Offset; @@ -2486,9 +2480,13 @@ DataAggregator::writePreAggregatedFile(StringRef OutputFilename) const { if (EC) return EC; - for (const auto &[Trace, Info] : Traces) - OS << Trace << " " << Info.TakenCount << '\n'; - OS << formatv("E {0:$[,]}\n", EventNames.keys()); + for (const auto &[Trace, Info] : Traces) { + auto ReturnIt = Returns.find(Trace.Branch); + const bool IsRet = ReturnIt != Returns.end() && ReturnIt->second; + OS << (IsRet ? 'R' : 'T') << " " << Trace << " " << Info << '\n'; + } + if (!EventNames.empty()) + OS << formatv("E {0:$[,]}\n", EventNames.keys()); for (const auto &[PC, Count] : BasicSamples) OS << formatv("S {0:x-} {1}\n", PC, Count); diff --git a/bolt/test/perf2bolt/perf_brstack.test b/bolt/test/perf2bolt/perf_brstack.test index e93f440650006..d7fe6abebebc6 100644 --- a/bolt/test/perf2bolt/perf_brstack.test +++ b/bolt/test/perf2bolt/perf_brstack.test @@ -3,7 +3,7 @@ REQUIRES: system-linux, perf-brstack RUN: %clang %S/Inputs/perf_test.c -no-pie -fuse-ld=lld -o %t -RUN: perf record -Fmax -j any,u -e cycles:u -o %t.perf.data -- %t +RUN: perf record -Fmax -j any,u,save_type -e cycles:u -o %t.perf.data -- %t RUN: perf2bolt %t -p=%t.perf.data -o %t.fdata -ignore-build-id RUN: perf2bolt %t -p=%t.perf.data -o %t.preagg -ignore-build-id --profile-format=preagg RUN: perf2bolt %t -pa -p=%t.preagg -o %t.roundtrip.fdata -ignore-build-id _______________________________________________ llvm-branch-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
