[llvm] [BOLT] Adding a unittest that covers Arm SPE PBT aggregation (PR #160095)
Ádám Kallai via llvm-commits
llvm-commits at lists.llvm.org
Tue Sep 30 00:56:56 PDT 2025
https://github.com/kaadam updated https://github.com/llvm/llvm-project/pull/160095
>From 9f1fa8a4f4ca7e4bdd8afa64c4312823f9efe8f9 Mon Sep 17 00:00:00 2001
From: Adam Kallai <kadam at inf.u-szeged.hu>
Date: Tue, 16 Sep 2025 11:09:41 +0200
Subject: [PATCH 1/5] [BOLT] Add unit test for SPE PBT feature
When the SPE previous branch target address (named as PBT) feature is
available, it records the previous branch target before the sampled operation.
One SPE sample by combining this feature, has two entries. It forms a chain
of two consecutive branches. Arm SPE stores the latest branch into
the first entry, and the previous branch address is stored into the second entry.
However PBT doesn't provide as much information as SPE does.
It lacks those information such as the address of source branch, branch type,
and prediction bit. These information filled with zero.
Consider the following example:
FROM/TO/P/-/-/1/COND/- FROM/TO/-/-/-/0//-
0xffff8000807216b4/0xffff800080721704/P/-/-/1/COND/- 0x0/0xffff8000807216ac/-/-/-/0//-
Where the first entry is the newest pair, the second one is the oldest pair.
---
bolt/unittests/Profile/PerfSpeEvents.cpp | 54 ++++++++++++++++++++++++
1 file changed, 54 insertions(+)
diff --git a/bolt/unittests/Profile/PerfSpeEvents.cpp b/bolt/unittests/Profile/PerfSpeEvents.cpp
index 8d023cd7b7e74..0c1ddbd67b88c 100644
--- a/bolt/unittests/Profile/PerfSpeEvents.cpp
+++ b/bolt/unittests/Profile/PerfSpeEvents.cpp
@@ -161,4 +161,58 @@ TEST_F(PerfSpeEventsTestHelper, SpeBranchesWithBrstack) {
parseAndCheckBrstackEvents(1234, ExpectedSamples);
}
+TEST_F(PerfSpeEventsTestHelper, SpeBranchesWithBrstackAndPbt) {
+ // Check perf input with SPE branch events as brstack format by
+ // combining with the previous branch target address (named as PBT).
+ // Example collection command:
+ // ```
+ // perf record -e 'arm_spe_0/branch_filter=1/u' -- BINARY
+ // ```
+ // How Bolt extracts the branch events:
+ // ```
+ // perf script -F pid,brstack --itrace=bl
+ // ```
+
+ opts::ArmSPE = true;
+ opts::ReadPerfEvents =
+ " 4567 0xa002/0xa003/PN/-/-/10/COND/- 0x0/0xa001/-/-/-/0//-\n"
+ " 4567 0xb002/0xb003/P/-/-/4/RET/- 0x0/0xb001/-/-/-/0//-\n"
+ " 4567 0xc456/0xc789/P/-/-/13/-/- 0x0/0xc123/-/-/-/0//-\n"
+ " 4567 0xd456/0xd789/M/-/-/7/RET/- 0x0/0xd123/-/-/-/0//-\n"
+ " 4567 0xe005/0xe009/P/-/-/14/RET/- 0x0/0xe001/-/-/-/0//-\n"
+ " 4567 0xd456/0xd789/M/-/-/7/RET/- 0x0/0xd123/-/-/-/0//-\n"
+ " 4567 0xf002/0xf003/MN/-/-/8/COND/- 0x0/0xf001/-/-/-/0//-\n"
+ " 4567 0xc456/0xc789/P/-/-/13/-/- 0x0/0xc123/-/-/-/0//-\n";
+
+ // ExpectedSamples contains the aggregated information about
+ // a branch {{From, To, TraceTo}, {TakenCount, MispredCount}}.
+ // If the PBT feture is availabe, an SPE sample has two entries.
+ // These two entries form a chain of two consecutive branches.
+ // However PBT lacks associated information such as branch
+ // source address, branch type, and prediction bit.
+ // For the first branch stack, please see the description above.
+ // Consider this example for PBT trace: {{0x0, 0xc123, 0xc456}, {2, 0}}.
+ // This entry has a TakenCount = 2, as we have two samples for
+ // this entry (0x0,d123) in our input. It has MispredsCount = 0,
+ // as it lacks prediction information.
+ // It also has no infromation about source branch address therefore
+ // the 'From' field filled with zero (0x0).
+ // TraceTo = 0xc456, means the execution jumped from 0xc123 to 0xc456.
+ std::vector<std::pair<Trace, TakenBranchInfo>> ExpectedSamples = {
+ {{0xa002, 0xa003, Trace::BR_ONLY}, {1, 0}},
+ {{0x0, 0xa001, 0xa002}, {1, 0}},
+ {{0xb002, 0xb003, Trace::BR_ONLY}, {1, 0}},
+ {{0x0, 0xb001, 0xb002}, {1, 0}},
+ {{0xc456, 0xc789, Trace::BR_ONLY}, {2, 0}},
+ {{0x0, 0xc123, 0xc456}, {2, 0}},
+ {{0xd456, 0xd789, Trace::BR_ONLY}, {2, 2}},
+ {{0x0, 0xd123, 0xd456}, {2, 0}},
+ {{0xe005, 0xe009, Trace::BR_ONLY}, {1, 0}},
+ {{0x0, 0xe001, 0xe005}, {1, 0}},
+ {{0xf002, 0xf003, Trace::BR_ONLY}, {1, 1}},
+ {{0x0, 0xf001, 0xf002}, {1, 0}}};
+
+ parseAndCheckBrstackEvents(4567, ExpectedSamples);
+}
+
#endif
>From deb242168c622af2116ca5173a48d38c721b3b63 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=C3=81d=C3=A1m=20Kallai?= <kadam at inf.u-szeged.hu>
Date: Fri, 26 Sep 2025 10:14:08 +0200
Subject: [PATCH 2/5] Fixes typo
Co-authored-by: Paschalis Mpeis <paschalis.mpeis at gmail.com>
---
bolt/unittests/Profile/PerfSpeEvents.cpp | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/bolt/unittests/Profile/PerfSpeEvents.cpp b/bolt/unittests/Profile/PerfSpeEvents.cpp
index 0c1ddbd67b88c..892c69b0d9c25 100644
--- a/bolt/unittests/Profile/PerfSpeEvents.cpp
+++ b/bolt/unittests/Profile/PerfSpeEvents.cpp
@@ -195,7 +195,7 @@ TEST_F(PerfSpeEventsTestHelper, SpeBranchesWithBrstackAndPbt) {
// This entry has a TakenCount = 2, as we have two samples for
// this entry (0x0,d123) in our input. It has MispredsCount = 0,
// as it lacks prediction information.
- // It also has no infromation about source branch address therefore
+ // It also has no information about source branch address therefore
// the 'From' field filled with zero (0x0).
// TraceTo = 0xc456, means the execution jumped from 0xc123 to 0xc456.
std::vector<std::pair<Trace, TakenBranchInfo>> ExpectedSamples = {
>From 673dd8a9e0b68e7243d1e2af7e60c77d454bfe64 Mon Sep 17 00:00:00 2001
From: Adam Kallai <kadam at inf.u-szeged.hu>
Date: Mon, 29 Sep 2025 17:55:58 +0200
Subject: [PATCH 3/5] Rewriting the test descritpion.
---
bolt/unittests/Profile/PerfSpeEvents.cpp | 26 ++++++++++++++++--------
1 file changed, 18 insertions(+), 8 deletions(-)
diff --git a/bolt/unittests/Profile/PerfSpeEvents.cpp b/bolt/unittests/Profile/PerfSpeEvents.cpp
index 892c69b0d9c25..00500ff91bd69 100644
--- a/bolt/unittests/Profile/PerfSpeEvents.cpp
+++ b/bolt/unittests/Profile/PerfSpeEvents.cpp
@@ -175,6 +175,7 @@ TEST_F(PerfSpeEventsTestHelper, SpeBranchesWithBrstackAndPbt) {
opts::ArmSPE = true;
opts::ReadPerfEvents =
+ // " <PID> <SRC>/<DEST>/PN/-/-/10/COND/- <NULL>/<PBT>/-/-/-/0//-\n"
" 4567 0xa002/0xa003/PN/-/-/10/COND/- 0x0/0xa001/-/-/-/0//-\n"
" 4567 0xb002/0xb003/P/-/-/4/RET/- 0x0/0xb001/-/-/-/0//-\n"
" 4567 0xc456/0xc789/P/-/-/13/-/- 0x0/0xc123/-/-/-/0//-\n"
@@ -187,17 +188,26 @@ TEST_F(PerfSpeEventsTestHelper, SpeBranchesWithBrstackAndPbt) {
// ExpectedSamples contains the aggregated information about
// a branch {{From, To, TraceTo}, {TakenCount, MispredCount}}.
// If the PBT feture is availabe, an SPE sample has two entries.
+ // Arm SPE records SRC/DEST addresses of the latest sampled branch
+ // operation, and it stores into the first entry. PBT record the target
+ // address of most recently taken branch in program order before the sampled
+ // operation, it placed into the second entry.
// These two entries form a chain of two consecutive branches.
// However PBT lacks associated information such as branch
// source address, branch type, and prediction bit.
- // For the first branch stack, please see the description above.
- // Consider this example for PBT trace: {{0x0, 0xc123, 0xc456}, {2, 0}}.
- // This entry has a TakenCount = 2, as we have two samples for
- // this entry (0x0,d123) in our input. It has MispredsCount = 0,
- // as it lacks prediction information.
- // It also has no information about source branch address therefore
- // the 'From' field filled with zero (0x0).
- // TraceTo = 0xc456, means the execution jumped from 0xc123 to 0xc456.
+ // Considering this Trace pair:
+ // {{0xd456, 0xd789, Trace::BR_ONLY}, {2, 2}},
+ // {{0x0, 0xd123, 0xd456}, {2, 0}}
+ // For SPE trace please see the description above.
+ // In the example the second entry is the PBT trace:
+ // {{0x0, 0xd123, 0xd456}, {2, 0}}.
+ // The PBT entry has a TakenCount = 2, as we have two samples for
+ // (0x0, 0xd123) entry in our input. The 'MispredsCount = 0' is
+ // always zero, as it lacks prediction information.
+ // It also has no infromation about source branch address therefore
+ // the 'From' field is always filled with zero (0x0).
+ // TraceTo = 0xc456, means the execution jumped from
+ // 0xc123 (PBT) to 0xc456 (SRC), and jumped further to 0xd789 (DEST).
std::vector<std::pair<Trace, TakenBranchInfo>> ExpectedSamples = {
{{0xa002, 0xa003, Trace::BR_ONLY}, {1, 0}},
{{0x0, 0xa001, 0xa002}, {1, 0}},
>From f5cbcd815599d5d45330a9808f4e3e4071373325 Mon Sep 17 00:00:00 2001
From: Adam Kallai <kadam at inf.u-szeged.hu>
Date: Tue, 30 Sep 2025 08:33:48 +0200
Subject: [PATCH 4/5] Fix the format
---
bolt/unittests/Profile/PerfSpeEvents.cpp | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/bolt/unittests/Profile/PerfSpeEvents.cpp b/bolt/unittests/Profile/PerfSpeEvents.cpp
index 00500ff91bd69..a1a68abcfdc9f 100644
--- a/bolt/unittests/Profile/PerfSpeEvents.cpp
+++ b/bolt/unittests/Profile/PerfSpeEvents.cpp
@@ -175,7 +175,7 @@ TEST_F(PerfSpeEventsTestHelper, SpeBranchesWithBrstackAndPbt) {
opts::ArmSPE = true;
opts::ReadPerfEvents =
- // " <PID> <SRC>/<DEST>/PN/-/-/10/COND/- <NULL>/<PBT>/-/-/-/0//-\n"
+ // "<PID> <SRC>/<DEST>/PN/-/-/10/COND/- <NULL>/<PBT>/-/-/-/0//-\n"
" 4567 0xa002/0xa003/PN/-/-/10/COND/- 0x0/0xa001/-/-/-/0//-\n"
" 4567 0xb002/0xb003/P/-/-/4/RET/- 0x0/0xb001/-/-/-/0//-\n"
" 4567 0xc456/0xc789/P/-/-/13/-/- 0x0/0xc123/-/-/-/0//-\n"
>From 2e8c920fe81ba54fad00c03e6ca0cc593ab74764 Mon Sep 17 00:00:00 2001
From: Adam Kallai <kadam at inf.u-szeged.hu>
Date: Tue, 30 Sep 2025 09:55:23 +0200
Subject: [PATCH 5/5] Fix typo (2)
---
bolt/unittests/Profile/PerfSpeEvents.cpp | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/bolt/unittests/Profile/PerfSpeEvents.cpp b/bolt/unittests/Profile/PerfSpeEvents.cpp
index a1a68abcfdc9f..871e4736a30c4 100644
--- a/bolt/unittests/Profile/PerfSpeEvents.cpp
+++ b/bolt/unittests/Profile/PerfSpeEvents.cpp
@@ -187,7 +187,7 @@ TEST_F(PerfSpeEventsTestHelper, SpeBranchesWithBrstackAndPbt) {
// ExpectedSamples contains the aggregated information about
// a branch {{From, To, TraceTo}, {TakenCount, MispredCount}}.
- // If the PBT feture is availabe, an SPE sample has two entries.
+ // If the PBT feature is available, an SPE sample has two entries.
// Arm SPE records SRC/DEST addresses of the latest sampled branch
// operation, and it stores into the first entry. PBT record the target
// address of most recently taken branch in program order before the sampled
More information about the llvm-commits
mailing list