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