[1/2] perf annotate: Handle x86 instruction suffix generally

Message ID 20230524052834.1041418-1-namhyung@kernel.org
State New
Headers
Series [1/2] perf annotate: Handle x86 instruction suffix generally |

Commit Message

Namhyung Kim May 24, 2023, 5:28 a.m. UTC
  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, it'd try again without the suffix if it's one of
the allowed suffixes.

Signed-off-by: Namhyung Kim <namhyung@kernel.org>
---
 tools/perf/util/annotate.c | 22 ++++++++++++++++++++++
 1 file changed, 22 insertions(+)
  

Comments

Adrian Hunter May 24, 2023, 6:11 a.m. UTC | #1
On 24/05/23 08:28, Namhyung Kim wrote:
> Most of x86 instructions can have size suffix like b, w, l or q.

(AT&T mnemonics)

> 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, it'd try again without the suffix if it's one of
> the allowed suffixes.

I guess it might be possible that xyz is in the table but xyz<suffix>
is a completely different instruction?

> 
> Signed-off-by: Namhyung Kim <namhyung@kernel.org>
> ---
>  tools/perf/util/annotate.c | 22 ++++++++++++++++++++++
>  1 file changed, 22 insertions(+)
> 
> diff --git a/tools/perf/util/annotate.c b/tools/perf/util/annotate.c
> index b708bbc49c9e..7f05f2a2aa83 100644
> --- a/tools/perf/util/annotate.c
> +++ b/tools/perf/util/annotate.c
> @@ -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;
>  }
>
  
Namhyung Kim May 24, 2023, 4:10 p.m. UTC | #2
Hi Adrian,

On Tue, May 23, 2023 at 11:11 PM Adrian Hunter <adrian.hunter@intel.com> wrote:
>
> On 24/05/23 08:28, Namhyung Kim wrote:
> > Most of x86 instructions can have size suffix like b, w, l or q.
>
> (AT&T mnemonics)

Right, will update.

>
> > 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, it'd try again without the suffix if it's one of
> > the allowed suffixes.
>
> I guess it might be possible that xyz is in the table but xyz<suffix>
> is a completely different instruction?

Then xyz<suffix> should be in the table too.  The match without
suffix is a fallback so it should find the correct instruction first.

Thanks,
Namhyung


>
> >
> > Signed-off-by: Namhyung Kim <namhyung@kernel.org>
> > ---
> >  tools/perf/util/annotate.c | 22 ++++++++++++++++++++++
> >  1 file changed, 22 insertions(+)
> >
> > diff --git a/tools/perf/util/annotate.c b/tools/perf/util/annotate.c
> > index b708bbc49c9e..7f05f2a2aa83 100644
> > --- a/tools/perf/util/annotate.c
> > +++ b/tools/perf/util/annotate.c
> > @@ -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;
> >  }
> >
>
  
Adrian Hunter May 24, 2023, 5:41 p.m. UTC | #3
On 24/05/23 19:10, Namhyung Kim wrote:
> Hi Adrian,
> 
> On Tue, May 23, 2023 at 11:11 PM Adrian Hunter <adrian.hunter@intel.com> wrote:
>>
>> On 24/05/23 08:28, Namhyung Kim wrote:
>>> Most of x86 instructions can have size suffix like b, w, l or q.
>>
>> (AT&T mnemonics)
> 
> Right, will update.
> 
>>
>>> 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, it'd try again without the suffix if it's one of
>>> the allowed suffixes.
>>
>> I guess it might be possible that xyz is in the table but xyz<suffix>
>> is a completely different instruction?
> 
> Then xyz<suffix> should be in the table too.  The match without
> suffix is a fallback so it should find the correct instruction first.

Right, so when adding xyz to the table, xyz<suffix> does not need
to be added as well if it is the same instruction but with different
operand sizes, but xyz<suffix> must be added as well if it is a
different instruction with different ops.

> 
> Thanks,
> Namhyung
> 
> 
>>
>>>
>>> Signed-off-by: Namhyung Kim <namhyung@kernel.org>
>>> ---
>>>  tools/perf/util/annotate.c | 22 ++++++++++++++++++++++
>>>  1 file changed, 22 insertions(+)
>>>
>>> diff --git a/tools/perf/util/annotate.c b/tools/perf/util/annotate.c
>>> index b708bbc49c9e..7f05f2a2aa83 100644
>>> --- a/tools/perf/util/annotate.c
>>> +++ b/tools/perf/util/annotate.c
>>> @@ -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;
>>>  }
>>>
>>
  

Patch

diff --git a/tools/perf/util/annotate.c b/tools/perf/util/annotate.c
index b708bbc49c9e..7f05f2a2aa83 100644
--- a/tools/perf/util/annotate.c
+++ b/tools/perf/util/annotate.c
@@ -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;
 }