Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > linux.kernel > #1626968 > unrolled thread
| Started by | Jin Yao <yao.jin@linux.intel.com> |
|---|---|
| First post | 2017-04-20 06:20 +0200 |
| Last post | 2017-04-23 10:40 +0200 |
| Articles | 8 — 3 participants |
Back to article view | Back to linux.kernel
[PATCH v6 0/7] perf report: Show branch type Jin Yao <yao.jin@linux.intel.com> - 2017-04-20 06:20 +0200
[PATCH v6 1/7] perf/core: Define the common branch type classification Jin Yao <yao.jin@linux.intel.com> - 2017-04-20 06:20 +0200
[PATCH v6 6/7] perf report: Show branch type statistics for stdio mode Jin Yao <yao.jin@linux.intel.com> - 2017-04-20 06:20 +0200
[PATCH v6 2/7] perf/x86/intel: Record branch type Jin Yao <yao.jin@linux.intel.com> - 2017-04-20 06:20 +0200
Re: [PATCH v6 2/7] perf/x86/intel: Record branch type Jiri Olsa <jolsa@redhat.com> - 2017-04-23 16:00 +0200
Re: [PATCH v6 2/7] perf/x86/intel: Record branch type "Jin, Yao" <yao.jin@linux.intel.com> - 2017-04-24 02:50 +0200
Re: [PATCH v6 0/7] perf report: Show branch type Jiri Olsa <jolsa@redhat.com> - 2017-04-20 11:40 +0200
Re: [PATCH v6 0/7] perf report: Show branch type "Jin, Yao" <yao.jin@linux.intel.com> - 2017-04-23 10:40 +0200
| From | Jin Yao <yao.jin@linux.intel.com> |
|---|---|
| Date | 2017-04-20 06:20 +0200 |
| Subject | [PATCH v6 0/7] perf report: Show branch type |
| Message-ID | <tybJv-4aP-3@gated-at.bofh.it> |
v6:
Update according to the review comments from
Jiri Olsa <jolsa@redhat.com>. Major modifications are:
1. Move that multiline conditional code inside {} brackets.
2. Move branch_type_stat_display() from builtin-report.c to
branch.c. Move branch_type_str() from callchain.c to
branch.c.
3. Keep the original branch info display order, that is:
predicted, abort, cycles, iterations
v5:
---
Mainly the v5 patch series are updated according to
comments from Jiri Olsa <jolsa@redhat.com>.
The kernel part doesn't have functional change. It just
solve the merge issue.
In userspace, the functions of branch type counting and
branch type name resolving are moved to the new files:
util/branch.c, util/branch.h.
And refactor the branch info printing code for better
maintenance.
Not changed (or just fix merge issue):
perf/core: Define the common branch type classification
perf/x86/intel: Record branch type
perf record: Create a new option save_type in --branch-filter
New patches:
perf report: Refactor the branch info printing code
perf util: Create branch.c/.h for common branch functions
Changed:
perf report: Show branch type statistics for stdio mode
perf report: Show branch type in callchain entry
v4:
---
1. Describe the major changes in patch description.
Thanks for Peter Zijlstra's reminding.
2. Initialize branch type to 0 in intel_pmu_lbr_read_32 and
intel_pmu_lbr_read_64. Remove the invalid else code in
intel_pmu_lbr_filter.
v3:
---
1. Move the JCC forward/backward and cross page computing from
kernel to userspace.
2. Use lookup table to replace original switch/case processing.
Changed:
perf/core: Define the common branch type classification
perf/x86/intel: Record branch type
perf report: Show branch type statistics for stdio mode
perf report: Show branch type in callchain entry
Not changed:
perf record: Create a new option save_type in --branch-filter
v2:
---
1. Use 4 bits in perf_branch_entry to record branch type.
2. Pull out some common branch types from FAR_BRANCH. Now the branch
types defined in perf_event.h:
Jin Yao (7):
perf/core: Define the common branch type classification
perf/x86/intel: Record branch type
perf record: Create a new option save_type in --branch-filter
perf report: Refactor the branch info printing code
perf util: Create branch.c/.h for common branch functions
perf report: Show branch type statistics for stdio mode
perf report: Show branch type in callchain entry
arch/x86/events/intel/lbr.c | 53 +++++++++-
include/uapi/linux/perf_event.h | 29 +++++-
tools/include/uapi/linux/perf_event.h | 29 +++++-
tools/perf/Documentation/perf-record.txt | 1 +
tools/perf/builtin-report.c | 25 +++++
tools/perf/util/Build | 1 +
tools/perf/util/branch.c | 168 +++++++++++++++++++++++++++++++
tools/perf/util/branch.h | 25 +++++
tools/perf/util/callchain.c | 140 ++++++++++++++------------
tools/perf/util/callchain.h | 5 +-
tools/perf/util/event.h | 3 +-
tools/perf/util/hist.c | 5 +-
tools/perf/util/machine.c | 26 +++--
tools/perf/util/parse-branch-options.c | 1 +
14 files changed, 427 insertions(+), 84 deletions(-)
create mode 100644 tools/perf/util/branch.c
create mode 100644 tools/perf/util/branch.h
--
2.7.4
[toc] | [next] | [standalone]
| From | Jin Yao <yao.jin@linux.intel.com> |
|---|---|
| Date | 2017-04-20 06:20 +0200 |
| Subject | [PATCH v6 1/7] perf/core: Define the common branch type classification |
| Message-ID | <tybJv-4aP-17@gated-at.bofh.it> |
| In reply to | #1626968 |
It is often useful to know the branch types while analyzing branch
data. For example, a call is very different from a conditional branch.
Currently we have to look it up in binary while the binary may later
not be available and even the binary is available but user has to take
some time. It is very useful for user to check it directly in perf
report.
Perf already has support for disassembling the branch instruction
to get the x86 branch type.
To keep consistent on kernel and userspace and make the classification
more common, the patch adds the common branch type classification
in perf_event.h.
PERF_BR_NONE : unknown
PERF_BR_JCC : conditional jump
PERF_BR_JMP : jump
PERF_BR_IND_JMP : indirect jump
PERF_BR_CALL : call
PERF_BR_IND_CALL : indirect call
PERF_BR_RET : return
PERF_BR_SYSCALL : syscall
PERF_BR_SYSRET : syscall return
PERF_BR_IRQ : hw interrupt/trap/fault
PERF_BR_INT : sw interrupt
PERF_BR_IRET : return from interrupt
PERF_BR_FAR_BRANCH: not generic far branch type
The patch also adds a new field type (4 bits) in perf_branch_entry
to record the branch type.
Since the disassembling of branch instruction needs some overhead,
a new PERF_SAMPLE_BRANCH_TYPE_SAVE is introduced to indicate if it
needs to disassemble the branch instruction and record the branch
type.
Change log
----------
v6: Not changed.
v5: Not changed. The v5 patch series just change the userspace.
v4: Comparing to previous version, the major changes are:
1. Remove the PERF_BR_JCC_FWD/PERF_BR_JCC_BWD, they will be
computed later in userspace.
2. Remove the "cross" field in perf_branch_entry. The cross page
computing will be done later in userspace.
Signed-off-by: Jin Yao <yao.jin@linux.intel.com>
---
include/uapi/linux/perf_event.h | 29 ++++++++++++++++++++++++++++-
tools/include/uapi/linux/perf_event.h | 29 ++++++++++++++++++++++++++++-
2 files changed, 56 insertions(+), 2 deletions(-)
diff --git a/include/uapi/linux/perf_event.h b/include/uapi/linux/perf_event.h
index d09a9cd..69af012 100644
--- a/include/uapi/linux/perf_event.h
+++ b/include/uapi/linux/perf_event.h
@@ -174,6 +174,8 @@ enum perf_branch_sample_type_shift {
PERF_SAMPLE_BRANCH_NO_FLAGS_SHIFT = 14, /* no flags */
PERF_SAMPLE_BRANCH_NO_CYCLES_SHIFT = 15, /* no cycles */
+ PERF_SAMPLE_BRANCH_TYPE_SAVE_SHIFT = 16, /* save branch type */
+
PERF_SAMPLE_BRANCH_MAX_SHIFT /* non-ABI */
};
@@ -198,9 +200,32 @@ enum perf_branch_sample_type {
PERF_SAMPLE_BRANCH_NO_FLAGS = 1U << PERF_SAMPLE_BRANCH_NO_FLAGS_SHIFT,
PERF_SAMPLE_BRANCH_NO_CYCLES = 1U << PERF_SAMPLE_BRANCH_NO_CYCLES_SHIFT,
+ PERF_SAMPLE_BRANCH_TYPE_SAVE =
+ 1U << PERF_SAMPLE_BRANCH_TYPE_SAVE_SHIFT,
+
PERF_SAMPLE_BRANCH_MAX = 1U << PERF_SAMPLE_BRANCH_MAX_SHIFT,
};
+/*
+ * Common flow change classification
+ */
+enum {
+ PERF_BR_NONE = 0, /* unknown */
+ PERF_BR_JCC = 1, /* conditional jump */
+ PERF_BR_JMP = 2, /* jump */
+ PERF_BR_IND_JMP = 3, /* indirect jump */
+ PERF_BR_CALL = 4, /* call */
+ PERF_BR_IND_CALL = 5, /* indirect call */
+ PERF_BR_RET = 6, /* return */
+ PERF_BR_SYSCALL = 7, /* syscall */
+ PERF_BR_SYSRET = 8, /* syscall return */
+ PERF_BR_IRQ = 9, /* hw interrupt/trap/fault */
+ PERF_BR_INT = 10, /* sw interrupt */
+ PERF_BR_IRET = 11, /* return from interrupt */
+ PERF_BR_FAR_BRANCH = 12, /* not generic far branch type */
+ PERF_BR_MAX,
+};
+
#define PERF_SAMPLE_BRANCH_PLM_ALL \
(PERF_SAMPLE_BRANCH_USER|\
PERF_SAMPLE_BRANCH_KERNEL|\
@@ -999,6 +1024,7 @@ union perf_mem_data_src {
* in_tx: running in a hardware transaction
* abort: aborting a hardware transaction
* cycles: cycles from last branch (or 0 if not supported)
+ * type: branch type
*/
struct perf_branch_entry {
__u64 from;
@@ -1008,7 +1034,8 @@ struct perf_branch_entry {
in_tx:1, /* in transaction */
abort:1, /* transaction abort */
cycles:16, /* cycle count to last branch */
- reserved:44;
+ type:4, /* branch type */
+ reserved:40;
};
#endif /* _UAPI_LINUX_PERF_EVENT_H */
diff --git a/tools/include/uapi/linux/perf_event.h b/tools/include/uapi/linux/perf_event.h
index d09a9cd..69af012 100644
--- a/tools/include/uapi/linux/perf_event.h
+++ b/tools/include/uapi/linux/perf_event.h
@@ -174,6 +174,8 @@ enum perf_branch_sample_type_shift {
PERF_SAMPLE_BRANCH_NO_FLAGS_SHIFT = 14, /* no flags */
PERF_SAMPLE_BRANCH_NO_CYCLES_SHIFT = 15, /* no cycles */
+ PERF_SAMPLE_BRANCH_TYPE_SAVE_SHIFT = 16, /* save branch type */
+
PERF_SAMPLE_BRANCH_MAX_SHIFT /* non-ABI */
};
@@ -198,9 +200,32 @@ enum perf_branch_sample_type {
PERF_SAMPLE_BRANCH_NO_FLAGS = 1U << PERF_SAMPLE_BRANCH_NO_FLAGS_SHIFT,
PERF_SAMPLE_BRANCH_NO_CYCLES = 1U << PERF_SAMPLE_BRANCH_NO_CYCLES_SHIFT,
+ PERF_SAMPLE_BRANCH_TYPE_SAVE =
+ 1U << PERF_SAMPLE_BRANCH_TYPE_SAVE_SHIFT,
+
PERF_SAMPLE_BRANCH_MAX = 1U << PERF_SAMPLE_BRANCH_MAX_SHIFT,
};
+/*
+ * Common flow change classification
+ */
+enum {
+ PERF_BR_NONE = 0, /* unknown */
+ PERF_BR_JCC = 1, /* conditional jump */
+ PERF_BR_JMP = 2, /* jump */
+ PERF_BR_IND_JMP = 3, /* indirect jump */
+ PERF_BR_CALL = 4, /* call */
+ PERF_BR_IND_CALL = 5, /* indirect call */
+ PERF_BR_RET = 6, /* return */
+ PERF_BR_SYSCALL = 7, /* syscall */
+ PERF_BR_SYSRET = 8, /* syscall return */
+ PERF_BR_IRQ = 9, /* hw interrupt/trap/fault */
+ PERF_BR_INT = 10, /* sw interrupt */
+ PERF_BR_IRET = 11, /* return from interrupt */
+ PERF_BR_FAR_BRANCH = 12, /* not generic far branch type */
+ PERF_BR_MAX,
+};
+
#define PERF_SAMPLE_BRANCH_PLM_ALL \
(PERF_SAMPLE_BRANCH_USER|\
PERF_SAMPLE_BRANCH_KERNEL|\
@@ -999,6 +1024,7 @@ union perf_mem_data_src {
* in_tx: running in a hardware transaction
* abort: aborting a hardware transaction
* cycles: cycles from last branch (or 0 if not supported)
+ * type: branch type
*/
struct perf_branch_entry {
__u64 from;
@@ -1008,7 +1034,8 @@ struct perf_branch_entry {
in_tx:1, /* in transaction */
abort:1, /* transaction abort */
cycles:16, /* cycle count to last branch */
- reserved:44;
+ type:4, /* branch type */
+ reserved:40;
};
#endif /* _UAPI_LINUX_PERF_EVENT_H */
--
2.7.4
[toc] | [prev] | [next] | [standalone]
| From | Jin Yao <yao.jin@linux.intel.com> |
|---|---|
| Date | 2017-04-20 06:20 +0200 |
| Subject | [PATCH v6 6/7] perf report: Show branch type statistics for stdio mode |
| Message-ID | <tybJw-4aP-21@gated-at.bofh.it> |
| In reply to | #1626968 |
Show the branch type statistics at the end of perf report --stdio.
For example:
perf report --stdio
JCC forward: 27.6%
JCC backward: 10.0%
CROSS_4K: 0.0%
CROSS_2M: 14.3%
JCC: 37.6%
JMP: 0.0%
IND_JMP: 6.5%
CALL: 26.6%
IND_CALL: 0.0%
RET: 29.3%
The branch types are:
---------------------
JCC forward: Conditional forward jump
JCC backward: Conditional backward jump
JMP: Jump imm
IND_JMP: Jump reg/mem
CALL: Call imm
IND_CALL: Call reg/mem
RET: Ret
SYSCALL: Syscall
SYSRET: Syscall return
IRQ: HW interrupt/trap/fault
INT: SW interrupt
IRET: Return from interrupt
FAR_BRANCH: Others not generic branch type
CROSS_4K and CROSS_2M:
----------------------
They are the metrics checking for branches cross 4K or 2MB pages.
It's an approximate computing. We don't know if the area is 4K or
2MB, so always compute both.
To make the output simple, if a branch crosses 2M area, CROSS_4K
will not be incremented.
Change log
----------
v6: Remove branch_type_stat_display() since it's moved to branch.c.
v5: Remove the unnecessary sort__mode checking in
hist_iter__branch_callback().
v4: Comparing to previous version, the major changes are:
Add the computing of JCC forward/JCC backward and cross page checking
by using the from and to addresses.
Signed-off-by: Jin Yao <yao.jin@linux.intel.com>
---
tools/perf/builtin-report.c | 25 +++++++++++++++++++++++++
tools/perf/util/hist.c | 5 +----
2 files changed, 26 insertions(+), 4 deletions(-)
diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c
index 5bbd4b2..ba5026a 100644
--- a/tools/perf/builtin-report.c
+++ b/tools/perf/builtin-report.c
@@ -37,6 +37,7 @@
#include "arch/common.h"
#include "util/time-utils.h"
#include "util/auxtrace.h"
+#include "util/branch.h"
#include <dlfcn.h>
#include <errno.h>
@@ -68,6 +69,7 @@ struct report {
u64 queue_size;
int socket_filter;
DECLARE_BITMAP(cpu_bitmap, MAX_NR_CPUS);
+ struct branch_type_stat brtype_stat;
};
static int report__config(const char *var, const char *value, void *cb)
@@ -146,6 +148,22 @@ static int hist_iter__report_callback(struct hist_entry_iter *iter,
return err;
}
+static int hist_iter__branch_callback(struct hist_entry_iter *iter,
+ struct addr_location *al __maybe_unused,
+ bool single __maybe_unused,
+ void *arg)
+{
+ struct hist_entry *he = iter->he;
+ struct report *rep = arg;
+ struct branch_info *bi;
+
+ bi = he->branch_info;
+ branch_type_count(&rep->brtype_stat, &bi->flags,
+ bi->from.addr, bi->to.addr);
+
+ return 0;
+}
+
static int process_sample_event(struct perf_tool *tool,
union perf_event *event,
struct perf_sample *sample,
@@ -184,6 +202,8 @@ static int process_sample_event(struct perf_tool *tool,
*/
if (!sample->branch_stack)
goto out_put;
+
+ iter.add_entry_cb = hist_iter__branch_callback;
iter.ops = &hist_iter_branch;
} else if (rep->mem_mode) {
iter.ops = &hist_iter_mem;
@@ -406,6 +426,9 @@ static int perf_evlist__tty_browse_hists(struct perf_evlist *evlist,
perf_read_values_destroy(&rep->show_threads_values);
}
+ if (sort__mode == SORT_MODE__BRANCH)
+ branch_type_stat_display(stdout, &rep->brtype_stat);
+
return 0;
}
@@ -938,6 +961,8 @@ int cmd_report(int argc, const char **argv)
if (has_br_stack && branch_call_mode)
symbol_conf.show_branchflag_count = true;
+ memset(&report.brtype_stat, 0, sizeof(struct branch_type_stat));
+
/*
* Branch mode is a tristate:
* -1 means default, so decide based on the file having branch data.
diff --git a/tools/perf/util/hist.c b/tools/perf/util/hist.c
index 65d4275..f3a3be5 100644
--- a/tools/perf/util/hist.c
+++ b/tools/perf/util/hist.c
@@ -747,12 +747,9 @@ iter_prepare_branch_entry(struct hist_entry_iter *iter, struct addr_location *al
}
static int
-iter_add_single_branch_entry(struct hist_entry_iter *iter,
+iter_add_single_branch_entry(struct hist_entry_iter *iter __maybe_unused,
struct addr_location *al __maybe_unused)
{
- /* to avoid calling callback function */
- iter->he = NULL;
-
return 0;
}
--
2.7.4
[toc] | [prev] | [next] | [standalone]
| From | Jin Yao <yao.jin@linux.intel.com> |
|---|---|
| Date | 2017-04-20 06:20 +0200 |
| Subject | [PATCH v6 2/7] perf/x86/intel: Record branch type |
| Message-ID | <tybJv-4aP-19@gated-at.bofh.it> |
| In reply to | #1626968 |
Perf already has support for disassembling the branch instruction
and using the branch type for filtering. The patch just records
the branch type in perf_branch_entry.
Before recording, the patch converts the x86 branch type to
common branch type.
Change log
----------
v6: Not changed.
v5: Just fix the merge error. No other update.
v4: Comparing to previous version, the major changes are:
1. Uses a lookup table to convert x86 branch type to common branch
type.
2. Move the JCC forward/JCC backward and cross page computing to
user space.
3. Initialize branch type to 0 in intel_pmu_lbr_read_32 and
intel_pmu_lbr_read_64
Signed-off-by: Jin Yao <yao.jin@linux.intel.com>
---
arch/x86/events/intel/lbr.c | 53 ++++++++++++++++++++++++++++++++++++++++++++-
1 file changed, 52 insertions(+), 1 deletion(-)
diff --git a/arch/x86/events/intel/lbr.c b/arch/x86/events/intel/lbr.c
index f924629..f10a7ed 100644
--- a/arch/x86/events/intel/lbr.c
+++ b/arch/x86/events/intel/lbr.c
@@ -109,6 +109,9 @@ enum {
X86_BR_ZERO_CALL = 1 << 15,/* zero length call */
X86_BR_CALL_STACK = 1 << 16,/* call stack */
X86_BR_IND_JMP = 1 << 17,/* indirect jump */
+
+ X86_BR_TYPE_SAVE = 1 << 18,/* indicate to save branch type */
+
};
#define X86_BR_PLM (X86_BR_USER | X86_BR_KERNEL)
@@ -510,6 +513,7 @@ static void intel_pmu_lbr_read_32(struct cpu_hw_events *cpuc)
cpuc->lbr_entries[i].in_tx = 0;
cpuc->lbr_entries[i].abort = 0;
cpuc->lbr_entries[i].cycles = 0;
+ cpuc->lbr_entries[i].type = 0;
cpuc->lbr_entries[i].reserved = 0;
}
cpuc->lbr_stack.nr = i;
@@ -596,6 +600,7 @@ static void intel_pmu_lbr_read_64(struct cpu_hw_events *cpuc)
cpuc->lbr_entries[out].in_tx = in_tx;
cpuc->lbr_entries[out].abort = abort;
cpuc->lbr_entries[out].cycles = cycles;
+ cpuc->lbr_entries[out].type = 0;
cpuc->lbr_entries[out].reserved = 0;
out++;
}
@@ -673,6 +678,10 @@ static int intel_pmu_setup_sw_lbr_filter(struct perf_event *event)
if (br_type & PERF_SAMPLE_BRANCH_CALL)
mask |= X86_BR_CALL | X86_BR_ZERO_CALL;
+
+ if (br_type & PERF_SAMPLE_BRANCH_TYPE_SAVE)
+ mask |= X86_BR_TYPE_SAVE;
+
/*
* stash actual user request into reg, it may
* be used by fixup code for some CPU
@@ -926,6 +935,44 @@ static int branch_type(unsigned long from, unsigned long to, int abort)
return ret;
}
+#define X86_BR_TYPE_MAP_MAX 16
+
+static int
+common_branch_type(int type)
+{
+ int i, mask;
+ const int branch_map[X86_BR_TYPE_MAP_MAX] = {
+ PERF_BR_CALL, /* X86_BR_CALL */
+ PERF_BR_RET, /* X86_BR_RET */
+ PERF_BR_SYSCALL, /* X86_BR_SYSCALL */
+ PERF_BR_SYSRET, /* X86_BR_SYSRET */
+ PERF_BR_INT, /* X86_BR_INT */
+ PERF_BR_IRET, /* X86_BR_IRET */
+ PERF_BR_JCC, /* X86_BR_JCC */
+ PERF_BR_JMP, /* X86_BR_JMP */
+ PERF_BR_IRQ, /* X86_BR_IRQ */
+ PERF_BR_IND_CALL, /* X86_BR_IND_CALL */
+ PERF_BR_NONE, /* X86_BR_ABORT */
+ PERF_BR_NONE, /* X86_BR_IN_TX */
+ PERF_BR_NONE, /* X86_BR_NO_TX */
+ PERF_BR_CALL, /* X86_BR_ZERO_CALL */
+ PERF_BR_NONE, /* X86_BR_CALL_STACK */
+ PERF_BR_IND_JMP, /* X86_BR_IND_JMP */
+ };
+
+ type >>= 2; /* skip X86_BR_USER and X86_BR_KERNEL */
+ mask = ~(~0 << 1);
+
+ for (i = 0; i < X86_BR_TYPE_MAP_MAX; i++) {
+ if (type & mask)
+ return branch_map[i];
+
+ type >>= 1;
+ }
+
+ return PERF_BR_NONE;
+}
+
/*
* implement actual branch filter based on user demand.
* Hardware may not exactly satisfy that request, thus
@@ -942,7 +989,8 @@ intel_pmu_lbr_filter(struct cpu_hw_events *cpuc)
bool compress = false;
/* if sampling all branches, then nothing to filter */
- if ((br_sel & X86_BR_ALL) == X86_BR_ALL)
+ if (((br_sel & X86_BR_ALL) == X86_BR_ALL) &&
+ ((br_sel & X86_BR_TYPE_SAVE) != X86_BR_TYPE_SAVE))
return;
for (i = 0; i < cpuc->lbr_stack.nr; i++) {
@@ -963,6 +1011,9 @@ intel_pmu_lbr_filter(struct cpu_hw_events *cpuc)
cpuc->lbr_entries[i].from = 0;
compress = true;
}
+
+ if ((br_sel & X86_BR_TYPE_SAVE) == X86_BR_TYPE_SAVE)
+ cpuc->lbr_entries[i].type = common_branch_type(type);
}
if (!compress)
--
2.7.4
[toc] | [prev] | [next] | [standalone]
| From | Jiri Olsa <jolsa@redhat.com> |
|---|---|
| Date | 2017-04-23 16:00 +0200 |
| Subject | Re: [PATCH v6 2/7] perf/x86/intel: Record branch type |
| Message-ID | <tzqdr-LO-13@gated-at.bofh.it> |
| In reply to | #1626971 |
On Thu, Apr 20, 2017 at 08:07:50PM +0800, Jin Yao wrote:
SNIP
>
> +#define X86_BR_TYPE_MAP_MAX 16
> +
> +static int
> +common_branch_type(int type)
> +{
> + int i, mask;
> + const int branch_map[X86_BR_TYPE_MAP_MAX] = {
> + PERF_BR_CALL, /* X86_BR_CALL */
> + PERF_BR_RET, /* X86_BR_RET */
> + PERF_BR_SYSCALL, /* X86_BR_SYSCALL */
> + PERF_BR_SYSRET, /* X86_BR_SYSRET */
> + PERF_BR_INT, /* X86_BR_INT */
> + PERF_BR_IRET, /* X86_BR_IRET */
> + PERF_BR_JCC, /* X86_BR_JCC */
> + PERF_BR_JMP, /* X86_BR_JMP */
> + PERF_BR_IRQ, /* X86_BR_IRQ */
> + PERF_BR_IND_CALL, /* X86_BR_IND_CALL */
> + PERF_BR_NONE, /* X86_BR_ABORT */
> + PERF_BR_NONE, /* X86_BR_IN_TX */
> + PERF_BR_NONE, /* X86_BR_NO_TX */
> + PERF_BR_CALL, /* X86_BR_ZERO_CALL */
> + PERF_BR_NONE, /* X86_BR_CALL_STACK */
> + PERF_BR_IND_JMP, /* X86_BR_IND_JMP */
> + };
> +
> + type >>= 2; /* skip X86_BR_USER and X86_BR_KERNEL */
> + mask = ~(~0 << 1);
is that a fancy way to get 1 into the mask? what do I miss?
> +
> + for (i = 0; i < X86_BR_TYPE_MAP_MAX; i++) {
> + if (type & mask)
> + return branch_map[i];
I wonder some bit search would be faster in here, but maybe not big deal
jirka
> +
> + type >>= 1;
> + }
> +
> + return PERF_BR_NONE;
> +}
> +
> /*
[toc] | [prev] | [next] | [standalone]
| From | "Jin, Yao" <yao.jin@linux.intel.com> |
|---|---|
| Date | 2017-04-24 02:50 +0200 |
| Subject | Re: [PATCH v6 2/7] perf/x86/intel: Record branch type |
| Message-ID | <tzAmt-7Jg-13@gated-at.bofh.it> |
| In reply to | #1629029 |
On 4/23/2017 9:55 PM, Jiri Olsa wrote:
> On Thu, Apr 20, 2017 at 08:07:50PM +0800, Jin Yao wrote:
>
> SNIP
>
>>
>> +#define X86_BR_TYPE_MAP_MAX 16
>> +
>> +static int
>> +common_branch_type(int type)
>> +{
>> + int i, mask;
>> + const int branch_map[X86_BR_TYPE_MAP_MAX] = {
>> + PERF_BR_CALL, /* X86_BR_CALL */
>> + PERF_BR_RET, /* X86_BR_RET */
>> + PERF_BR_SYSCALL, /* X86_BR_SYSCALL */
>> + PERF_BR_SYSRET, /* X86_BR_SYSRET */
>> + PERF_BR_INT, /* X86_BR_INT */
>> + PERF_BR_IRET, /* X86_BR_IRET */
>> + PERF_BR_JCC, /* X86_BR_JCC */
>> + PERF_BR_JMP, /* X86_BR_JMP */
>> + PERF_BR_IRQ, /* X86_BR_IRQ */
>> + PERF_BR_IND_CALL, /* X86_BR_IND_CALL */
>> + PERF_BR_NONE, /* X86_BR_ABORT */
>> + PERF_BR_NONE, /* X86_BR_IN_TX */
>> + PERF_BR_NONE, /* X86_BR_NO_TX */
>> + PERF_BR_CALL, /* X86_BR_ZERO_CALL */
>> + PERF_BR_NONE, /* X86_BR_CALL_STACK */
>> + PERF_BR_IND_JMP, /* X86_BR_IND_JMP */
>> + };
>> +
>> + type >>= 2; /* skip X86_BR_USER and X86_BR_KERNEL */
>> + mask = ~(~0 << 1);
> is that a fancy way to get 1 into the mask? what do I miss?
>
>> +
>> + for (i = 0; i < X86_BR_TYPE_MAP_MAX; i++) {
>> + if (type & mask)
>> + return branch_map[i];
> I wonder some bit search would be faster in here, but maybe not big deal
>
> jirka
I just think the branch_map[] doesn't contain many entries (16 entries
here), so maybe checking 1 bit one time should be acceptable. I just
want to keep the code simple.
But if the number of entries is more (e.g. 64), maybe it'd better check
2 or 4 bits one time.
Thanks
Jin Yao
>
>> +
>> + type >>= 1;
>> + }
>> +
>> + return PERF_BR_NONE;
>> +}
>> +
>> /*
[toc] | [prev] | [next] | [standalone]
| From | Jiri Olsa <jolsa@redhat.com> |
|---|---|
| Date | 2017-04-20 11:40 +0200 |
| Message-ID | <tygJb-7df-11@gated-at.bofh.it> |
| In reply to | #1626968 |
On Thu, Apr 20, 2017 at 08:07:48PM +0800, Jin Yao wrote:
> v6:
> Update according to the review comments from
> Jiri Olsa <jolsa@redhat.com>. Major modifications are:
>
> 1. Move that multiline conditional code inside {} brackets.
>
> 2. Move branch_type_stat_display() from builtin-report.c to
> branch.c. Move branch_type_str() from callchain.c to
> branch.c.
>
> 3. Keep the original branch info display order, that is:
> predicted, abort, cycles, iterations
for the tools part
Acked-by: Jiri Olsa <jolsa@kernel.org>
thanks,
jirka
[toc] | [prev] | [next] | [standalone]
| From | "Jin, Yao" <yao.jin@linux.intel.com> |
|---|---|
| Date | 2017-04-23 10:40 +0200 |
| Message-ID | <tzldL-652-3@gated-at.bofh.it> |
| In reply to | #1627238 |
On 4/20/2017 5:36 PM, Jiri Olsa wrote:
> On Thu, Apr 20, 2017 at 08:07:48PM +0800, Jin Yao wrote:
>> v6:
>> Update according to the review comments from
>> Jiri Olsa <jolsa@redhat.com>. Major modifications are:
>>
>> 1. Move that multiline conditional code inside {} brackets.
>>
>> 2. Move branch_type_stat_display() from builtin-report.c to
>> branch.c. Move branch_type_str() from callchain.c to
>> branch.c.
>>
>> 3. Keep the original branch info display order, that is:
>> predicted, abort, cycles, iterations
> for the tools part
>
> Acked-by: Jiri Olsa <jolsa@kernel.org>
>
> thanks,
> jirka
Thanks so much!
Is the kernel part OK?
Thanks
Jin Yao
[toc] | [prev] | [standalone]
Back to top | Article view | linux.kernel
csiph-web