Skip to content

Commit

Permalink
perf annotate-data: Handle macro fusion on x86
Browse files Browse the repository at this point in the history
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 <[email protected]>
Cc: Stephane Eranian <[email protected]>
Cc: Masami Hiramatsu <[email protected]>
Link: https://lore.kernel.org/r/[email protected]
Signed-off-by: Namhyung Kim <[email protected]>
  • Loading branch information
namhyung committed Jan 22, 2024
1 parent a3397d6 commit 1cf4df0
Showing 1 changed file with 16 additions and 1 deletion.
17 changes: 16 additions & 1 deletion tools/perf/util/annotate.c
Original file line number Diff line number Diff line change
Expand Up @@ -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++;
Expand All @@ -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);
Expand All @@ -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;
Expand Down

0 comments on commit 1cf4df0

Please sign in to comment.