[PATCH v2 06/14] perf cs-etm: Mark branches that were not taken

From: Leo Yan

Date: Wed Sep 23 2026 - 11:45:10 EST


An exception can transfer execution to the kernel after any instruction.
When this creates a trace boundary, perf may attribute the trace-end
sample to the last instruction in the range. If that instruction is an
untaken branch, reporting only its branch type can make the transfer look
like a taken branch.

Set PERF_IP_FLAG_NOT_TAKEN for branch ranges when
last_instr_taken_branch is false. This records the decoded branch
outcome independently of exception entry.

For a discontinuity without an exception element, perf script previously
reported an untaken B.LS as:

tr end jcc 4000f8 => 0 b.ls #0x400118
tr strt jmp 0 => 4000fc

With the not-taken flag set:

tr end jcc/not_taken/ 4000f8 => 0 b.ls #0x400118
tr strt jmp 0 => 4000fc

Here, 4000f8 remains the last traced instruction and 4000fc is the trace
restart address. These boundary samples do not establish an IRQ entry or
an exception return; the not_taken flag records only the branch outcome.

Assisted-by: Codex:gpt-6
Signed-off-by: Leo Yan <leo.yan@xxxxxxx>
---
tools/perf/util/cs-etm.c | 5 +++++
1 file changed, 5 insertions(+)

diff --git a/tools/perf/util/cs-etm.c b/tools/perf/util/cs-etm.c
index 0163d93ac2d537a2190536e77d24628b4d707751..c54218aeef53e8420447e9a2bee6e98d8225e335 100644
--- a/tools/perf/util/cs-etm.c
+++ b/tools/perf/util/cs-etm.c
@@ -2415,6 +2415,11 @@ static int cs_etm__set_sample_flags(struct cs_etm_queue *etmq,
packet->flags = PERF_IP_FLAG_BRANCH |
PERF_IP_FLAG_RETURN;

+ /* Report branch that is not taken */
+ if ((packet->flags & PERF_IP_FLAG_BRANCH) &&
+ !packet->last_instr_taken_branch)
+ packet->flags |= PERF_IP_FLAG_NOT_TAKEN;
+
/*
* Decoder might insert a discontinuity in the middle of
* instruction packets, fixup prev_packet with flag

--
2.34.1