perf annotate: Handle x86 instruction suffix generally
authorNamhyung Kim <namhyung@kernel.org>
Wed, 24 May 2023 20:50:53 +0000 (13:50 -0700)
committerArnaldo Carvalho de Melo <acme@redhat.com>
Fri, 9 Jun 2023 13:56:05 +0000 (10:56 -0300)
In AT&T asm syntax, most of x86 instructions can have size suffix like
b, w, l or q.  Instead of adding all these instructions in the table,
we can handle them in a general way.

For example, it can try to find an instruction as is.  If not found,
assuming it has a suffix and it'd try again without the suffix if it's
one of the allowed suffixes.  This way, we can reduce the instruction
table size for duplicated entries of the same instructions with a
different suffix.

If an instruction xyz and others like xyz<suffix> are completely
different ones, then they both need to be listed in the table so that
they can be found before the second attempt (without the suffix).

Reviewed-by: Adrian Hunter <adrian.hunter@intel.com>
Reviewed-by: Masami Hiramatsu <mhiramat@kernel.org>
Signed-off-by: Namhyung Kim <namhyung@kernel.org>
Cc: Andi Kleen <ak@linux.intel.com>
Cc: Ian Rogers <irogers@google.com>
Cc: Ingo Molnar <mingo@kernel.org>
Cc: Jiri Olsa <jolsa@kernel.org>
Cc: Kan Liang <kan.liang@linux.intel.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Link: https://lore.kernel.org/r/20230524205054.3087004-1-namhyung@kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
tools/perf/util/annotate.c

index b708bbc..7f05f2a 100644 (file)
@@ -70,6 +70,7 @@ struct arch {
        struct ins_ops  *(*associate_instruction_ops)(struct arch *arch, const char *name);
        bool            sorted_instructions;
        bool            initialized;
+       const char      *insn_suffix;
        void            *priv;
        unsigned int    model;
        unsigned int    family;
@@ -179,6 +180,7 @@ static struct arch architectures[] = {
                .init = x86__annotate_init,
                .instructions = x86__instructions,
                .nr_instructions = ARRAY_SIZE(x86__instructions),
+               .insn_suffix = "bwlq",
                .objdump =  {
                        .comment_char = '#',
                },
@@ -720,6 +722,26 @@ static struct ins_ops *__ins__find(struct arch *arch, const char *name)
        }
 
        ins = bsearch(name, arch->instructions, nmemb, sizeof(struct ins), ins__key_cmp);
+       if (ins)
+               return ins->ops;
+
+       if (arch->insn_suffix) {
+               char tmp[32];
+               char suffix;
+               size_t len = strlen(name);
+
+               if (len == 0 || len >= sizeof(tmp))
+                       return NULL;
+
+               suffix = name[len - 1];
+               if (strchr(arch->insn_suffix, suffix) == NULL)
+                       return NULL;
+
+               strcpy(tmp, name);
+               tmp[len - 1] = '\0'; /* remove the suffix and check again */
+
+               ins = bsearch(tmp, arch->instructions, nmemb, sizeof(struct ins), ins__key_cmp);
+       }
        return ins ? ins->ops : NULL;
 }