Commit 88b14731 authored by Leo Yan's avatar Leo Yan Committed by Namhyung Kim
Browse files

perf script: Separate events from branch types



Branch types and events are two different things.  A branch type can be
a conditional branch, an indirect branch, a procedure call, a return, or
an exception taken, etc.  The extra event information is provided for
what happens during a branch, e.g. if a branch is mispredicted or not
taken (specific to conditional branches).

To deliver information about branches, this commit separates events from
branch types.  It parses branch types first, then appends event strings
embraced by the '/' character.  If multiple events occur, the events is
separated with a comma (,).

Also add a minor improvement by adding char 'm' in char array for branch
mispredict event.

Below are extracted sample flags.

Before:
        branch:   br miss
  instructions:   br miss

After:
        branch:   jmp/miss/
  instructions:   jmp/miss/

Reviewed-by: default avatarIan Rogers <irogers@google.com>
Reviewed-by: default avatarJames Clark <james.clark@linaro.org>
Signed-off-by: default avatarLeo Yan <leo.yan@arm.com>
Link: https://lore.kernel.org/r/20250304111240.3378214-4-leo.yan@arm.com


Signed-off-by: default avatarNamhyung Kim <namhyung@kernel.org>
parent 4d598188
Loading
Loading
Loading
Loading
+4 −1
Original line number Diff line number Diff line
@@ -69,7 +69,7 @@ enum {
	PERF_IP_FLAG_BRANCH_MISS	= 1ULL << 15,
};

#define PERF_IP_FLAG_CHARS "bcrosyiABExghDt"
#define PERF_IP_FLAG_CHARS "bcrosyiABExghDtm"

#define PERF_ADDITIONAL_STATE_MASK	\
	(PERF_IP_FLAG_IN_TX |		\
@@ -90,6 +90,9 @@ enum {
	PERF_IP_FLAG_VMENTRY		|\
	PERF_IP_FLAG_VMEXIT)

#define PERF_IP_FLAG_BRACH_EVENT_MASK	\
	PERF_IP_FLAG_BRANCH_MISS

#define PERF_MEM_DATA_SRC_NONE \
	(PERF_MEM_S(OP, NA) |\
	 PERF_MEM_S(LVL, NA) |\
+33 −3
Original line number Diff line number Diff line
@@ -309,7 +309,14 @@ static const struct {
	{PERF_IP_FLAG_BRANCH | PERF_IP_FLAG_TRACE_END, "tr end"},
	{PERF_IP_FLAG_BRANCH | PERF_IP_FLAG_CALL | PERF_IP_FLAG_VMENTRY, "vmentry"},
	{PERF_IP_FLAG_BRANCH | PERF_IP_FLAG_CALL | PERF_IP_FLAG_VMEXIT, "vmexit"},
	{PERF_IP_FLAG_BRANCH | PERF_IP_FLAG_BRANCH_MISS, "br miss"},
	{0, NULL}
};

static const struct {
	u32 flags;
	const char *name;
} branch_events[] = {
	{PERF_IP_FLAG_BRANCH_MISS, "miss"},
	{0, NULL}
};

@@ -317,8 +324,9 @@ static int sample_flags_to_name(u32 flags, char *str, size_t size)
{
	int i;
	const char *prefix;
	int pos = 0, ret;
	int pos = 0, ret, ev_idx = 0;
	u32 xf = flags & PERF_ADDITIONAL_STATE_MASK;
	u32 types, events;
	char xs[16] = { 0 };

	/* Clear additional state bits */
@@ -338,8 +346,9 @@ static int sample_flags_to_name(u32 flags, char *str, size_t size)

	flags &= ~(PERF_IP_FLAG_TRACE_BEGIN | PERF_IP_FLAG_TRACE_END);

	types = flags & ~PERF_IP_FLAG_BRACH_EVENT_MASK;
	for (i = 0; sample_flags[i].name; i++) {
		if (sample_flags[i].flags != flags)
		if (sample_flags[i].flags != types)
			continue;

		ret = snprintf(str + pos, size - pos, "%s", sample_flags[i].name);
@@ -349,6 +358,27 @@ static int sample_flags_to_name(u32 flags, char *str, size_t size)
		break;
	}

	events = flags & PERF_IP_FLAG_BRACH_EVENT_MASK;
	for (i = 0; branch_events[i].name; i++) {
		if (!(branch_events[i].flags & events))
			continue;

		ret = snprintf(str + pos, size - pos, !ev_idx ? "/%s" : ",%s",
			       branch_events[i].name);
		if (ret < 0)
			return ret;
		pos += ret;
		ev_idx++;
	}

	/* Add an end character '/' for events */
	if (ev_idx) {
		ret = snprintf(str + pos, size - pos, "/");
		if (ret < 0)
			return ret;
		pos += ret;
	}

	if (!xf)
		return pos;