[llvm] [llvm-profgen] Add pgo accuracy metrics (PR #93975)
via llvm-commits
llvm-commits at lists.llvm.org
Fri May 31 08:34:18 PDT 2024
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-pgo
Author: None (lifengxiang1025)
<details>
<summary>Changes</summary>
Emit pgo accuracy metrics by comparing branch probability in bbaddrmap section and branch probability calculated by perf sampling.
---
Full diff: https://github.com/llvm/llvm-project/pull/93975.diff
9 Files Affected:
- (added) llvm/test/tools/llvm-profgen/Inputs/pgo-accuracy-metrics.perfbin ()
- (added) llvm/test/tools/llvm-profgen/Inputs/pgo-accuracy-metrics.perfscrpit (+2)
- (added) llvm/test/tools/llvm-profgen/pgo-accuracy-metrics.test (+24)
- (modified) llvm/tools/llvm-profgen/CMakeLists.txt (+1)
- (added) llvm/tools/llvm-profgen/PGOAccuracyMetrics.cpp (+106)
- (added) llvm/tools/llvm-profgen/PGOAccuracyMetrics.h (+45)
- (modified) llvm/tools/llvm-profgen/ProfiledBinary.cpp (+8)
- (modified) llvm/tools/llvm-profgen/ProfiledBinary.h (+10)
- (modified) llvm/tools/llvm-profgen/llvm-profgen.cpp (+13)
``````````diff
diff --git a/llvm/test/tools/llvm-profgen/Inputs/pgo-accuracy-metrics.perfbin b/llvm/test/tools/llvm-profgen/Inputs/pgo-accuracy-metrics.perfbin
new file mode 100755
index 0000000000000..7ae145c299adb
Binary files /dev/null and b/llvm/test/tools/llvm-profgen/Inputs/pgo-accuracy-metrics.perfbin differ
diff --git a/llvm/test/tools/llvm-profgen/Inputs/pgo-accuracy-metrics.perfscrpit b/llvm/test/tools/llvm-profgen/Inputs/pgo-accuracy-metrics.perfscrpit
new file mode 100644
index 0000000000000..7152093802751
--- /dev/null
+++ b/llvm/test/tools/llvm-profgen/Inputs/pgo-accuracy-metrics.perfscrpit
@@ -0,0 +1,2 @@
+PERF_RECORD_MMAP2 36922/36922: [0x5592aaa7f000(0x1000) @ 0x1000 08:10 26214013168 3588669473]: r-xp /pgo-accuracy-metrics.perfbin
+ 5592aaa7f1fa 0x7f2ed752662d/0x7f2ed7526850/P/-/-/3 0x7f2ed7526602/0x7f2ed7526614/P/-/-/1 0x7f2ed7526b34/0x7f2ed75265f0/P/-/-/1 0x5592aaa7f080/0x7f2ed7526b30/P/-/-/1 0x5592aaa7f1ed/0x5592aaa7f080/P/-/-/1 0x5592aaa7f21e/0x5592aaa7f1e4/P/-/-/1 0x5592aaa7f213/0x5592aaa7f215/P/-/-/1 0x5592aaa7f1fd/0x5592aaa7f20a/P/-/-/15 0x7f2ed7526b3d/0x5592aaa7f1f2/P/-/-/1 0x7f2ed752665f/0x7f2ed7526b39/P/-/-/1 0x7f2ed7526639/0x7f2ed752664a/P/-/-/1 0x7f2ed752689d/0x7f2ed7526632/P/-/-/6 0x7f2ed752662d/0x7f2ed7526850/P/-/-/3 0x7f2ed7526602/0x7f2ed7526614/P/-/-/1 0x7f2ed7526b34/0x7f2ed75265f0/P/-/-/1 0x5592aaa7f080/0x7f2ed7526b30/P/-/-/1 0x5592aaa7f1ed/0x5592aaa7f080/P/-/-/1 0x5592aaa7f21e/0x5592aaa7f1e4/P/-/-/1 0x5592aaa7f213/0x5592aaa7f215/P/-/-/1 0x5592aaa7f1fd/0x5592aaa7f20a/P/-/-/15 0x7f2ed7526b3d/0x5592aaa7f1f2/P/-/-/1 0x7f2ed752665f/0x7f2ed7526b39/P/-/-/1 0x7f2ed7526639/0x7f2ed752664a/P/-/-/1 0x7f2ed752689d/0x7f2ed7526632/P/-/-/6 0x7f2ed752662d/0x7f2ed7526850/P/-/-/3 0x7f2ed7526602/0x7f2ed7526614/P/-/-/1 0x7f2ed7526b34/0x7f2ed75265f0/P/-/-/1 0x5592aaa7f080/0x7f2ed7526b30/P/-/-/1 0x5592aaa7f1ed/0x5592aaa7f080/P/-/-/1 0x5592aaa7f21e/0x5592aaa7f1e4/P/-/-/1 0x5592aaa7f213/0x5592aaa7f215/P/-/-/1 0x5592aaa7f1fd/0x5592aaa7f20a/P/-/-/14
diff --git a/llvm/test/tools/llvm-profgen/pgo-accuracy-metrics.test b/llvm/test/tools/llvm-profgen/pgo-accuracy-metrics.test
new file mode 100644
index 0000000000000..b4fd875bd704e
--- /dev/null
+++ b/llvm/test/tools/llvm-profgen/pgo-accuracy-metrics.test
@@ -0,0 +1,24 @@
+; Test pgo accuracy metrics
+; RUN: llvm-profgen --perfscript=%S/Inputs/pgo-accuracy-metrics.perfscript --binary=%S/Inputs/pgo-accuracy-metrics.perfbin --output=%t --pgo-accuracy-metrics 2>&1 | FileCheck %s --check-prefix=CHECK-STATS
+
+; CHECK-STATS: UnknownBranches: 0
+; CHECK-STATS: MatchedBranches: 5
+; CHECK-STATS: DismatchedBranches: 4
+
+; Original code:
+; clang++ test.cpp -g -fbasic-block-sections=labels -mllvm -pgo-analysis-map=br-prob
+
+#include <iostream>
+#include <random>
+int main() {
+ int a = 0;
+ int b = 0;
+ for (int i = 0; i < 100000000; ++i) {
+ if (rand() % 1) {
+ ++a;
+ } else {
+ ++b;
+ }
+ }
+ return 0;
+}
diff --git a/llvm/tools/llvm-profgen/CMakeLists.txt b/llvm/tools/llvm-profgen/CMakeLists.txt
index 354c63f409ffe..af8ea240f8a54 100644
--- a/llvm/tools/llvm-profgen/CMakeLists.txt
+++ b/llvm/tools/llvm-profgen/CMakeLists.txt
@@ -22,4 +22,5 @@ add_llvm_tool(llvm-profgen
ProfiledBinary.cpp
ProfileGenerator.cpp
MissingFrameInferrer.cpp
+ PGOAccuracyMetrics.cpp
)
diff --git a/llvm/tools/llvm-profgen/PGOAccuracyMetrics.cpp b/llvm/tools/llvm-profgen/PGOAccuracyMetrics.cpp
new file mode 100644
index 0000000000000..2c9394805e072
--- /dev/null
+++ b/llvm/tools/llvm-profgen/PGOAccuracyMetrics.cpp
@@ -0,0 +1,106 @@
+#include "PGOAccuracyMetrics.h"
+static cl::opt<double> BranchProbabilityThreshold(
+ "pgo-accuracy-metrics-branch-probability-threshold",
+ cl::desc("PGO accuracy metrics branch probability threshold"),
+ cl::init(20.0));
+
+namespace llvm {
+namespace sampleprof {
+
+void PGOAccuracyMetrics::init() {
+ for (auto &Function : BBAddrMaps) {
+ for (auto &Range : Function.getBBRanges()) {
+ uint64_t BaseAddress = Range.BaseAddress;
+ for (auto &BB : Range.BBEntries) {
+ uint64_t Address = BaseAddress + BB.Offset;
+ BBAddrToID[Address] =
+ std::make_pair(Function.getFunctionAddress(), BB.ID);
+ }
+ }
+ }
+
+ for (auto It : SampleCounters) {
+ const RangeSample &RangeCounter = It.second.RangeCounter;
+ const BranchSample &BranchCounter = It.second.BranchCounter;
+
+ for (auto Item : RangeCounter) {
+ auto From = BBAddrToID.lower_bound(Item.first.first);
+ auto End = BBAddrToID.upper_bound(Item.first.second);
+ if (From == End)
+ continue;
+ for (auto To = std::next(From); To != End; ++To) {
+ assert(From->second.first == To->second.first);
+ EdgeCounter[From->second.first]
+ [std::make_pair(From->second.second, To->second.second)] +=
+ Item.second;
+ From = To;
+ }
+ }
+
+ for (auto Item : BranchCounter) {
+ auto Ptr = BBAddrToID.upper_bound(Item.first.first);
+ if (Ptr == BBAddrToID.begin())
+ continue;
+ auto From = std::prev(Ptr)->second;
+ auto To = BBAddrToID[Item.first.second];
+ assert(From.first == To.first);
+ EdgeCounter[From.first][{From.second, To.second}] += Item.second;
+ }
+ }
+}
+
+void PGOAccuracyMetrics::emitPGOAccuracyMetrics() {
+ assert(BBAddrMaps.size() == PGOAnalysisMaps.size());
+
+ for (uint64_t I = 0; I < BBAddrMaps.size(); ++I) {
+ auto &BBAddrMap = BBAddrMaps[I];
+ auto &PGOAnalysisMap = PGOAnalysisMaps[I];
+ assert(BBAddrMap.getNumBBEntries() == PGOAnalysisMap.BBEntries.size());
+ size_t Pos = 0;
+ for (auto &Range : BBAddrMap.getBBRanges()) {
+ for (auto &BB : Range.BBEntries) {
+ uint64_t Sum = 0;
+ for (auto Successor : PGOAnalysisMap.BBEntries[Pos].Successors) {
+ Sum += EdgeCounter[BBAddrMap.getFunctionAddress()]
+ [std::make_pair(BB.ID, Successor.ID)];
+ }
+
+ for (auto Successor : PGOAnalysisMap.BBEntries[Pos].Successors) {
+ if (Successor.Prob.isUnknown()) {
+ ++UnknownBranches;
+ continue;
+ }
+ double SampleBranchProb =
+ rint((Sum == 0
+ ? (double)1 /
+ PGOAnalysisMap.BBEntries[Pos].Successors.size()
+ : (double)EdgeCounter[BBAddrMap.getFunctionAddress()]
+ [std::make_pair(BB.ID,
+ Successor.ID)] /
+ Sum) *
+ 100.0 * 100.0) /
+ 100.0;
+ double RecordBranchProb =
+ rint(((double)Successor.Prob.getNumerator() /
+ Successor.Prob.getDenominator()) *
+ 100.0 * 100.0) /
+ 100.0;
+ if (abs(SampleBranchProb - RecordBranchProb) <
+ BranchProbabilityThreshold) {
+ ++MatchedBranches;
+ } else {
+ ++DismatchedBranches;
+ }
+ }
+ ++Pos;
+ }
+ }
+ }
+
+ llvm::outs() << "UnknownBranches: " << UnknownBranches << "\n";
+ llvm::outs() << "MatchedBranches: " << MatchedBranches << "\n";
+ llvm::outs() << "DismatchedBranches: " << DismatchedBranches << "\n";
+}
+
+} // namespace sampleprof
+} // namespace llvm
diff --git a/llvm/tools/llvm-profgen/PGOAccuracyMetrics.h b/llvm/tools/llvm-profgen/PGOAccuracyMetrics.h
new file mode 100644
index 0000000000000..5363713abbff8
--- /dev/null
+++ b/llvm/tools/llvm-profgen/PGOAccuracyMetrics.h
@@ -0,0 +1,45 @@
+//===-- PGOAccuracyMetrics.h ------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+#ifndef LLVM_TOOLS_LLVM_PROFGEN_PGOACCURACYMETRICS_H
+#define LLVM_TOOLS_LLVM_PROFGEN_PGOACCURACYMETRICS_H
+
+#include "PerfReader.h"
+#include "llvm/Object/ELFTypes.h"
+
+namespace llvm {
+namespace sampleprof {
+class PGOAccuracyMetrics {
+public:
+ PGOAccuracyMetrics(const ContextSampleCounterMap &CSCM,
+ const std::vector<BBAddrMap> &BBAM,
+ const std::vector<PGOAnalysisMap> &PGOAM)
+ : SampleCounters(CSCM), BBAddrMaps(BBAM), PGOAnalysisMaps(PGOAM) {
+ init();
+ }
+ void init();
+ void emitPGOAccuracyMetrics();
+
+private:
+ const ContextSampleCounterMap &SampleCounters;
+ const std::vector<BBAddrMap> &BBAddrMaps;
+ const std::vector<PGOAnalysisMap> &PGOAnalysisMaps;
+
+ // key is bb's address, value is function's address and bb's unique id;
+ std::map<uint64_t, std::pair<uint64_t, uint32_t>> BBAddrToID;
+ std::unordered_map<uint64_t,
+ std::map<std::pair<uint32_t, uint32_t>, uint64_t>>
+ EdgeCounter;
+
+ uint64_t UnknownBranches = 0;
+ uint64_t MatchedBranches = 0;
+ uint64_t DismatchedBranches = 0;
+};
+} // namespace sampleprof
+} // namespace llvm
+
+#endif
\ No newline at end of file
diff --git a/llvm/tools/llvm-profgen/ProfiledBinary.cpp b/llvm/tools/llvm-profgen/ProfiledBinary.cpp
index 1baf35820f97f..d0695deae86e5 100644
--- a/llvm/tools/llvm-profgen/ProfiledBinary.cpp
+++ b/llvm/tools/llvm-profgen/ProfiledBinary.cpp
@@ -256,6 +256,14 @@ void ProfiledBinary::load() {
warnNoFuncEntry();
+ if (auto *ELFObj = dyn_cast<ELFObjectFileBase>(Obj)) {
+ auto BBAddrMapsOrErr =
+ ELFObj->readBBAddrMap(std::nullopt, &PGOAnalysisMaps);
+ if (!BBAddrMapsOrErr.takeError()) {
+ BBAddrMaps = *BBAddrMapsOrErr;
+ }
+ }
+
// TODO: decode other sections.
}
diff --git a/llvm/tools/llvm-profgen/ProfiledBinary.h b/llvm/tools/llvm-profgen/ProfiledBinary.h
index 5d2088ad7691c..08c6d065ebca4 100644
--- a/llvm/tools/llvm-profgen/ProfiledBinary.h
+++ b/llvm/tools/llvm-profgen/ProfiledBinary.h
@@ -299,6 +299,10 @@ class ProfiledBinary {
bool IsCOFF = false;
+ std::vector<PGOAnalysisMap> PGOAnalysisMaps;
+
+ std::vector<BBAddrMap> BBAddrMaps;
+
void setPreferredTextSegmentAddresses(const ObjectFile *O);
template <class ELFT>
@@ -600,6 +604,12 @@ class ProfiledBinary {
bool getMissingMMapWarned() { return MissingMMapWarned; }
void setMissingMMapWarned(bool Value) { MissingMMapWarned = Value; }
+
+ const std::vector<BBAddrMap> &getBBAddrMaps() const { return BBAddrMaps; }
+
+ const std::vector<PGOAnalysisMap> &getPGOAnalysisMaps() const {
+ return PGOAnalysisMaps;
+ }
};
} // end namespace sampleprof
diff --git a/llvm/tools/llvm-profgen/llvm-profgen.cpp b/llvm/tools/llvm-profgen/llvm-profgen.cpp
index 3b974e25103ad..6a904d8acbe83 100644
--- a/llvm/tools/llvm-profgen/llvm-profgen.cpp
+++ b/llvm/tools/llvm-profgen/llvm-profgen.cpp
@@ -11,6 +11,7 @@
//===----------------------------------------------------------------------===//
#include "ErrorHandling.h"
+#include "PGOAccuracyMetrics.h"
#include "PerfReader.h"
#include "ProfileGenerator.h"
#include "ProfiledBinary.h"
@@ -67,6 +68,11 @@ static cl::opt<std::string> DebugBinPath(
"from it instead of the executable binary."),
cl::cat(ProfGenCategory));
+static cl::opt<bool>
+ EmitPGOAccuracyMetrics("pgo-accuracy-metrics", cl::init(false),
+ cl::desc("Print PGO accuracy metrics"),
+ cl::cat(ProfGenCategory));
+
extern cl::opt<bool> ShowDisassemblyOnly;
extern cl::opt<bool> ShowSourceLocations;
extern cl::opt<bool> SkipSymbolization;
@@ -179,6 +185,13 @@ int main(int argc, const char *argv[]) {
// Parse perf events and samples
Reader->parsePerfTraces();
+ if (EmitPGOAccuracyMetrics) {
+ PGOAccuracyMetrics PGOAM(Reader->getSampleCounters(),
+ Binary->getBBAddrMaps(),
+ Binary->getPGOAnalysisMaps());
+ PGOAM.emitPGOAccuracyMetrics();
+ }
+
if (SkipSymbolization)
return EXIT_SUCCESS;
``````````
</details>
https://github.com/llvm/llvm-project/pull/93975
More information about the llvm-commits
mailing list