[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
Fri Sep 26 01:14:16 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/2] [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/2] 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 = {



More information about the llvm-commits mailing list