Skip to content

Commit 4ca0d34

Browse files
heihernamhyung
authored andcommitted
perf annotate: Fix instruction association and parsing for LoongArch
In the perf annotate view for LoongArch, there is no arrowed line pointing to the target from the branch instruction. This issue is caused by incorrect instruction association and parsing. $ perf record alloc-6276705c94ad1398 # rust benchmark $ perf report 0.28 │ ori $a1, $zero, 0x63 │ move $a2, $zero 10.55 │ addi.d $a3, $a2, 1(0x1) │ sltu $a4, $a3, $s7 9.53 │ masknez $a4, $s7, $a4 │ sub.d $a3, $a3, $a4 12.12 │ st.d $a1, $fp, 24(0x18) │ st.d $a3, $fp, 16(0x10) 16.29 │ slli.d $a2, $a2, 0x2 │ ldx.w $a2, $s8, $a2 12.77 │ st.w $a2, $sp, 724(0x2d4) │ st.w $s0, $sp, 720(0x2d0) 7.03 │ addi.d $a2, $sp, 720(0x2d0) │ addi.d $a1, $a1, -1(0xfff) 12.03 │ move $a2, $a3 │ → bne $a1, $s3, -52(0x3ffcc) # 82ce8 <test::bench::Bencher::iter+0x3f4> 2.50 │ addi.d $a0, $a0, 1(0x1) This patch fixes instruction association issues, such as associating branch instructions with jump_ops instead of call_ops, and corrects false instruction matches. It also implements branch instruction parsing specifically for LoongArch. With this patch, we will be able to see the arrowed line. 0.79 │3ec: ori $a1, $zero, 0x63 │ move $a2, $zero 10.32 │3f4:┌─→addi.d $a3, $a2, 1(0x1) │ │ sltu $a4, $a3, $s7 10.44 │ │ masknez $a4, $s7, $a4 │ │ sub.d $a3, $a3, $a4 14.17 │ │ st.d $a1, $fp, 24(0x18) │ │ st.d $a3, $fp, 16(0x10) 13.15 │ │ slli.d $a2, $a2, 0x2 │ │ ldx.w $a2, $s8, $a2 11.00 │ │ st.w $a2, $sp, 724(0x2d4) │ │ st.w $s0, $sp, 720(0x2d0) 8.00 │ │ addi.d $a2, $sp, 720(0x2d0) │ │ addi.d $a1, $a1, -1(0xfff) 11.99 │ │ move $a2, $a3 │ └──bne $a1, $s3, 3f4 3.17 │ addi.d $a0, $a0, 1(0x1) Signed-off-by: WANG Rui <[email protected]> Acked-by: Namhyung Kim <[email protected]> Cc: Mark Rutland <[email protected]> Cc: Peter Zijlstra <[email protected]> Cc: Arnaldo Carvalho de Melo <[email protected]> Cc: Jiri Olsa <[email protected]> Cc: Alexander Shishkin <[email protected]> Cc: [email protected] Cc: [email protected] Cc: Huacai Chen <[email protected]> Cc: Tiezhu Yang <[email protected]> Cc: Ingo Molnar <[email protected]> Cc: WANG Xuerui <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Namhyung Kim <[email protected]>
1 parent 2e9f9d4 commit 4ca0d34

File tree

3 files changed

+109
-18
lines changed

3 files changed

+109
-18
lines changed

tools/perf/arch/loongarch/annotate/instructions.c

Lines changed: 103 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -5,25 +5,115 @@
55
* Copyright (C) 2020-2023 Loongson Technology Corporation Limited
66
*/
77

8+
static int loongarch_call__parse(struct arch *arch, struct ins_operands *ops, struct map_symbol *ms)
9+
{
10+
char *c, *endptr, *tok, *name;
11+
struct map *map = ms->map;
12+
struct addr_map_symbol target = {
13+
.ms = { .map = map, },
14+
};
15+
16+
c = strchr(ops->raw, '#');
17+
if (c++ == NULL)
18+
return -1;
19+
20+
ops->target.addr = strtoull(c, &endptr, 16);
21+
22+
name = strchr(endptr, '<');
23+
name++;
24+
25+
if (arch->objdump.skip_functions_char &&
26+
strchr(name, arch->objdump.skip_functions_char))
27+
return -1;
28+
29+
tok = strchr(name, '>');
30+
if (tok == NULL)
31+
return -1;
32+
33+
*tok = '\0';
34+
ops->target.name = strdup(name);
35+
*tok = '>';
36+
37+
if (ops->target.name == NULL)
38+
return -1;
39+
40+
target.addr = map__objdump_2mem(map, ops->target.addr);
41+
42+
if (maps__find_ams(ms->maps, &target) == 0 &&
43+
map__rip_2objdump(target.ms.map, map__map_ip(target.ms.map, target.addr)) == ops->target.addr)
44+
ops->target.sym = target.ms.sym;
45+
46+
return 0;
47+
}
48+
49+
static struct ins_ops loongarch_call_ops = {
50+
.parse = loongarch_call__parse,
51+
.scnprintf = call__scnprintf,
52+
};
53+
54+
static int loongarch_jump__parse(struct arch *arch, struct ins_operands *ops, struct map_symbol *ms)
55+
{
56+
struct map *map = ms->map;
57+
struct symbol *sym = ms->sym;
58+
struct addr_map_symbol target = {
59+
.ms = { .map = map, },
60+
};
61+
const char *c = strchr(ops->raw, '#');
62+
u64 start, end;
63+
64+
ops->raw_comment = strchr(ops->raw, arch->objdump.comment_char);
65+
ops->raw_func_start = strchr(ops->raw, '<');
66+
67+
if (ops->raw_func_start && c > ops->raw_func_start)
68+
c = NULL;
69+
70+
if (c++ != NULL)
71+
ops->target.addr = strtoull(c, NULL, 16);
72+
else
73+
ops->target.addr = strtoull(ops->raw, NULL, 16);
74+
75+
target.addr = map__objdump_2mem(map, ops->target.addr);
76+
start = map__unmap_ip(map, sym->start);
77+
end = map__unmap_ip(map, sym->end);
78+
79+
ops->target.outside = target.addr < start || target.addr > end;
80+
81+
if (maps__find_ams(ms->maps, &target) == 0 &&
82+
map__rip_2objdump(target.ms.map, map__map_ip(target.ms.map, target.addr)) == ops->target.addr)
83+
ops->target.sym = target.ms.sym;
84+
85+
if (!ops->target.outside) {
86+
ops->target.offset = target.addr - start;
87+
ops->target.offset_avail = true;
88+
} else {
89+
ops->target.offset_avail = false;
90+
}
91+
92+
return 0;
93+
}
94+
95+
static struct ins_ops loongarch_jump_ops = {
96+
.parse = loongarch_jump__parse,
97+
.scnprintf = jump__scnprintf,
98+
};
99+
8100
static
9101
struct ins_ops *loongarch__associate_ins_ops(struct arch *arch, const char *name)
10102
{
11103
struct ins_ops *ops = NULL;
12104

13-
if (!strncmp(name, "beqz", 4) ||
14-
!strncmp(name, "bnez", 4) ||
15-
!strncmp(name, "beq", 3) ||
16-
!strncmp(name, "bne", 3) ||
17-
!strncmp(name, "blt", 3) ||
18-
!strncmp(name, "bge", 3) ||
19-
!strncmp(name, "bltu", 4) ||
20-
!strncmp(name, "bgeu", 4) ||
21-
!strncmp(name, "bl", 2))
22-
ops = &call_ops;
23-
else if (!strncmp(name, "jirl", 4))
105+
if (!strcmp(name, "bl"))
106+
ops = &loongarch_call_ops;
107+
else if (!strcmp(name, "jirl"))
24108
ops = &ret_ops;
25-
else if (name[0] == 'b')
26-
ops = &jump_ops;
109+
else if (!strcmp(name, "b") ||
110+
!strncmp(name, "beq", 3) ||
111+
!strncmp(name, "bne", 3) ||
112+
!strncmp(name, "blt", 3) ||
113+
!strncmp(name, "bge", 3) ||
114+
!strncmp(name, "bltu", 4) ||
115+
!strncmp(name, "bgeu", 4))
116+
ops = &loongarch_jump_ops;
27117
else
28118
return NULL;
29119

tools/perf/arch/s390/annotate/instructions.c

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -45,9 +45,6 @@ static int s390_call__parse(struct arch *arch, struct ins_operands *ops,
4545
return 0;
4646
}
4747

48-
static int call__scnprintf(struct ins *ins, char *bf, size_t size,
49-
struct ins_operands *ops, int max_ins_name);
50-
5148
static struct ins_ops s390_call_ops = {
5249
.parse = s390_call__parse,
5350
.scnprintf = call__scnprintf,

tools/perf/util/annotate.c

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,10 @@ static regex_t file_lineno;
6262
static struct ins_ops *ins__find(struct arch *arch, const char *name);
6363
static void ins__sort(struct arch *arch);
6464
static int disasm_line__parse(char *line, const char **namep, char **rawp);
65+
static int call__scnprintf(struct ins *ins, char *bf, size_t size,
66+
struct ins_operands *ops, int max_ins_name);
67+
static int jump__scnprintf(struct ins *ins, char *bf, size_t size,
68+
struct ins_operands *ops, int max_ins_name);
6569

6670
struct arch {
6771
const char *name;
@@ -324,7 +328,7 @@ static struct ins_ops call_ops = {
324328

325329
bool ins__is_call(const struct ins *ins)
326330
{
327-
return ins->ops == &call_ops || ins->ops == &s390_call_ops;
331+
return ins->ops == &call_ops || ins->ops == &s390_call_ops || ins->ops == &loongarch_call_ops;
328332
}
329333

330334
/*
@@ -465,7 +469,7 @@ static struct ins_ops jump_ops = {
465469

466470
bool ins__is_jump(const struct ins *ins)
467471
{
468-
return ins->ops == &jump_ops;
472+
return ins->ops == &jump_ops || ins->ops == &loongarch_jump_ops;
469473
}
470474

471475
static int comment__symbol(char *raw, char *comment, u64 *addrp, char **namep)

0 commit comments

Comments
 (0)