bestat.c 5.81 KB
Newer Older
Christian Würdig's avatar
Christian Würdig committed
1
/*
2
 * Copyright (C) 1995-2011 University of Karlsruhe.  All right reserved.
Christian Würdig's avatar
Christian Würdig committed
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
 *
 * This file is part of libFirm.
 *
 * This file may be distributed and/or modified under the terms of the
 * GNU General Public License version 2 as published by the Free Software
 * Foundation and appearing in the file LICENSE.GPL included in the
 * packaging of this file.
 *
 * Licensees holding valid libFirm Professional Edition licenses may use
 * this file in accordance with the libFirm Commercial License.
 * Agreement provided with the Software.
 *
 * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
 * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE.
 */

Christian Würdig's avatar
Christian Würdig committed
20
/**
Christian Würdig's avatar
Christian Würdig committed
21
22
 * @file
 * @brief       Provides several statistic functions for the backend.
Matthias Braun's avatar
Matthias Braun committed
23
 * @author      Christian Wuerdig, Matthias Braun
Christian Würdig's avatar
Christian Würdig committed
24
 */
25
26
#include "config.h"

27
28
#include <time.h>

29
30
31
32
#include "irnode_t.h"
#include "irprintf.h"
#include "irgwalk.h"
#include "irhooks.h"
Michael Beck's avatar
Michael Beck committed
33
#include "execfreq.h"
34
#include "firmstat_t.h"
35
#include "irtools.h"
Sebastian Hack's avatar
Sebastian Hack committed
36
#include "statev.h"
Matthias Braun's avatar
Matthias Braun committed
37
#include "error.h"
38

39
40
#include "bearch.h"
#include "beirg.h"
41
42
43
#include "bestat.h"
#include "belive_t.h"
#include "besched.h"
44
#include "benode.h"
Christian Würdig's avatar
Christian Würdig committed
45
46


47

48
49
typedef struct pressure_walker_env_t pressure_walker_env_t;
struct pressure_walker_env_t {
50
	ir_graph *irg;
51
52
53
	be_lv_t  *lv;
	double    insn_count;
	double    regpressure;
54
	size_t    max_pressure;
55
	const arch_register_class_t *cls;
Sebastian Hack's avatar
Sebastian Hack committed
56
57
};

58
59
60
61
static void check_reg_pressure_class(pressure_walker_env_t *env,
                                     ir_node *block,
                                     const arch_register_class_t *cls)
{
62
63
64
	ir_graph    *irg  = env->irg;
	ir_nodeset_t live_nodes;
	size_t       max_live;
65
66

	ir_nodeset_init(&live_nodes);
67
	be_liveness_end_of_block(env->lv, cls, block, &live_nodes);
68
69
70
71
	max_live = ir_nodeset_size(&live_nodes);
	env->regpressure += max_live;

	sched_foreach_reverse(block, irn) {
72
		size_t cnt;
73

74
		if (is_Phi(irn))
75
76
			break;

77
		be_liveness_transfer(cls, irn, &live_nodes);
78
79
80
81
82
		cnt      = ir_nodeset_size(&live_nodes);
		max_live = cnt < max_live ? max_live : cnt;
		env->regpressure += cnt;
		env->insn_count++;
	}
83

84
	if (max_live > env->max_pressure)
85
		env->max_pressure = max_live;
86

87
88
89
	stat_be_block_regpressure(irg, block, max_live, cls->name);
	ir_nodeset_destroy(&live_nodes);
}
90

91
92
static void stat_reg_pressure_block(ir_node *block, void *data)
{
93
	pressure_walker_env_t *env = (pressure_walker_env_t*)data;
94

95
	check_reg_pressure_class(env, block, env->cls);
96
97
}

98
void be_do_stat_reg_pressure(ir_graph *irg, const arch_register_class_t *cls)
99
{
100
101
102
	pressure_walker_env_t  env;
	double                 average_pressure;

103
	env.irg          = irg;
104
105
106
	env.insn_count   = 0;
	env.max_pressure = 0;
	env.regpressure  = 0;
107
	be_assure_live_sets(irg);
108
	env.lv           = be_get_irg_liveness(irg);
109
	env.cls          = cls;
110

111
112
	/* Collect register pressure information for each block */
	irg_block_walk_graph(irg, stat_reg_pressure_block, NULL, &env);
Sebastian Hack's avatar
Sebastian Hack committed
113

114
	average_pressure = env.regpressure / env.insn_count;
115
116
	stat_ev_emit("bechordal_average_register_pressure", average_pressure);
	stat_ev_emit("bechordal_maximum_register_pressure", env.max_pressure);
117
}
118

Christian Würdig's avatar
Christian Würdig committed
119
120
121



122
typedef struct estimate_irg_costs_env_t {
Christian Würdig's avatar
Christian Würdig committed
123
124
	ir_exec_freq     *execfreqs;
	double           costs;
125
126
127
128
} estimate_irg_costs_env_t;

static void estimate_block_costs(ir_node *block, void *data)
{
129
	estimate_irg_costs_env_t *env = (estimate_irg_costs_env_t*)data;
130
	double costs = 0.0;
131
132

	sched_foreach(block, node) {
133
		costs += arch_get_op_estimated_cost(node);
134
135
136
137
	}

	env->costs += costs * get_block_execfreq(env->execfreqs, block);
}
138

139
double be_estimate_irg_costs(ir_graph *irg, ir_exec_freq *execfreqs)
140
141
{
	estimate_irg_costs_env_t env;
Christian Würdig's avatar
Christian Würdig committed
142

143
	env.execfreqs = execfreqs;
Christian Würdig's avatar
Christian Würdig committed
144
	env.costs     = 0.0;
145
146
147
148
149
150

	irg_block_walk_graph(irg, estimate_block_costs, NULL, &env);

	return env.costs;
}

Christian Würdig's avatar
Christian Würdig committed
151

152

Matthias Braun's avatar
Matthias Braun committed
153
154
static void node_stat_walker(ir_node *irn, void *data)
{
155
	be_node_stats_t *const stats = (be_node_stats_t*)data;
Matthias Braun's avatar
Matthias Braun committed
156
157

	/* if the node is a normal phi */
158
	if (is_Phi(irn)) {
Matthias Braun's avatar
Matthias Braun committed
159
160
161
162
163
		if (get_irn_mode(irn) == mode_M) {
			(*stats)[BE_STAT_MEM_PHIS]++;
		} else {
			(*stats)[BE_STAT_PHIS]++;
		}
164
165
166
167
	} else if (be_is_Perm(irn)) {
		(*stats)[BE_STAT_PERMS]++;
	} else if (be_is_Copy(irn)) {
		(*stats)[BE_STAT_COPIES]++;
Matthias Braun's avatar
Matthias Braun committed
168
169
170
	}
}

171
void be_collect_node_stats(be_node_stats_t *new_stats, ir_graph *irg)
Matthias Braun's avatar
Matthias Braun committed
172
{
173
	memset(new_stats, 0, sizeof(*new_stats));
174
	irg_walk_graph(irg, NULL, node_stat_walker, new_stats);
Matthias Braun's avatar
Matthias Braun committed
175
}
176

Matthias Braun's avatar
Matthias Braun committed
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
void be_subtract_node_stats(be_node_stats_t *stats, be_node_stats_t *sub)
{
	int i;
	for (i = 0; i < BE_STAT_COUNT; ++i) {
		(*stats)[i] -= (*sub)[i];
	}
}

void be_copy_node_stats(be_node_stats_t *dest, be_node_stats_t *src)
{
	memcpy(dest, src, sizeof(be_node_stats_t));
}

static const char *get_stat_name(enum be_stat_tag_t tag)
{
192
	switch (tag) {
Matthias Braun's avatar
Matthias Braun committed
193
194
195
196
197
198
199
200
201
202
	case BE_STAT_PHIS:     return "phis";
	case BE_STAT_MEM_PHIS: return "mem_phis";
	case BE_STAT_COPIES:   return "copies";
	case BE_STAT_PERMS:    return "perms";
	default:               panic("unknown stat tag found");
	}
}

void be_emit_node_stats(be_node_stats_t *stats, const char *prefix)
{
203
204
	static char   buf[256];
	be_stat_tag_t i;
Matthias Braun's avatar
Matthias Braun committed
205

206
	for (i = BE_STAT_FIRST; i < BE_STAT_COUNT; ++i) {
Matthias Braun's avatar
Matthias Braun committed
207
208
209
210
211
212
213
214
215
		snprintf(buf, sizeof(buf), "%s%s", prefix, get_stat_name(i));
		stat_ev_dbl(buf, (*stats)[i]);
	}
}



static void insn_count_walker(ir_node *irn, void *data)
{
216
	unsigned long *cnt = (unsigned long*)data;
Matthias Braun's avatar
Matthias Braun committed
217

218
	switch (get_irn_opcode(irn)) {
Matthias Braun's avatar
Matthias Braun committed
219
220
	case iro_Proj:
	case iro_Phi:
221
	case beo_Start:
Matthias Braun's avatar
Matthias Braun committed
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
	case iro_End:
		break;
	default:
		(*cnt)++;
	}
}

unsigned long be_count_insns(ir_graph *irg)
{
	unsigned long cnt = 0;
	irg_walk_graph(irg, insn_count_walker, NULL, &cnt);
	return cnt;
}

static void block_count_walker(ir_node *node, void *data)
{
238
	unsigned long *cnt = (unsigned long*)data;
239
	if (node == get_irg_end_block(get_irn_irg(node)))
Matthias Braun's avatar
Matthias Braun committed
240
241
242
243
244
245
246
247
248
249
		return;
	(*cnt)++;
}

unsigned long be_count_blocks(ir_graph *irg)
{
	unsigned long cnt = 0;
	irg_block_walk_graph(irg, block_count_walker, NULL, &cnt);
	return cnt;
}