diff options
author | Namhyung Kim <namhyung@kernel.org> | 2024-01-16 22:26:50 -0800 |
---|---|---|
committer | Namhyung Kim <namhyung@kernel.org> | 2024-01-22 12:08:19 -0800 |
commit | 1cf4df0373eed561f543a9e0e0ac2498384d67a0 (patch) | |
tree | ad6cba939dc844e4af8e3d54c019612b54e0060b /tools/perf/util/annotate.c | |
parent | a3397d69e4e7a1ea37af413ccbdf52dec208ce11 (diff) |
perf annotate-data: Handle macro fusion on x86
When a sample was come from a conditional branch without a memory
operand, it could be due to a macro fusion with a previous instruction.
So it needs to check the memory operand in the previous one.
This improves the stat like below:
Annotate data type stats:
total 294, ok 147 (50.0%), bad 147 (50.0%)
-----------------------------------------------------------
30 : no_sym
32 : no_mem_ops
71 : no_var
6 : no_typeinfo
8 : bad_offset
Reviewed-by: Ian Rogers <irogers@google.com>
Cc: Stephane Eranian <eranian@google.com>
Cc: Masami Hiramatsu <mhiramat@kernel.org>
Link: https://lore.kernel.org/r/20240117062657.985479-3-namhyung@kernel.org
Signed-off-by: Namhyung Kim <namhyung@kernel.org>
Diffstat (limited to 'tools/perf/util/annotate.c')
-rw-r--r-- | tools/perf/util/annotate.c | 17 |
1 files changed, 16 insertions, 1 deletions
diff --git a/tools/perf/util/annotate.c b/tools/perf/util/annotate.c index 8d761be1a102..0ec42e85ca5c 100644 --- a/tools/perf/util/annotate.c +++ b/tools/perf/util/annotate.c @@ -3751,6 +3751,7 @@ struct annotated_data_type *hist_entry__get_data_type(struct hist_entry *he) return NULL; } +retry: istat = annotate_data_stat(&ann_insn_stat, dl->ins.name); if (istat == NULL) { ann_data_stat.no_insn++; @@ -3767,7 +3768,7 @@ struct annotated_data_type *hist_entry__get_data_type(struct hist_entry *he) if (!op_loc->mem_ref) continue; - /* Recalculate IP since it can be changed due to LOCK prefix */ + /* Recalculate IP because of LOCK prefix or insn fusion */ ip = ms->sym->start + dl->al.offset; mem_type = find_data_type(ms, ip, op_loc->reg, op_loc->offset); @@ -3786,6 +3787,20 @@ struct annotated_data_type *hist_entry__get_data_type(struct hist_entry *he) return mem_type; } + /* + * Some instructions can be fused and the actual memory access came + * from the previous instruction. + */ + if (dl->al.offset > 0) { + struct disasm_line *prev_dl; + + prev_dl = list_prev_entry(dl, al.node); + if (ins__is_fused(arch, prev_dl->ins.name, dl->ins.name)) { + dl = prev_dl; + goto retry; + } + } + ann_data_stat.no_mem_ops++; istat->bad++; return NULL; |