1 // SPDX-License-Identifier: GPL-2.0
2 #include <string.h>
3 #include "../../../util/evlist.h"
4 #include "../../../util/evsel.h"
5 #include "topdown.h"
6 #include "evsel.h"
7
arch_evlist__cmp(const struct evsel * lhs,const struct evsel * rhs)8 int arch_evlist__cmp(const struct evsel *lhs, const struct evsel *rhs)
9 {
10 /*
11 * Currently the following topdown events sequence are supported to
12 * move and regroup correctly.
13 *
14 * a. all events in a group
15 * perf stat -e "{instructions,topdown-retiring,slots}" -C0 sleep 1
16 * WARNING: events were regrouped to match PMUs
17 * Performance counter stats for 'CPU(s) 0':
18 * 15,066,240 slots
19 * 1,899,760 instructions
20 * 2,126,998 topdown-retiring
21 * b. all events not in a group
22 * perf stat -e "instructions,topdown-retiring,slots" -C0 sleep 1
23 * WARNING: events were regrouped to match PMUs
24 * Performance counter stats for 'CPU(s) 0':
25 * 2,045,561 instructions
26 * 17,108,370 slots
27 * 2,281,116 topdown-retiring
28 * c. slots event in a group but topdown metrics events outside the group
29 * perf stat -e "{instructions,slots},topdown-retiring" -C0 sleep 1
30 * WARNING: events were regrouped to match PMUs
31 * Performance counter stats for 'CPU(s) 0':
32 * 20,323,878 slots
33 * 2,634,884 instructions
34 * 3,028,656 topdown-retiring
35 * d. slots event and topdown metrics events in two groups
36 * perf stat -e "{instructions,slots},{topdown-retiring}" -C0 sleep 1
37 * WARNING: events were regrouped to match PMUs
38 * Performance counter stats for 'CPU(s) 0':
39 * 26,319,024 slots
40 * 2,427,791 instructions
41 * 2,683,508 topdown-retiring
42 * e. slots event and metrics event are not in a group and not adjacent
43 * perf stat -e "{instructions,slots},cycles,topdown-retiring" -C0 sleep 1
44 * WARNING: events were regrouped to match PMUs
45 * 68,433,522 slots
46 * 8,856,102 topdown-retiring
47 * 7,791,494 instructions
48 * 11,469,513 cycles
49 */
50 if (topdown_sys_has_perf_metrics() &&
51 (arch_evsel__must_be_in_group(lhs) || arch_evsel__must_be_in_group(rhs))) {
52 /* Ensure the topdown slots comes first. */
53 if (arch_is_topdown_slots(lhs))
54 return -1;
55 if (arch_is_topdown_slots(rhs))
56 return 1;
57
58 /*
59 * Move topdown metrics events forward only when topdown metrics
60 * events are not in same group with previous slots event. If
61 * topdown metrics events are already in same group with slots
62 * event, do nothing.
63 */
64 if (lhs->core.leader != rhs->core.leader) {
65 bool lhs_topdown = arch_is_topdown_metrics(lhs);
66 bool rhs_topdown = arch_is_topdown_metrics(rhs);
67
68 if (lhs_topdown && !rhs_topdown)
69 return -1;
70 if (!lhs_topdown && rhs_topdown)
71 return 1;
72 }
73 }
74
75 /* Retire latency event should not be group leader*/
76 if (lhs->retire_lat && !rhs->retire_lat)
77 return 1;
78 if (!lhs->retire_lat && rhs->retire_lat)
79 return -1;
80
81 /* Default ordering by insertion index. */
82 return lhs->core.idx - rhs->core.idx;
83 }
84