1e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng/*
2e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng * builtin-diff.c
3e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng *
4e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng * Builtin diff command: Analyze two perf.data input files, look up and read
5e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng * DSOs and symbol information, sort them and produce a diff.
6e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng */
7e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng#include "builtin.h"
8e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
9e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng#include "util/debug.h"
10e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng#include "util/event.h"
11e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng#include "util/hist.h"
12e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng#include "util/evsel.h"
13e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng#include "util/evlist.h"
14e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng#include "util/session.h"
15e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng#include "util/tool.h"
16e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng#include "util/sort.h"
17e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng#include "util/symbol.h"
18e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng#include "util/util.h"
19e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
20e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng#include <stdlib.h>
21e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng#include <math.h>
22e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
23e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng/* Diff command specific HPP columns. */
24e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengenum {
25e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	PERF_HPP_DIFF__BASELINE,
26e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	PERF_HPP_DIFF__PERIOD,
27e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	PERF_HPP_DIFF__PERIOD_BASELINE,
28e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	PERF_HPP_DIFF__DELTA,
29e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	PERF_HPP_DIFF__RATIO,
30e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	PERF_HPP_DIFF__WEIGHTED_DIFF,
31e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	PERF_HPP_DIFF__FORMULA,
32e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
33e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	PERF_HPP_DIFF__MAX_INDEX
34e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng};
35e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
36e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengstruct diff_hpp_fmt {
37e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	struct perf_hpp_fmt	 fmt;
38e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	int			 idx;
39e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	char			*header;
40e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	int			 header_width;
41e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng};
42e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
43e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengstruct data__file {
44e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	struct perf_session	*session;
45e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	const char		*file;
46e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	int			 idx;
47e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	struct hists		*hists;
48e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	struct diff_hpp_fmt	 fmt[PERF_HPP_DIFF__MAX_INDEX];
49e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng};
50e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
51e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengstatic struct data__file *data__files;
52e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengstatic int data__files_cnt;
53e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
54e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng#define data__for_each_file_start(i, d, s)	\
55e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	for (i = s, d = &data__files[s];	\
56e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	     i < data__files_cnt;		\
57e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	     i++, d = &data__files[i])
58e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
59e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng#define data__for_each_file(i, d) data__for_each_file_start(i, d, 0)
60e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng#define data__for_each_file_new(i, d) data__for_each_file_start(i, d, 1)
61e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
62e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengstatic char diff__default_sort_order[] = "dso,symbol";
63e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengstatic bool force;
64e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengstatic bool show_period;
65e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengstatic bool show_formula;
66e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengstatic bool show_baseline_only;
67e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengstatic unsigned int sort_compute;
68e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
69e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengstatic s64 compute_wdiff_w1;
70e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengstatic s64 compute_wdiff_w2;
71e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
72e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengenum {
73e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	COMPUTE_DELTA,
74e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	COMPUTE_RATIO,
75e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	COMPUTE_WEIGHTED_DIFF,
76e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	COMPUTE_MAX,
77e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng};
78e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
79e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengconst char *compute_names[COMPUTE_MAX] = {
80e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	[COMPUTE_DELTA] = "delta",
81e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	[COMPUTE_RATIO] = "ratio",
82e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	[COMPUTE_WEIGHTED_DIFF] = "wdiff",
83e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng};
84e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
85e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengstatic int compute;
86e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
87e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengstatic int compute_2_hpp[COMPUTE_MAX] = {
88e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	[COMPUTE_DELTA]		= PERF_HPP_DIFF__DELTA,
89e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	[COMPUTE_RATIO]		= PERF_HPP_DIFF__RATIO,
90e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	[COMPUTE_WEIGHTED_DIFF]	= PERF_HPP_DIFF__WEIGHTED_DIFF,
91e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng};
92e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
93e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng#define MAX_COL_WIDTH 70
94e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
95e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengstatic struct header_column {
96e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	const char *name;
97e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	int width;
98e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng} columns[PERF_HPP_DIFF__MAX_INDEX] = {
99e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	[PERF_HPP_DIFF__BASELINE] = {
100e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		.name  = "Baseline",
101e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	},
102e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	[PERF_HPP_DIFF__PERIOD] = {
103e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		.name  = "Period",
104e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		.width = 14,
105e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	},
106e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	[PERF_HPP_DIFF__PERIOD_BASELINE] = {
107e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		.name  = "Base period",
108e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		.width = 14,
109e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	},
110e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	[PERF_HPP_DIFF__DELTA] = {
111e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		.name  = "Delta",
112e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		.width = 7,
113e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	},
114e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	[PERF_HPP_DIFF__RATIO] = {
115e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		.name  = "Ratio",
116e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		.width = 14,
117e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	},
118e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	[PERF_HPP_DIFF__WEIGHTED_DIFF] = {
119e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		.name  = "Weighted diff",
120e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		.width = 14,
121e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	},
122e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	[PERF_HPP_DIFF__FORMULA] = {
123e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		.name  = "Formula",
124e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		.width = MAX_COL_WIDTH,
125e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	}
126e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng};
127e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
128e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengstatic int setup_compute_opt_wdiff(char *opt)
129e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng{
130e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	char *w1_str = opt;
131e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	char *w2_str;
132e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
133e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	int ret = -EINVAL;
134e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
135e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	if (!opt)
136e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		goto out;
137e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
138e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	w2_str = strchr(opt, ',');
139e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	if (!w2_str)
140e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		goto out;
141e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
142e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	*w2_str++ = 0x0;
143e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	if (!*w2_str)
144e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		goto out;
145e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
146e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	compute_wdiff_w1 = strtol(w1_str, NULL, 10);
147e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	compute_wdiff_w2 = strtol(w2_str, NULL, 10);
148e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
149e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	if (!compute_wdiff_w1 || !compute_wdiff_w2)
150e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		goto out;
151e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
152e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	pr_debug("compute wdiff w1(%" PRId64 ") w2(%" PRId64 ")\n",
153e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		  compute_wdiff_w1, compute_wdiff_w2);
154e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
155e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	ret = 0;
156e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
157e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng out:
158e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	if (ret)
159e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		pr_err("Failed: wrong weight data, use 'wdiff:w1,w2'\n");
160e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
161e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	return ret;
162e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng}
163e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
164e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengstatic int setup_compute_opt(char *opt)
165e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng{
166e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	if (compute == COMPUTE_WEIGHTED_DIFF)
167e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		return setup_compute_opt_wdiff(opt);
168e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
169e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	if (opt) {
170e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		pr_err("Failed: extra option specified '%s'", opt);
171e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		return -EINVAL;
172e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	}
173e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
174e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	return 0;
175e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng}
176e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
177e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengstatic int setup_compute(const struct option *opt, const char *str,
178e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng			 int unset __maybe_unused)
179e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng{
180e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	int *cp = (int *) opt->value;
181e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	char *cstr = (char *) str;
182e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	char buf[50];
183e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	unsigned i;
184e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	char *option;
185e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
186e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	if (!str) {
187e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		*cp = COMPUTE_DELTA;
188e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		return 0;
189e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	}
190e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
191e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	option = strchr(str, ':');
192e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	if (option) {
193e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		unsigned len = option++ - str;
194e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
195e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		/*
196e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		 * The str data are not writeable, so we need
197e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		 * to use another buffer.
198e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		 */
199e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
200e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		/* No option value is longer. */
201e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		if (len >= sizeof(buf))
202e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng			return -EINVAL;
203e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
204e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		strncpy(buf, str, len);
205e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		buf[len] = 0x0;
206e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		cstr = buf;
207e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	}
208e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
209e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	for (i = 0; i < COMPUTE_MAX; i++)
210e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		if (!strcmp(cstr, compute_names[i])) {
211e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng			*cp = i;
212e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng			return setup_compute_opt(option);
213e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		}
214e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
215e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	pr_err("Failed: '%s' is not computation method "
216e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	       "(use 'delta','ratio' or 'wdiff')\n", str);
217e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	return -EINVAL;
218e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng}
219e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
220e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengstatic double period_percent(struct hist_entry *he, u64 period)
221e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng{
222e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	u64 total = he->hists->stats.total_period;
223e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	return (period * 100.0) / total;
224e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng}
225e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
226e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengstatic double compute_delta(struct hist_entry *he, struct hist_entry *pair)
227e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng{
228e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	double old_percent = period_percent(he, he->stat.period);
229e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	double new_percent = period_percent(pair, pair->stat.period);
230e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
231e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	pair->diff.period_ratio_delta = new_percent - old_percent;
232e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	pair->diff.computed = true;
233e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	return pair->diff.period_ratio_delta;
234e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng}
235e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
236e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengstatic double compute_ratio(struct hist_entry *he, struct hist_entry *pair)
237e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng{
238e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	double old_period = he->stat.period ?: 1;
239e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	double new_period = pair->stat.period;
240e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
241e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	pair->diff.computed = true;
242e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	pair->diff.period_ratio = new_period / old_period;
243e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	return pair->diff.period_ratio;
244e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng}
245e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
246e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengstatic s64 compute_wdiff(struct hist_entry *he, struct hist_entry *pair)
247e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng{
248e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	u64 old_period = he->stat.period;
249e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	u64 new_period = pair->stat.period;
250e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
251e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	pair->diff.computed = true;
252e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	pair->diff.wdiff = new_period * compute_wdiff_w2 -
253e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng			   old_period * compute_wdiff_w1;
254e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
255e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	return pair->diff.wdiff;
256e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng}
257e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
258e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengstatic int formula_delta(struct hist_entry *he, struct hist_entry *pair,
259e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng			 char *buf, size_t size)
260e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng{
261e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	return scnprintf(buf, size,
262e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng			 "(%" PRIu64 " * 100 / %" PRIu64 ") - "
263e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng			 "(%" PRIu64 " * 100 / %" PRIu64 ")",
264e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng			  pair->stat.period, pair->hists->stats.total_period,
265e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng			  he->stat.period, he->hists->stats.total_period);
266e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng}
267e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
268e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengstatic int formula_ratio(struct hist_entry *he, struct hist_entry *pair,
269e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng			 char *buf, size_t size)
270e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng{
271e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	double old_period = he->stat.period;
272e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	double new_period = pair->stat.period;
273e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
274e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	return scnprintf(buf, size, "%.0F / %.0F", new_period, old_period);
275e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng}
276e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
277e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengstatic int formula_wdiff(struct hist_entry *he, struct hist_entry *pair,
278e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng			 char *buf, size_t size)
279e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng{
280e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	u64 old_period = he->stat.period;
281e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	u64 new_period = pair->stat.period;
282e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
283e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	return scnprintf(buf, size,
284e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		  "(%" PRIu64 " * " "%" PRId64 ") - (%" PRIu64 " * " "%" PRId64 ")",
285e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		  new_period, compute_wdiff_w2, old_period, compute_wdiff_w1);
286e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng}
287e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
288e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengstatic int formula_fprintf(struct hist_entry *he, struct hist_entry *pair,
289e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng			   char *buf, size_t size)
290e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng{
291e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	switch (compute) {
292e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	case COMPUTE_DELTA:
293e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		return formula_delta(he, pair, buf, size);
294e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	case COMPUTE_RATIO:
295e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		return formula_ratio(he, pair, buf, size);
296e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	case COMPUTE_WEIGHTED_DIFF:
297e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		return formula_wdiff(he, pair, buf, size);
298e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	default:
299e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		BUG_ON(1);
300e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	}
301e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
302e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	return -1;
303e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng}
304e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
305e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengstatic int hists__add_entry(struct hists *self,
306e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng			    struct addr_location *al, u64 period,
307e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng			    u64 weight)
308e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng{
309e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	if (__hists__add_entry(self, al, NULL, period, weight) != NULL)
310e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		return 0;
311e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	return -ENOMEM;
312e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng}
313e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
314e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengstatic int diff__process_sample_event(struct perf_tool *tool __maybe_unused,
315e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng				      union perf_event *event,
316e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng				      struct perf_sample *sample,
317e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng				      struct perf_evsel *evsel,
318e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng				      struct machine *machine)
319e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng{
320e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	struct addr_location al;
321e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
322e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	if (perf_event__preprocess_sample(event, machine, &al, sample) < 0) {
323e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		pr_warning("problem processing %d event, skipping it.\n",
324e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng			   event->header.type);
325e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		return -1;
326e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	}
327e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
328e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	if (al.filtered)
329e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		return 0;
330e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
331e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	if (hists__add_entry(&evsel->hists, &al, sample->period, sample->weight)) {
332e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		pr_warning("problem incrementing symbol period, skipping event\n");
333e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		return -1;
334e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	}
335e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
336e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	evsel->hists.stats.total_period += sample->period;
337e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	return 0;
338e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng}
339e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
340e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengstatic struct perf_tool tool = {
341e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	.sample	= diff__process_sample_event,
342e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	.mmap	= perf_event__process_mmap,
343e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	.comm	= perf_event__process_comm,
344e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	.exit	= perf_event__process_exit,
345e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	.fork	= perf_event__process_fork,
346e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	.lost	= perf_event__process_lost,
347e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	.ordered_samples = true,
348e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	.ordering_requires_timestamps = true,
349e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng};
350e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
351e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengstatic struct perf_evsel *evsel_match(struct perf_evsel *evsel,
352e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng				      struct perf_evlist *evlist)
353e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng{
354e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	struct perf_evsel *e;
355e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
356e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	list_for_each_entry(e, &evlist->entries, node)
357e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		if (perf_evsel__match2(evsel, e))
358e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng			return e;
359e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
360e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	return NULL;
361e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng}
362e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
363e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengstatic void perf_evlist__collapse_resort(struct perf_evlist *evlist)
364e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng{
365e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	struct perf_evsel *evsel;
366e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
367e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	list_for_each_entry(evsel, &evlist->entries, node) {
368e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		struct hists *hists = &evsel->hists;
369e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
370e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		hists__collapse_resort(hists);
371e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	}
372e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng}
373e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
374e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengstatic struct hist_entry*
375e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengget_pair_data(struct hist_entry *he, struct data__file *d)
376e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng{
377e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	if (hist_entry__has_pairs(he)) {
378e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		struct hist_entry *pair;
379e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
380e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		list_for_each_entry(pair, &he->pairs.head, pairs.node)
381e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng			if (pair->hists == d->hists)
382e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng				return pair;
383e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	}
384e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
385e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	return NULL;
386e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng}
387e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
388e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengstatic struct hist_entry*
389e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengget_pair_fmt(struct hist_entry *he, struct diff_hpp_fmt *dfmt)
390e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng{
391e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	void *ptr = dfmt - dfmt->idx;
392e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	struct data__file *d = container_of(ptr, struct data__file, fmt);
393e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
394e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	return get_pair_data(he, d);
395e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng}
396e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
397e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengstatic void hists__baseline_only(struct hists *hists)
398e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng{
399e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	struct rb_root *root;
400e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	struct rb_node *next;
401e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
402e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	if (sort__need_collapse)
403e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		root = &hists->entries_collapsed;
404e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	else
405e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		root = hists->entries_in;
406e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
407e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	next = rb_first(root);
408e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	while (next != NULL) {
409e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		struct hist_entry *he = rb_entry(next, struct hist_entry, rb_node_in);
410e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
411e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		next = rb_next(&he->rb_node_in);
412e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		if (!hist_entry__next_pair(he)) {
413e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng			rb_erase(&he->rb_node_in, root);
414e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng			hist_entry__free(he);
415e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		}
416e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	}
417e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng}
418e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
419e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengstatic void hists__precompute(struct hists *hists)
420e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng{
421e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	struct rb_root *root;
422e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	struct rb_node *next;
423e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
424e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	if (sort__need_collapse)
425e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		root = &hists->entries_collapsed;
426e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	else
427e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		root = hists->entries_in;
428e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
429e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	next = rb_first(root);
430e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	while (next != NULL) {
431e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		struct hist_entry *he, *pair;
432e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
433e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		he   = rb_entry(next, struct hist_entry, rb_node_in);
434e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		next = rb_next(&he->rb_node_in);
435e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
436e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		pair = get_pair_data(he, &data__files[sort_compute]);
437e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		if (!pair)
438e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng			continue;
439e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
440e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		switch (compute) {
441e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		case COMPUTE_DELTA:
442e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng			compute_delta(he, pair);
443e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng			break;
444e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		case COMPUTE_RATIO:
445e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng			compute_ratio(he, pair);
446e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng			break;
447e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		case COMPUTE_WEIGHTED_DIFF:
448e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng			compute_wdiff(he, pair);
449e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng			break;
450e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		default:
451e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng			BUG_ON(1);
452e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		}
453e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	}
454e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng}
455e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
456e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengstatic int64_t cmp_doubles(double l, double r)
457e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng{
458e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	if (l > r)
459e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		return -1;
460e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	else if (l < r)
461e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		return 1;
462e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	else
463e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		return 0;
464e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng}
465e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
466e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengstatic int64_t
467e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng__hist_entry__cmp_compute(struct hist_entry *left, struct hist_entry *right,
468e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng			int c)
469e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng{
470e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	switch (c) {
471e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	case COMPUTE_DELTA:
472e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	{
473e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		double l = left->diff.period_ratio_delta;
474e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		double r = right->diff.period_ratio_delta;
475e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
476e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		return cmp_doubles(l, r);
477e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	}
478e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	case COMPUTE_RATIO:
479e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	{
480e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		double l = left->diff.period_ratio;
481e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		double r = right->diff.period_ratio;
482e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
483e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		return cmp_doubles(l, r);
484e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	}
485e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	case COMPUTE_WEIGHTED_DIFF:
486e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	{
487e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		s64 l = left->diff.wdiff;
488e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		s64 r = right->diff.wdiff;
489e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
490e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		return r - l;
491e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	}
492e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	default:
493e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		BUG_ON(1);
494e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	}
495e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
496e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	return 0;
497e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng}
498e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
499e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengstatic int64_t
500e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chenghist_entry__cmp_compute(struct hist_entry *left, struct hist_entry *right,
501e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng			int c)
502e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng{
503e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	bool pairs_left  = hist_entry__has_pairs(left);
504e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	bool pairs_right = hist_entry__has_pairs(right);
505e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	struct hist_entry *p_right, *p_left;
506e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
507e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	if (!pairs_left && !pairs_right)
508e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		return 0;
509e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
510e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	if (!pairs_left || !pairs_right)
511e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		return pairs_left ? -1 : 1;
512e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
513e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	p_left  = get_pair_data(left,  &data__files[sort_compute]);
514e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	p_right = get_pair_data(right, &data__files[sort_compute]);
515e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
516e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	if (!p_left && !p_right)
517e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		return 0;
518e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
519e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	if (!p_left || !p_right)
520e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		return p_left ? -1 : 1;
521e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
522e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	/*
523e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	 * We have 2 entries of same kind, let's
524e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	 * make the data comparison.
525e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	 */
526e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	return __hist_entry__cmp_compute(p_left, p_right, c);
527e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng}
528e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
529e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengstatic void insert_hist_entry_by_compute(struct rb_root *root,
530e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng					 struct hist_entry *he,
531e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng					 int c)
532e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng{
533e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	struct rb_node **p = &root->rb_node;
534e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	struct rb_node *parent = NULL;
535e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	struct hist_entry *iter;
536e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
537e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	while (*p != NULL) {
538e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		parent = *p;
539e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		iter = rb_entry(parent, struct hist_entry, rb_node);
540e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		if (hist_entry__cmp_compute(he, iter, c) < 0)
541e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng			p = &(*p)->rb_left;
542e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		else
543e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng			p = &(*p)->rb_right;
544e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	}
545e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
546e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	rb_link_node(&he->rb_node, parent, p);
547e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	rb_insert_color(&he->rb_node, root);
548e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng}
549e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
550e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengstatic void hists__compute_resort(struct hists *hists)
551e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng{
552e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	struct rb_root *root;
553e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	struct rb_node *next;
554e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
555e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	if (sort__need_collapse)
556e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		root = &hists->entries_collapsed;
557e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	else
558e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		root = hists->entries_in;
559e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
560e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	hists->entries = RB_ROOT;
561e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	next = rb_first(root);
562e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
563e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	hists->nr_entries = 0;
564e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	hists->stats.total_period = 0;
565e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	hists__reset_col_len(hists);
566e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
567e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	while (next != NULL) {
568e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		struct hist_entry *he;
569e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
570e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		he = rb_entry(next, struct hist_entry, rb_node_in);
571e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		next = rb_next(&he->rb_node_in);
572e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
573e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		insert_hist_entry_by_compute(&hists->entries, he, compute);
574e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		hists__inc_nr_entries(hists, he);
575e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	}
576e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng}
577e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
578e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengstatic void hists__process(struct hists *hists)
579e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng{
580e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	if (show_baseline_only)
581e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		hists__baseline_only(hists);
582e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
583e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	if (sort_compute) {
584e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		hists__precompute(hists);
585e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		hists__compute_resort(hists);
586e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	} else {
587e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		hists__output_resort(hists);
588e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	}
589e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
590e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	hists__fprintf(hists, true, 0, 0, 0, stdout);
591e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng}
592e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
593e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengstatic void data__fprintf(void)
594e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng{
595e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	struct data__file *d;
596e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	int i;
597e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
598e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	fprintf(stdout, "# Data files:\n");
599e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
600e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	data__for_each_file(i, d)
601e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		fprintf(stdout, "#  [%d] %s %s\n",
602e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng			d->idx, d->file,
603e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng			!d->idx ? "(Baseline)" : "");
604e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
605e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	fprintf(stdout, "#\n");
606e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng}
607e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
608e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengstatic void data_process(void)
609e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng{
610e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	struct perf_evlist *evlist_base = data__files[0].session->evlist;
611e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	struct perf_evsel *evsel_base;
612e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	bool first = true;
613e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
614e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	list_for_each_entry(evsel_base, &evlist_base->entries, node) {
615e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		struct data__file *d;
616e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		int i;
617e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
618e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		data__for_each_file_new(i, d) {
619e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng			struct perf_evlist *evlist = d->session->evlist;
620e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng			struct perf_evsel *evsel;
621e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
622e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng			evsel = evsel_match(evsel_base, evlist);
623e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng			if (!evsel)
624e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng				continue;
625e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
626e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng			d->hists = &evsel->hists;
627e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
628e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng			hists__match(&evsel_base->hists, &evsel->hists);
629e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
630e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng			if (!show_baseline_only)
631e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng				hists__link(&evsel_base->hists,
632e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng					    &evsel->hists);
633e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		}
634e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
635e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		fprintf(stdout, "%s# Event '%s'\n#\n", first ? "" : "\n",
636e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng			perf_evsel__name(evsel_base));
637e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
638e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		first = false;
639e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
640e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		if (verbose || data__files_cnt > 2)
641e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng			data__fprintf();
642e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
643e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		hists__process(&evsel_base->hists);
644e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	}
645e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng}
646e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
647e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengstatic void data__free(struct data__file *d)
648e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng{
649e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	int col;
650e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
651e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	for (col = 0; col < PERF_HPP_DIFF__MAX_INDEX; col++) {
652e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		struct diff_hpp_fmt *fmt = &d->fmt[col];
653e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
654e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		free(fmt->header);
655e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	}
656e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng}
657e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
658e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengstatic int __cmd_diff(void)
659e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng{
660e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	struct data__file *d;
661e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	int ret = -EINVAL, i;
662e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
663e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	data__for_each_file(i, d) {
664e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		d->session = perf_session__new(d->file, O_RDONLY, force,
665e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng					       false, &tool);
666e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		if (!d->session) {
667e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng			pr_err("Failed to open %s\n", d->file);
668e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng			ret = -ENOMEM;
669e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng			goto out_delete;
670e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		}
671e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
672e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		ret = perf_session__process_events(d->session, &tool);
673e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		if (ret) {
674e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng			pr_err("Failed to process %s\n", d->file);
675e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng			goto out_delete;
676e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		}
677e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
678e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		perf_evlist__collapse_resort(d->session->evlist);
679e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	}
680e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
681e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	data_process();
682e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
683e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng out_delete:
684e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	data__for_each_file(i, d) {
685e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		if (d->session)
686e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng			perf_session__delete(d->session);
687e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
688e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		data__free(d);
689e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	}
690e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
691e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	free(data__files);
692e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	return ret;
693e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng}
694e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
695e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengstatic const char * const diff_usage[] = {
696e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	"perf diff [<options>] [old_file] [new_file]",
697e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	NULL,
698e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng};
699e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
700e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengstatic const struct option options[] = {
701e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	OPT_INCR('v', "verbose", &verbose,
702e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		    "be more verbose (show symbol address, etc)"),
703e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	OPT_BOOLEAN('b', "baseline-only", &show_baseline_only,
704e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		    "Show only items with match in baseline"),
705e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	OPT_CALLBACK('c', "compute", &compute,
706e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		     "delta,ratio,wdiff:w1,w2 (default delta)",
707e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		     "Entries differential computation selection",
708e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		     setup_compute),
709e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	OPT_BOOLEAN('p', "period", &show_period,
710e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		    "Show period values."),
711e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	OPT_BOOLEAN('F', "formula", &show_formula,
712e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		    "Show formula."),
713e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	OPT_BOOLEAN('D', "dump-raw-trace", &dump_trace,
714e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		    "dump raw trace in ASCII"),
715e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	OPT_BOOLEAN('f', "force", &force, "don't complain, do it"),
716e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	OPT_BOOLEAN('m', "modules", &symbol_conf.use_modules,
717e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		    "load module symbols - WARNING: use only with -k and LIVE kernel"),
718e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	OPT_STRING('d', "dsos", &symbol_conf.dso_list_str, "dso[,dso...]",
719e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		   "only consider symbols in these dsos"),
720e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	OPT_STRING('C', "comms", &symbol_conf.comm_list_str, "comm[,comm...]",
721e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		   "only consider symbols in these comms"),
722e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	OPT_STRING('S', "symbols", &symbol_conf.sym_list_str, "symbol[,symbol...]",
723e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		   "only consider these symbols"),
724e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	OPT_STRING('s', "sort", &sort_order, "key[,key2...]",
725e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		   "sort by key(s): pid, comm, dso, symbol, parent"),
726e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	OPT_STRING('t', "field-separator", &symbol_conf.field_sep, "separator",
727e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		   "separator for columns, no spaces will be added between "
728e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		   "columns '.' is reserved."),
729e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	OPT_STRING(0, "symfs", &symbol_conf.symfs, "directory",
730e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		    "Look for files with symbols relative to this directory"),
731e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	OPT_UINTEGER('o', "order", &sort_compute, "Specify compute sorting."),
732e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	OPT_END()
733e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng};
734e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
735e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengstatic double baseline_percent(struct hist_entry *he)
736e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng{
737e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	struct hists *hists = he->hists;
738e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	return 100.0 * he->stat.period / hists->stats.total_period;
739e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng}
740e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
741e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengstatic int hpp__color_baseline(struct perf_hpp_fmt *fmt,
742e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng			       struct perf_hpp *hpp, struct hist_entry *he)
743e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng{
744e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	struct diff_hpp_fmt *dfmt =
745e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		container_of(fmt, struct diff_hpp_fmt, fmt);
746e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	double percent = baseline_percent(he);
747e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	char pfmt[20] = " ";
748e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
749e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	if (!he->dummy) {
750e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		scnprintf(pfmt, 20, "%%%d.2f%%%%", dfmt->header_width - 1);
751e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		return percent_color_snprintf(hpp->buf, hpp->size,
752e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng					      pfmt, percent);
753e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	} else
754e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		return scnprintf(hpp->buf, hpp->size, "%*s",
755e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng				 dfmt->header_width, pfmt);
756e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng}
757e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
758e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengstatic int hpp__entry_baseline(struct hist_entry *he, char *buf, size_t size)
759e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng{
760e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	double percent = baseline_percent(he);
761e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	const char *fmt = symbol_conf.field_sep ? "%.2f" : "%6.2f%%";
762e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	int ret = 0;
763e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
764e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	if (!he->dummy)
765e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		ret = scnprintf(buf, size, fmt, percent);
766e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
767e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	return ret;
768e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng}
769e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
770e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengstatic void
771e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chenghpp__entry_unpair(struct hist_entry *he, int idx, char *buf, size_t size)
772e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng{
773e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	switch (idx) {
774e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	case PERF_HPP_DIFF__PERIOD_BASELINE:
775e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		scnprintf(buf, size, "%" PRIu64, he->stat.period);
776e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		break;
777e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
778e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	default:
779e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		break;
780e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	}
781e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng}
782e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
783e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengstatic void
784e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chenghpp__entry_pair(struct hist_entry *he, struct hist_entry *pair,
785e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		int idx, char *buf, size_t size)
786e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng{
787e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	double diff;
788e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	double ratio;
789e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	s64 wdiff;
790e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
791e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	switch (idx) {
792e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	case PERF_HPP_DIFF__DELTA:
793e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		if (pair->diff.computed)
794e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng			diff = pair->diff.period_ratio_delta;
795e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		else
796e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng			diff = compute_delta(he, pair);
797e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
798e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		if (fabs(diff) >= 0.01)
799e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng			scnprintf(buf, size, "%+4.2F%%", diff);
800e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		break;
801e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
802e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	case PERF_HPP_DIFF__RATIO:
803e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		/* No point for ratio number if we are dummy.. */
804e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		if (he->dummy)
805e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng			break;
806e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
807e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		if (pair->diff.computed)
808e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng			ratio = pair->diff.period_ratio;
809e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		else
810e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng			ratio = compute_ratio(he, pair);
811e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
812e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		if (ratio > 0.0)
813e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng			scnprintf(buf, size, "%14.6F", ratio);
814e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		break;
815e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
816e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	case PERF_HPP_DIFF__WEIGHTED_DIFF:
817e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		/* No point for wdiff number if we are dummy.. */
818e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		if (he->dummy)
819e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng			break;
820e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
821e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		if (pair->diff.computed)
822e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng			wdiff = pair->diff.wdiff;
823e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		else
824e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng			wdiff = compute_wdiff(he, pair);
825e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
826e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		if (wdiff != 0)
827e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng			scnprintf(buf, size, "%14ld", wdiff);
828e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		break;
829e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
830e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	case PERF_HPP_DIFF__FORMULA:
831e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		formula_fprintf(he, pair, buf, size);
832e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		break;
833e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
834e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	case PERF_HPP_DIFF__PERIOD:
835e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		scnprintf(buf, size, "%" PRIu64, pair->stat.period);
836e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		break;
837e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
838e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	default:
839e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		BUG_ON(1);
840e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	};
841e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng}
842e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
843e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengstatic void
844e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng__hpp__entry_global(struct hist_entry *he, struct diff_hpp_fmt *dfmt,
845e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		    char *buf, size_t size)
846e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng{
847e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	struct hist_entry *pair = get_pair_fmt(he, dfmt);
848e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	int idx = dfmt->idx;
849e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
850e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	/* baseline is special */
851e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	if (idx == PERF_HPP_DIFF__BASELINE)
852e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		hpp__entry_baseline(he, buf, size);
853e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	else {
854e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		if (pair)
855e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng			hpp__entry_pair(he, pair, idx, buf, size);
856e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		else
857e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng			hpp__entry_unpair(he, idx, buf, size);
858e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	}
859e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng}
860e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
861e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengstatic int hpp__entry_global(struct perf_hpp_fmt *_fmt, struct perf_hpp *hpp,
862e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng			     struct hist_entry *he)
863e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng{
864e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	struct diff_hpp_fmt *dfmt =
865e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		container_of(_fmt, struct diff_hpp_fmt, fmt);
866e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	char buf[MAX_COL_WIDTH] = " ";
867e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
868e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	__hpp__entry_global(he, dfmt, buf, MAX_COL_WIDTH);
869e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
870e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	if (symbol_conf.field_sep)
871e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		return scnprintf(hpp->buf, hpp->size, "%s", buf);
872e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	else
873e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		return scnprintf(hpp->buf, hpp->size, "%*s",
874e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng				 dfmt->header_width, buf);
875e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng}
876e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
877e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengstatic int hpp__header(struct perf_hpp_fmt *fmt,
878e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		       struct perf_hpp *hpp)
879e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng{
880e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	struct diff_hpp_fmt *dfmt =
881e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		container_of(fmt, struct diff_hpp_fmt, fmt);
882e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
883e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	BUG_ON(!dfmt->header);
884e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	return scnprintf(hpp->buf, hpp->size, dfmt->header);
885e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng}
886e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
887e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengstatic int hpp__width(struct perf_hpp_fmt *fmt,
888e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		      struct perf_hpp *hpp __maybe_unused)
889e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng{
890e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	struct diff_hpp_fmt *dfmt =
891e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		container_of(fmt, struct diff_hpp_fmt, fmt);
892e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
893e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	BUG_ON(dfmt->header_width <= 0);
894e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	return dfmt->header_width;
895e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng}
896e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
897e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengstatic void init_header(struct data__file *d, struct diff_hpp_fmt *dfmt)
898e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng{
899e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng#define MAX_HEADER_NAME 100
900e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	char buf_indent[MAX_HEADER_NAME];
901e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	char buf[MAX_HEADER_NAME];
902e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	const char *header = NULL;
903e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	int width = 0;
904e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
905e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	BUG_ON(dfmt->idx >= PERF_HPP_DIFF__MAX_INDEX);
906e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	header = columns[dfmt->idx].name;
907e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	width  = columns[dfmt->idx].width;
908e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
909e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	/* Only our defined HPP fmts should appear here. */
910e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	BUG_ON(!header);
911e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
912e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	if (data__files_cnt > 2)
913e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		scnprintf(buf, MAX_HEADER_NAME, "%s/%d", header, d->idx);
914e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
915e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng#define NAME (data__files_cnt > 2 ? buf : header)
916e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	dfmt->header_width = width;
917e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	width = (int) strlen(NAME);
918e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	if (dfmt->header_width < width)
919e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		dfmt->header_width = width;
920e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
921e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	scnprintf(buf_indent, MAX_HEADER_NAME, "%*s",
922e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		  dfmt->header_width, NAME);
923e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
924e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	dfmt->header = strdup(buf_indent);
925e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng#undef MAX_HEADER_NAME
926e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng#undef NAME
927e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng}
928e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
929e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengstatic void data__hpp_register(struct data__file *d, int idx)
930e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng{
931e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	struct diff_hpp_fmt *dfmt = &d->fmt[idx];
932e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	struct perf_hpp_fmt *fmt = &dfmt->fmt;
933e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
934e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	dfmt->idx = idx;
935e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
936e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	fmt->header = hpp__header;
937e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	fmt->width  = hpp__width;
938e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	fmt->entry  = hpp__entry_global;
939e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
940e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	/* TODO more colors */
941e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	if (idx == PERF_HPP_DIFF__BASELINE)
942e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		fmt->color = hpp__color_baseline;
943e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
944e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	init_header(d, dfmt);
945e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	perf_hpp__column_register(fmt);
946e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng}
947e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
948e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengstatic void ui_init(void)
949e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng{
950e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	struct data__file *d;
951e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	int i;
952e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
953e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	data__for_each_file(i, d) {
954e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
955e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		/*
956e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		 * Baseline or compute realted columns:
957e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		 *
958e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		 *   PERF_HPP_DIFF__BASELINE
959e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		 *   PERF_HPP_DIFF__DELTA
960e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		 *   PERF_HPP_DIFF__RATIO
961e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		 *   PERF_HPP_DIFF__WEIGHTED_DIFF
962e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		 */
963e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		data__hpp_register(d, i ? compute_2_hpp[compute] :
964e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng					  PERF_HPP_DIFF__BASELINE);
965e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
966e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		/*
967e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		 * And the rest:
968e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		 *
969e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		 * PERF_HPP_DIFF__FORMULA
970e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		 * PERF_HPP_DIFF__PERIOD
971e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		 * PERF_HPP_DIFF__PERIOD_BASELINE
972e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		 */
973e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		if (show_formula && i)
974e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng			data__hpp_register(d, PERF_HPP_DIFF__FORMULA);
975e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
976e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		if (show_period)
977e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng			data__hpp_register(d, i ? PERF_HPP_DIFF__PERIOD :
978e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng						  PERF_HPP_DIFF__PERIOD_BASELINE);
979e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	}
980e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng}
981e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
982e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengstatic int data_init(int argc, const char **argv)
983e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng{
984e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	struct data__file *d;
985e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	static const char *defaults[] = {
986e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		"perf.data.old",
987e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		"perf.data",
988e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	};
989e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	bool use_default = true;
990e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	int i;
991e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
992e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	data__files_cnt = 2;
993e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
994e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	if (argc) {
995e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		if (argc == 1)
996e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng			defaults[1] = argv[0];
997e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		else {
998e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng			data__files_cnt = argc;
999e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng			use_default = false;
1000e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		}
1001e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	} else if (symbol_conf.default_guest_vmlinux_name ||
1002e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		   symbol_conf.default_guest_kallsyms) {
1003e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		defaults[0] = "perf.data.host";
1004e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		defaults[1] = "perf.data.guest";
1005e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	}
1006e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
1007e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	if (sort_compute >= (unsigned int) data__files_cnt) {
1008e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		pr_err("Order option out of limit.\n");
1009e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		return -EINVAL;
1010e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	}
1011e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
1012e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	data__files = zalloc(sizeof(*data__files) * data__files_cnt);
1013e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	if (!data__files)
1014e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		return -ENOMEM;
1015e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
1016e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	data__for_each_file(i, d) {
1017e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		d->file = use_default ? defaults[i] : argv[i];
1018e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		d->idx  = i;
1019e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	}
1020e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
1021e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	return 0;
1022e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng}
1023e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
1024e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengint cmd_diff(int argc, const char **argv, const char *prefix __maybe_unused)
1025e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng{
1026e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	sort_order = diff__default_sort_order;
1027e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	argc = parse_options(argc, argv, options, diff_usage, 0);
1028e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
1029e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	if (symbol__init() < 0)
1030e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		return -1;
1031e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
1032e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	if (data_init(argc, argv) < 0)
1033e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		return -1;
1034e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
1035e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	ui_init();
1036e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
1037e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	if (setup_sorting() < 0)
1038e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		usage_with_options(diff_usage, options);
1039e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
1040e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	setup_pager();
1041e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
1042e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	sort__setup_elide(NULL);
1043e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
1044e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	return __cmd_diff();
1045e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng}
1046