firmstat.c 62 KB
Newer Older
Christian Würdig's avatar
Christian Würdig committed
1
/*
2
 * Copyright (C) 1995-2010 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.
 */

Michael Beck's avatar
Michael Beck committed
20
21
22
23
/**
 * @file
 * @brief   Statistics for Firm.
 * @author  Michael Beck
24
 */
Matthias Braun's avatar
Matthias Braun committed
25
#include "config.h"
26

27
#include <stdio.h>
28
#include <stdlib.h>
29
#include <string.h>
30

31
32
33
#include "irouts.h"
#include "irdump.h"
#include "hashptr.h"
34
#include "firmstat_t.h"
Michael Beck's avatar
Michael Beck committed
35
#include "irpass_t.h"
36
37
#include "pattern.h"
#include "dags.h"
38
#include "stat_dmp.h"
Michael Beck's avatar
Michael Beck committed
39
#include "xmalloc.h"
40
#include "irhooks.h"
41
#include "util.h"
Michael Beck's avatar
Michael Beck committed
42

43
44
45
46
47
/*
 * need this to be static:
 * Special pseudo Opcodes that we need to count some interesting cases
 */

Michael Beck's avatar
Michael Beck committed
48
/**
49
 * The Phi0, a node that is created during SSA construction
Michael Beck's avatar
Michael Beck committed
50
 */
51
52
static ir_op _op_Phi0;

Michael Beck's avatar
Michael Beck committed
53
/** The PhiM, just to count memory Phi's. */
54
55
56
57
58
59
60
61
62
63
64
static ir_op _op_PhiM;

/** The Mul by Const node. */
static ir_op _op_MulC;

/** The Div by Const node. */
static ir_op _op_DivC;

/** The Div by Const node. */
static ir_op _op_ModC;

65
66
67
/** The memory Proj node. */
static ir_op _op_ProjM;

68
69
70
71
72
73
/** A Sel of a Sel */
static ir_op _op_SelSel;

/** A Sel of a Sel of a Sel */
static ir_op _op_SelSelSel;

Michael Beck's avatar
Michael Beck committed
74
75
/* ---------------------------------------------------------------------------------- */

76
/** Marks the begin of a statistic (hook) function. */
77
#define STAT_ENTER    ++status->recursive
78
79

/** Marks the end of a statistic (hook) functions. */
80
#define STAT_LEAVE    --status->recursive
81
82

/** Allows to enter a statistic function only when we are not already in a hook. */
83
#define STAT_ENTER_SINGLE    do { if (status->recursive > 0) return; ++status->recursive; } while (0)
Michael Beck's avatar
Michael Beck committed
84

85
/**
86
87
 * global status
 */
Michael Beck's avatar
Michael Beck committed
88
static const unsigned status_disable = 0;
89
static stat_info_t *status = (stat_info_t *)&status_disable;
90

91
/**
Michael Beck's avatar
Michael Beck committed
92
 * Compare two elements of the opcode hash.
93
 */
94
95
static int opcode_cmp(const void *elt, const void *key)
{
96
97
	const node_entry_t *e1 = (const node_entry_t*)elt;
	const node_entry_t *e2 = (const node_entry_t*)key;
98

Michael Beck's avatar
Michael Beck committed
99
	return e1->op->code - e2->op->code;
Michael Beck's avatar
Michael Beck committed
100
}  /* opcode_cmp */
101

102
/**
Michael Beck's avatar
Michael Beck committed
103
 * Compare two elements of the graph hash.
104
 */
105
106
static int graph_cmp(const void *elt, const void *key)
{
107
108
	const graph_entry_t *e1 = (const graph_entry_t*)elt;
	const graph_entry_t *e2 = (const graph_entry_t*)key;
109

Michael Beck's avatar
Michael Beck committed
110
	return e1->irg != e2->irg;
Michael Beck's avatar
Michael Beck committed
111
}  /* graph_cmp */
112

113
/**
Michael Beck's avatar
Michael Beck committed
114
 * Compare two elements of the optimization hash.
115
 */
116
117
static int opt_cmp(const void *elt, const void *key)
{
118
119
	const opt_entry_t *e1 = (const opt_entry_t*)elt;
	const opt_entry_t *e2 = (const opt_entry_t*)key;
120

Michael Beck's avatar
Michael Beck committed
121
	return e1->op->code != e2->op->code;
Michael Beck's avatar
Michael Beck committed
122
}  /* opt_cmp */
123

124
/**
Michael Beck's avatar
Michael Beck committed
125
 * Compare two elements of the block/extbb hash.
126
 */
127
128
static int block_cmp(const void *elt, const void *key)
{
129
130
	const block_entry_t *e1 = (const block_entry_t*)elt;
	const block_entry_t *e2 = (const block_entry_t*)key;
131

Michael Beck's avatar
Michael Beck committed
132
	/* it's enough to compare the block number */
Michael Beck's avatar
Michael Beck committed
133
	return e1->block_nr != e2->block_nr;
Michael Beck's avatar
Michael Beck committed
134
}  /* block_cmp */
135

136
/**
Michael Beck's avatar
Michael Beck committed
137
 * Compare two elements of the be_block hash.
138
 */
139
140
static int be_block_cmp(const void *elt, const void *key)
{
141
142
	const be_block_entry_t *e1 = (const be_block_entry_t*)elt;
	const be_block_entry_t *e2 = (const be_block_entry_t*)key;
143

Michael Beck's avatar
Michael Beck committed
144
	return e1->block_nr != e2->block_nr;
Michael Beck's avatar
Michael Beck committed
145
}  /* be_block_cmp */
146

147
/**
Michael Beck's avatar
Michael Beck committed
148
 * Compare two elements of reg pressure hash.
149
 */
150
151
static int reg_pressure_cmp(const void *elt, const void *key)
{
152
153
	const reg_pressure_entry_t *e1 = (const reg_pressure_entry_t*)elt;
	const reg_pressure_entry_t *e2 = (const reg_pressure_entry_t*)key;
154

Michael Beck's avatar
Michael Beck committed
155
	return e1->class_name != e2->class_name;
Michael Beck's avatar
Michael Beck committed
156
}  /* reg_pressure_cmp */
157

158
/**
Michael Beck's avatar
Michael Beck committed
159
 * Compare two elements of the perm_stat hash.
160
 */
161
162
static int perm_stat_cmp(const void *elt, const void *key)
{
163
164
	const perm_stat_entry_t *e1 = (const perm_stat_entry_t*)elt;
	const perm_stat_entry_t *e2 = (const perm_stat_entry_t*)key;
165

Michael Beck's avatar
Michael Beck committed
166
	return e1->perm != e2->perm;
Michael Beck's avatar
Michael Beck committed
167
}  /* perm_stat_cmp */
168
169

/**
Michael Beck's avatar
Michael Beck committed
170
 * Compare two elements of the perm_class hash.
171
 */
172
173
static int perm_class_cmp(const void *elt, const void *key)
{
174
175
	const perm_class_entry_t *e1 = (const perm_class_entry_t*)elt;
	const perm_class_entry_t *e2 = (const perm_class_entry_t*)key;
176

Michael Beck's avatar
Michael Beck committed
177
	return e1->class_name != e2->class_name;
Michael Beck's avatar
Michael Beck committed
178
}  /* perm_class_cmp */
179

Michael Beck's avatar
Michael Beck committed
180
/**
Michael Beck's avatar
Michael Beck committed
181
 * Compare two elements of the ir_op hash.
Michael Beck's avatar
Michael Beck committed
182
 */
183
184
static int opcode_cmp_2(const void *elt, const void *key)
{
185
186
	const ir_op *e1 = (const ir_op*)elt;
	const ir_op *e2 = (const ir_op*)key;
Michael Beck's avatar
Michael Beck committed
187

Michael Beck's avatar
Michael Beck committed
188
	return e1->code != e2->code;
Michael Beck's avatar
Michael Beck committed
189
}  /* opcode_cmp_2 */
Michael Beck's avatar
Michael Beck committed
190

191
/**
Michael Beck's avatar
Michael Beck committed
192
 * Compare two elements of the address_mark set.
193
 */
194
195
static int address_mark_cmp(const void *elt, const void *key, size_t size)
{
196
197
	const address_mark_entry_t *e1 = (const address_mark_entry_t*)elt;
	const address_mark_entry_t *e2 = (const address_mark_entry_t*)key;
Matthias Braun's avatar
Matthias Braun committed
198
	(void) size;
199

Michael Beck's avatar
Michael Beck committed
200
201
	/* compare only the nodes, the rest is used as data container */
	return e1->node != e2->node;
Michael Beck's avatar
Michael Beck committed
202
}  /* address_mark_cmp */
203

204
/**
Michael Beck's avatar
Michael Beck committed
205
 * Clear all counter in a node_entry_t.
206
 */
207
208
static void opcode_clear_entry(node_entry_t *elem)
{
Michael Beck's avatar
Michael Beck committed
209
210
211
	cnt_clr(&elem->cnt_alive);
	cnt_clr(&elem->new_node);
	cnt_clr(&elem->into_Id);
212
	cnt_clr(&elem->normalized);
Michael Beck's avatar
Michael Beck committed
213
}  /* opcode_clear_entry */
214

215
/**
Michael Beck's avatar
Michael Beck committed
216
217
 * Returns the associates node_entry_t for an ir_op (and allocates
 * one if not yet available).
Michael Beck's avatar
Michael Beck committed
218
219
220
 *
 * @param op    the IR operation
 * @param hmap  a hash map containing ir_op* -> node_entry_t*
221
 */
222
223
static node_entry_t *opcode_get_entry(const ir_op *op, hmap_node_entry_t *hmap)
{
Michael Beck's avatar
Michael Beck committed
224
225
	node_entry_t key;
	node_entry_t *elem;
226

Michael Beck's avatar
Michael Beck committed
227
	key.op = op;
228

229
	elem = (node_entry_t*)pset_find(hmap, &key, op->code);
Michael Beck's avatar
Michael Beck committed
230
231
	if (elem)
		return elem;
232

233
	elem = OALLOCZ(&status->cnts, node_entry_t);
234

Michael Beck's avatar
Michael Beck committed
235
236
	/* clear counter */
	opcode_clear_entry(elem);
237

Michael Beck's avatar
Michael Beck committed
238
	elem->op = op;
239

240
	return (node_entry_t*)pset_insert(hmap, elem, op->code);
Michael Beck's avatar
Michael Beck committed
241
}  /* opcode_get_entry */
242

Michael Beck's avatar
Michael Beck committed
243
244
/**
 * Returns the associates ir_op for an opcode
Michael Beck's avatar
Michael Beck committed
245
246
247
 *
 * @param code  the IR opcode
 * @param hmap  the hash map containing opcode -> ir_op*
Michael Beck's avatar
Michael Beck committed
248
 */
249
250
static ir_op *opcode_find_entry(ir_opcode code, hmap_ir_op *hmap)
{
Michael Beck's avatar
Michael Beck committed
251
	ir_op key;
Michael Beck's avatar
Michael Beck committed
252

Michael Beck's avatar
Michael Beck committed
253
	key.code = code;
254
	return (ir_op*)pset_find(hmap, &key, code);
Michael Beck's avatar
Michael Beck committed
255
}  /* opcode_find_entry */
Michael Beck's avatar
Michael Beck committed
256

257
/**
Michael Beck's avatar
Michael Beck committed
258
259
260
261
 * Clears all counter in a graph_entry_t.
 *
 * @param elem  the graph entry
 * @param all   if non-zero, clears all counters, else leave accumulated ones
262
 */
263
264
static void graph_clear_entry(graph_entry_t *elem, int all)
{
Michael Beck's avatar
Michael Beck committed
265
266
	int i;

Michael Beck's avatar
Michael Beck committed
267
	/* clear accumulated / non-accumulated counter */
Michael Beck's avatar
Michael Beck committed
268
269
270
	for (i = all ? 0 : _gcnt_non_acc; i < _gcnt_last; ++i) {
		cnt_clr(&elem->cnt[i]);
	}  /* for */
Michael Beck's avatar
Michael Beck committed
271
272
273
274
275
276
277
278
279
280
281
282
283

	if (elem->block_hash) {
		del_pset(elem->block_hash);
		elem->block_hash = NULL;
	}  /* if */

	if (elem->extbb_hash) {
		del_pset(elem->extbb_hash);
		elem->extbb_hash = NULL;
	}  /* if */

	obstack_free(&elem->recalc_cnts, NULL);
	obstack_init(&elem->recalc_cnts);
Michael Beck's avatar
Michael Beck committed
284
}  /* graph_clear_entry */
285

286
/**
Michael Beck's avatar
Michael Beck committed
287
288
 * Returns the associated graph_entry_t for an IR graph.
 *
Michael Beck's avatar
Michael Beck committed
289
 * @param irg   the IR graph, NULL for the global counter
Michael Beck's avatar
Michael Beck committed
290
 * @param hmap  the hash map containing ir_graph* -> graph_entry_t*
291
 */
Michael Beck's avatar
Michael Beck committed
292
static graph_entry_t *graph_get_entry(ir_graph *irg, hmap_graph_entry_t *hmap)
293
{
Michael Beck's avatar
Michael Beck committed
294
295
	graph_entry_t key;
	graph_entry_t *elem;
Matthias Braun's avatar
Matthias Braun committed
296
	size_t i;
297

Michael Beck's avatar
Michael Beck committed
298
	key.irg = irg;
299

300
	elem = (graph_entry_t*)pset_find(hmap, &key, HASH_PTR(irg));
301

Michael Beck's avatar
Michael Beck committed
302
303
304
305
	if (elem) {
		/* create hash map backend block information */
		if (! elem->be_block_hash)
			elem->be_block_hash = new_pset(be_block_cmp, 5);
306

Michael Beck's avatar
Michael Beck committed
307
308
		return elem;
	}  /* if */
309

Michael Beck's avatar
Michael Beck committed
310
	/* allocate a new one */
311
	elem = OALLOCZ(&status->cnts, graph_entry_t);
Michael Beck's avatar
Michael Beck committed
312
	obstack_init(&elem->recalc_cnts);
313

Michael Beck's avatar
Michael Beck committed
314
315
	/* clear counter */
	graph_clear_entry(elem, 1);
316

Michael Beck's avatar
Michael Beck committed
317
318
319
320
	/* new hash table for opcodes here  */
	elem->opcode_hash   = new_pset(opcode_cmp, 5);
	elem->address_mark  = new_set(address_mark_cmp, 5);
	elem->irg           = irg;
321

Michael Beck's avatar
Michael Beck committed
322
323
324
	/* these hash tables are created on demand */
	elem->block_hash = NULL;
	elem->extbb_hash = NULL;
Michael Beck's avatar
Michael Beck committed
325

326
	for (i = 0; i != ARRAY_SIZE(elem->opt_hash); ++i)
Michael Beck's avatar
Michael Beck committed
327
		elem->opt_hash[i] = new_pset(opt_cmp, 4);
328

329
	return (graph_entry_t*)pset_insert(hmap, elem, HASH_PTR(irg));
Michael Beck's avatar
Michael Beck committed
330
}  /* graph_get_entry */
331

332
/**
Michael Beck's avatar
Michael Beck committed
333
 * Clear all counter in an opt_entry_t.
334
 */
335
336
static void opt_clear_entry(opt_entry_t *elem)
{
Michael Beck's avatar
Michael Beck committed
337
	cnt_clr(&elem->count);
Michael Beck's avatar
Michael Beck committed
338
}  /* opt_clear_entry */
339

340
/**
Michael Beck's avatar
Michael Beck committed
341
342
343
344
 * Returns the associated opt_entry_t for an IR operation.
 *
 * @param op    the IR operation
 * @param hmap  the hash map containing ir_op* -> opt_entry_t*
345
 */
Michael Beck's avatar
Michael Beck committed
346
static opt_entry_t *opt_get_entry(const ir_op *op, hmap_opt_entry_t *hmap)
347
{
Michael Beck's avatar
Michael Beck committed
348
349
	opt_entry_t key;
	opt_entry_t *elem;
350

Michael Beck's avatar
Michael Beck committed
351
	key.op = op;
352

353
	elem = (opt_entry_t*)pset_find(hmap, &key, op->code);
Michael Beck's avatar
Michael Beck committed
354
355
	if (elem)
		return elem;
356

357
	elem = OALLOCZ(&status->cnts, opt_entry_t);
358

Michael Beck's avatar
Michael Beck committed
359
360
	/* clear new counter */
	opt_clear_entry(elem);
361

Michael Beck's avatar
Michael Beck committed
362
	elem->op = op;
363

364
	return (opt_entry_t*)pset_insert(hmap, elem, op->code);
Michael Beck's avatar
Michael Beck committed
365
}  /* opt_get_entry */
366

367
368
369
/**
 * clears all counter in a block_entry_t
 */
370
371
static void block_clear_entry(block_entry_t *elem)
{
Michael Beck's avatar
Michael Beck committed
372
373
374
375
	int i;

	for (i = 0; i < _bcnt_last; ++i)
		cnt_clr(&elem->cnt[i]);
Michael Beck's avatar
Michael Beck committed
376
}  /* block_clear_entry */
377

378
/**
Michael Beck's avatar
Michael Beck committed
379
380
381
382
 * Returns the associated block_entry_t for an block.
 *
 * @param block_nr  an IR  block number
 * @param hmap      a hash map containing long -> block_entry_t
383
 */
384
static block_entry_t *block_get_entry(struct obstack *obst, long block_nr, hmap_block_entry_t *hmap)
385
{
Michael Beck's avatar
Michael Beck committed
386
387
	block_entry_t key;
	block_entry_t *elem;
388

Michael Beck's avatar
Michael Beck committed
389
	key.block_nr = block_nr;
390

391
	elem = (block_entry_t*)pset_find(hmap, &key, block_nr);
Michael Beck's avatar
Michael Beck committed
392
393
	if (elem)
		return elem;
394

395
	elem = OALLOCZ(obst, block_entry_t);
396

Michael Beck's avatar
Michael Beck committed
397
398
	/* clear new counter */
	block_clear_entry(elem);
399

Michael Beck's avatar
Michael Beck committed
400
	elem->block_nr = block_nr;
401

402
	return (block_entry_t*)pset_insert(hmap, elem, block_nr);
Michael Beck's avatar
Michael Beck committed
403
}  /* block_get_entry */
404

405
/**
Michael Beck's avatar
Michael Beck committed
406
 * Clear all sets in be_block_entry_t.
407
408
409
410
411
412
 */
static void be_block_clear_entry(be_block_entry_t *elem)
{
	if (elem->reg_pressure)
		del_pset(elem->reg_pressure);

413
414
415
	if (elem->sched_ready)
		stat_delete_distrib_tbl(elem->sched_ready);

416
417
418
419
420
421
	if (elem->perm_class_stat)
		del_pset(elem->perm_class_stat);

	elem->reg_pressure    = new_pset(reg_pressure_cmp, 5);
	elem->sched_ready     = stat_new_int_distrib_tbl();
	elem->perm_class_stat = new_pset(perm_class_cmp, 5);
Michael Beck's avatar
Michael Beck committed
422
}  /* be_block_clear_entry */
423
424
425
426
427
428
429
430
431

/**
 * Returns the associated be_block_entry_t for an block.
 *
 * @param block_nr  an IR  block number
 * @param hmap      a hash map containing long -> be_block_entry_t
 */
static be_block_entry_t *be_block_get_entry(struct obstack *obst, long block_nr, hmap_be_block_entry_t *hmap)
{
Michael Beck's avatar
Michael Beck committed
432
433
	be_block_entry_t key;
	be_block_entry_t *elem;
434

Michael Beck's avatar
Michael Beck committed
435
	key.block_nr = block_nr;
436

437
	elem = (be_block_entry_t*)pset_find(hmap, &key, block_nr);
Michael Beck's avatar
Michael Beck committed
438
439
	if (elem)
		return elem;
440

441
	elem = OALLOCZ(obst, be_block_entry_t);
442

Michael Beck's avatar
Michael Beck committed
443
444
	/* clear new counter */
	be_block_clear_entry(elem);
445

Michael Beck's avatar
Michael Beck committed
446
	elem->block_nr = block_nr;
447

448
	return (be_block_entry_t*)pset_insert(hmap, elem, block_nr);
Michael Beck's avatar
Michael Beck committed
449
}  /* be_block_get_entry */
450

451
452
453
/**
 * clears all sets in perm_class_entry_t
 */
454
455
static void perm_class_clear_entry(perm_class_entry_t *elem)
{
456
457
458
459
	if (elem->perm_stat)
		del_pset(elem->perm_stat);

	elem->perm_stat = new_pset(perm_stat_cmp, 5);
Michael Beck's avatar
Michael Beck committed
460
}  /* perm_class_clear_entry */
461
462
463
464

/**
 * Returns the associated perm_class entry for a register class.
 *
465
466
 * @param class_name  the register class name
 * @param hmap        a hash map containing class_name -> perm_class_entry_t
467
 */
468
469
static perm_class_entry_t *perm_class_get_entry(struct obstack *obst, const char *class_name,
                                                hmap_perm_class_entry_t *hmap)
470
{
Michael Beck's avatar
Michael Beck committed
471
472
	perm_class_entry_t key;
	perm_class_entry_t *elem;
473

Michael Beck's avatar
Michael Beck committed
474
	key.class_name = class_name;
475

476
	elem = (perm_class_entry_t*)pset_find(hmap, &key, HASH_PTR(class_name));
Michael Beck's avatar
Michael Beck committed
477
478
	if (elem)
		return elem;
479

480
	elem = OALLOCZ(obst, perm_class_entry_t);
481

Michael Beck's avatar
Michael Beck committed
482
483
	/* clear new counter */
	perm_class_clear_entry(elem);
484

Michael Beck's avatar
Michael Beck committed
485
	elem->class_name = class_name;
486

487
	return (perm_class_entry_t*)pset_insert(hmap, elem, HASH_PTR(class_name));
Michael Beck's avatar
Michael Beck committed
488
}  /* perm_class_get_entry */
489
490
491
492

/**
 * clears all sets in perm_stat_entry_t
 */
493
494
static void perm_stat_clear_entry(perm_stat_entry_t *elem)
{
495
496
497
498
499
500
501
502
	if (elem->chains)
		stat_delete_distrib_tbl(elem->chains);

	if (elem->cycles)
		stat_delete_distrib_tbl(elem->cycles);

	elem->chains = stat_new_int_distrib_tbl();
	elem->cycles = stat_new_int_distrib_tbl();
Michael Beck's avatar
Michael Beck committed
503
}  /* perm_stat_clear_entry */
504
505
506
507
508
509
510
511
512

/**
 * Returns the associated perm_stat entry for a perm.
 *
 * @param perm      the perm node
 * @param hmap      a hash map containing perm -> perm_stat_entry_t
 */
static perm_stat_entry_t *perm_stat_get_entry(struct obstack *obst, ir_node *perm, hmap_perm_stat_entry_t *hmap)
{
Michael Beck's avatar
Michael Beck committed
513
514
	perm_stat_entry_t key;
	perm_stat_entry_t *elem;
515

Michael Beck's avatar
Michael Beck committed
516
	key.perm = perm;
517

518
	elem = (perm_stat_entry_t*)pset_find(hmap, &key, HASH_PTR(perm));
Michael Beck's avatar
Michael Beck committed
519
520
	if (elem)
		return elem;
521

522
	elem = OALLOCZ(obst, perm_stat_entry_t);
523

Michael Beck's avatar
Michael Beck committed
524
525
	/* clear new counter */
	perm_stat_clear_entry(elem);
526

Michael Beck's avatar
Michael Beck committed
527
	elem->perm = perm;
528

529
	return (perm_stat_entry_t*)pset_insert(hmap, elem, HASH_PTR(perm));
Michael Beck's avatar
Michael Beck committed
530
}  /* perm_stat_get_entry */
531

Michael Beck's avatar
Michael Beck committed
532
533
534
/**
 * Clear optimizations counter,
 */
535
536
static void clear_optimization_counter(void)
{
Michael Beck's avatar
Michael Beck committed
537
538
539
540
541
	int i;
	for (i = 0; i < FS_OPT_MAX; ++i)
		cnt_clr(&status->num_opts[i]);
}

Michael Beck's avatar
Michael Beck committed
542
543
/**
 * Returns the ir_op for an IR-node,
Michael Beck's avatar
Michael Beck committed
544
545
546
 * handles special cases and return pseudo op codes.
 *
 * @param none  an IR node
Michael Beck's avatar
Michael Beck committed
547
 */
548
static ir_op *stat_get_irn_op(ir_node *node)
Michael Beck's avatar
Michael Beck committed
549
{
Michael Beck's avatar
Michael Beck committed
550
	ir_op *op = get_irn_op(node);
551
	unsigned opc = op->code;
Michael Beck's avatar
Michael Beck committed
552
553
554
555
556
557
558
559
560

	switch (opc) {
	case iro_Phi:
		if (get_irn_arity(node) == 0) {
			/* special case, a Phi0 node, count on extra counter */
			op = status->op_Phi0 ? status->op_Phi0 : op;
		} else if (get_irn_mode(node) == mode_M) {
			/* special case, a Memory Phi node, count on extra counter */
			op = status->op_PhiM ? status->op_PhiM : op;
Michael Beck's avatar
Michael Beck committed
561
		}  /* if */
Michael Beck's avatar
Michael Beck committed
562
563
564
565
566
567
568
569
		break;
	case iro_Proj:
		if (get_irn_mode(node) == mode_M) {
			/* special case, a Memory Proj node, count on extra counter */
			op = status->op_ProjM ? status->op_ProjM : op;
		}  /* if */
		break;
	case iro_Mul:
Michael Beck's avatar
Michael Beck committed
570
		if (is_Const(get_Mul_left(node)) || is_Const(get_Mul_right(node))) {
Michael Beck's avatar
Michael Beck committed
571
572
573
574
575
			/* special case, a Multiply by a const, count on extra counter */
			op = status->op_MulC ? status->op_MulC : op;
		}  /* if */
		break;
	case iro_Div:
Michael Beck's avatar
Michael Beck committed
576
		if (is_Const(get_Div_right(node))) {
Michael Beck's avatar
Michael Beck committed
577
578
579
580
581
			/* special case, a division by a const, count on extra counter */
			op = status->op_DivC ? status->op_DivC : op;
		}  /* if */
		break;
	case iro_Mod:
Michael Beck's avatar
Michael Beck committed
582
		if (is_Const(get_Mod_right(node))) {
Michael Beck's avatar
Michael Beck committed
583
584
585
586
587
			/* special case, a module by a const, count on extra counter */
			op = status->op_ModC ? status->op_ModC : op;
		}  /* if */
		break;
	case iro_Sel:
588
		if (is_Sel(get_Sel_ptr(node))) {
Michael Beck's avatar
Michael Beck committed
589
590
			/* special case, a Sel of a Sel, count on extra counter */
			op = status->op_SelSel ? status->op_SelSel : op;
591
			if (is_Sel(get_Sel_ptr(get_Sel_ptr(node)))) {
Michael Beck's avatar
Michael Beck committed
592
593
594
595
596
597
				/* special case, a Sel of a Sel of a Sel, count on extra counter */
				op = status->op_SelSelSel ? status->op_SelSelSel : op;
			}  /* if */
		}  /* if */
		break;
	default:
598
		break;
Michael Beck's avatar
Michael Beck committed
599
	}  /* switch */
Michael Beck's avatar
Michael Beck committed
600
601

	return op;
Michael Beck's avatar
Michael Beck committed
602
}  /* stat_get_irn_op */
Michael Beck's avatar
Michael Beck committed
603
604

/**
605
 * update the block counter
Michael Beck's avatar
Michael Beck committed
606
 */
Michael Beck's avatar
Michael Beck committed
607
static void undate_block_info(ir_node *node, graph_entry_t *graph)
608
{
Michael Beck's avatar
Michael Beck committed
609
610
611
612
613
614
615
616
617
	ir_op *op = get_irn_op(node);
	ir_node *block;
	block_entry_t *b_entry;
	int i, arity;

	/* check for block */
	if (op == op_Block) {
		arity = get_irn_arity(node);
		b_entry = block_get_entry(&graph->recalc_cnts, get_irn_node_nr(node), graph->block_hash);
Michael Beck's avatar
Michael Beck committed
618
619
620
621
622
		/* mark start end block to allow to filter them out */
		if (node == get_irg_start_block(graph->irg))
			b_entry->is_start = 1;
		else if (node == get_irg_end_block(graph->irg))
			b_entry->is_end = 1;
Michael Beck's avatar
Michael Beck committed
623
624
625
626
627
628
629

		/* count all incoming edges */
		for (i = 0; i < arity; ++i) {
			ir_node *pred = get_irn_n(node, i);
			ir_node *other_block = get_nodes_block(pred);
			block_entry_t *b_entry_other = block_get_entry(&graph->recalc_cnts, get_irn_node_nr(other_block), graph->block_hash);

630
			cnt_inc(&b_entry->cnt[bcnt_in_edges]);  /* an edge coming from another block */
Michael Beck's avatar
Michael Beck committed
631
			cnt_inc(&b_entry_other->cnt[bcnt_out_edges]);
Michael Beck's avatar
Michael Beck committed
632
633
634
		}  /* for */
		return;
	}  /* if */
635

Michael Beck's avatar
Michael Beck committed
636
637
	block   = get_nodes_block(node);
	b_entry = block_get_entry(&graph->recalc_cnts, get_irn_node_nr(block), graph->block_hash);
638

Michael Beck's avatar
Michael Beck committed
639
640
	if (op == op_Phi && mode_is_datab(get_irn_mode(node))) {
		/* count data Phi per block */
Michael Beck's avatar
Michael Beck committed
641
		cnt_inc(&b_entry->cnt[bcnt_phi_data]);
Michael Beck's avatar
Michael Beck committed
642
	}  /* if */
Michael Beck's avatar
Michael Beck committed
643

Michael Beck's avatar
Michael Beck committed
644
	/* we have a new node in our block */
Michael Beck's avatar
Michael Beck committed
645
	cnt_inc(&b_entry->cnt[bcnt_nodes]);
646

Michael Beck's avatar
Michael Beck committed
647
	/* don't count keep-alive edges */
Michael Beck's avatar
Michael Beck committed
648
	if (is_End(node))
Michael Beck's avatar
Michael Beck committed
649
		return;
Michael Beck's avatar
Michael Beck committed
650

Michael Beck's avatar
Michael Beck committed
651
	arity = get_irn_arity(node);
652

Michael Beck's avatar
Michael Beck committed
653
654
655
	for (i = 0; i < arity; ++i) {
		ir_node *pred = get_irn_n(node, i);
		ir_node *other_block;
656

Michael Beck's avatar
Michael Beck committed
657
		other_block = get_nodes_block(pred);
658

Michael Beck's avatar
Michael Beck committed
659
		if (other_block == block)
660
			cnt_inc(&b_entry->cnt[bcnt_edges]); /* a in block edge */
Michael Beck's avatar
Michael Beck committed
661
662
		else {
			block_entry_t *b_entry_other = block_get_entry(&graph->recalc_cnts, get_irn_node_nr(other_block), graph->block_hash);
663

664
			cnt_inc(&b_entry->cnt[bcnt_in_edges]);  /* an edge coming from another block */
Michael Beck's avatar
Michael Beck committed
665
			cnt_inc(&b_entry_other->cnt[bcnt_out_edges]);
Michael Beck's avatar
Michael Beck committed
666
667
		}  /* if */
	}  /* for */
Michael Beck's avatar
Michael Beck committed
668
}  /* undate_block_info */
Michael Beck's avatar
Michael Beck committed
669

Michael Beck's avatar
Michael Beck committed
670
/**
Michael Beck's avatar
Michael Beck committed
671
 * Update the extended block counter.
Michael Beck's avatar
Michael Beck committed
672
 */
Michael Beck's avatar
Michael Beck committed
673
static void update_extbb_info(ir_node *node, graph_entry_t *graph)
Michael Beck's avatar
Michael Beck committed
674
{
Michael Beck's avatar
Michael Beck committed
675
676
677
678
	ir_op *op = get_irn_op(node);
	ir_extblk *extbb;
	extbb_entry_t *eb_entry;
	int i, arity;
Michael Beck's avatar
Michael Beck committed
679

Michael Beck's avatar
Michael Beck committed
680
681
682
683
684
	/* check for block */
	if (op == op_Block) {
		extbb = get_nodes_extbb(node);
		arity = get_irn_arity(node);
		eb_entry = block_get_entry(&graph->recalc_cnts, get_extbb_node_nr(extbb), graph->extbb_hash);
Michael Beck's avatar
Michael Beck committed
685

Michael Beck's avatar
Michael Beck committed
686
687
688
689
		/* count all incoming edges */
		for (i = 0; i < arity; ++i) {
			ir_node *pred = get_irn_n(node, i);
			ir_extblk *other_extbb = get_nodes_extbb(pred);
Michael Beck's avatar
Michael Beck committed
690

Michael Beck's avatar
Michael Beck committed
691
692
			if (extbb != other_extbb) {
				extbb_entry_t *eb_entry_other = block_get_entry(&graph->recalc_cnts, get_extbb_node_nr(other_extbb), graph->extbb_hash);
Michael Beck's avatar
Michael Beck committed
693

694
				cnt_inc(&eb_entry->cnt[bcnt_in_edges]); /* an edge coming from another extbb */
Michael Beck's avatar
Michael Beck committed
695
				cnt_inc(&eb_entry_other->cnt[bcnt_out_edges]);
Michael Beck's avatar
Michael Beck committed
696
697
698
699
			}  /* if */
		}  /* for */
		return;
	}  /* if */
Michael Beck's avatar
Michael Beck committed
700

Michael Beck's avatar
Michael Beck committed
701
702
	extbb    = get_nodes_extbb(node);
	eb_entry = block_get_entry(&graph->recalc_cnts, get_extbb_node_nr(extbb), graph->extbb_hash);
Michael Beck's avatar
Michael Beck committed
703

Michael Beck's avatar
Michael Beck committed
704
705
	if (op == op_Phi && mode_is_datab(get_irn_mode(node))) {
		/* count data Phi per extbb */
Michael Beck's avatar
Michael Beck committed
706
		cnt_inc(&eb_entry->cnt[bcnt_phi_data]);
Michael Beck's avatar
Michael Beck committed
707
	}  /* if */
Michael Beck's avatar
Michael Beck committed
708

Michael Beck's avatar
Michael Beck committed
709
	/* we have a new node in our block */
Michael Beck's avatar
Michael Beck committed
710
	cnt_inc(&eb_entry->cnt[bcnt_nodes]);
Michael Beck's avatar
Michael Beck committed
711

Michael Beck's avatar
Michael Beck committed
712
	/* don't count keep-alive edges */
713
	if (is_End(node))
Michael Beck's avatar
Michael Beck committed
714
		return;
Michael Beck's avatar
Michael Beck committed
715

Michael Beck's avatar
Michael Beck committed
716
	arity = get_irn_arity(node);
Michael Beck's avatar
Michael Beck committed
717

Michael Beck's avatar
Michael Beck committed
718
719
720
	for (i = 0; i < arity; ++i) {
		ir_node *pred = get_irn_n(node, i);
		ir_extblk *other_extbb = get_nodes_extbb(pred);
Michael Beck's avatar
Michael Beck committed
721

Michael Beck's avatar
Michael Beck committed
722
		if (other_extbb == extbb)
723
			cnt_inc(&eb_entry->cnt[bcnt_edges]);    /* a in extbb edge */
Michael Beck's avatar
Michael Beck committed
724
725
		else {
			extbb_entry_t *eb_entry_other = block_get_entry(&graph->recalc_cnts, get_extbb_node_nr(other_extbb), graph->extbb_hash);
Michael Beck's avatar
Michael Beck committed
726

727
			cnt_inc(&eb_entry->cnt[bcnt_in_edges]); /* an edge coming from another extbb */
Michael Beck's avatar
Michael Beck committed
728
			cnt_inc(&eb_entry_other->cnt[bcnt_out_edges]);
Michael Beck's avatar
Michael Beck committed
729
730
		}  /* if */
	}  /* for */
Michael Beck's avatar
Michael Beck committed
731
}  /* update_extbb_info */
Michael Beck's avatar
Michael Beck committed
732

Michael Beck's avatar
Michael Beck committed
733
734
735
736
/**
 * Calculates how many arguments of the call are const, updates
 * param distribution.
 */
737
738
static void analyse_params_of_Call(graph_entry_t *graph, ir_node *call)
{
Michael Beck's avatar
Michael Beck committed
739
	int i, num_const_args = 0, num_local_adr = 0;
Michael Beck's avatar
Michael Beck committed
740
	int n = get_Call_n_params(call);
Michael Beck's avatar
Michael Beck committed
741

Michael Beck's avatar
Michael Beck committed
742
743
	for (i = 0; i < n; ++i) {
		ir_node *param = get_Call_param(call, i);
Michael Beck's avatar
Michael Beck committed
744

Michael Beck's avatar
Michael Beck committed
745
746
747
748
749
750
751
752
753
754
755
756
757
		if (is_irn_constlike(param))
			++num_const_args;
		else if (is_Sel(param)) {
			ir_node *base = param;

			do {
				base = get_Sel_ptr(base);
			} while (is_Sel(base));

			if (base == get_irg_frame(current_ir_graph))
				++num_local_adr;
		}

Michael Beck's avatar
Michael Beck committed
758
	}  /* for */
Michael Beck's avatar
Michael Beck committed
759
760
761
762
763
764
765
766
767
768

	if (num_const_args > 0)
		cnt_inc(&graph->cnt[gcnt_call_with_cnst_arg]);
	if (num_const_args == n)
		cnt_inc(&graph->cnt[gcnt_call_with_all_cnst_arg]);
	if (num_local_adr > 0)
		cnt_inc(&graph->cnt[gcnt_call_with_local_adr]);

	stat_inc_int_distrib_tbl(status->dist_param_cnt, n);
}  /* analyse_params_of_Call */
Michael Beck's avatar
Michael Beck committed
769

770
/**
Michael Beck's avatar
Michael Beck committed
771
 * Update info on calls.
Michael Beck's avatar
Michael Beck committed
772
773
774
 *
 * @param call   The call
 * @param graph  The graph entry containing the call
775
 */
776
static void stat_update_call(ir_node *call, graph_entry_t *graph)
777
{
778
779
780
781
	ir_node   *block = get_nodes_block(call);
	ir_node   *ptr = get_Call_ptr(call);
	ir_entity *ent = NULL;
	ir_graph  *callee = NULL;
Michael Beck's avatar
Michael Beck committed
782
783
784
785
786
787
788
789
790

	/*
	 * If the block is bad, the whole subgraph will collapse later
	 * so do not count this call.
	 * This happens in dead code.
	 */
	if (is_Bad(block))
		return;

Michael Beck's avatar
Michael Beck committed
791
	cnt_inc(&graph->cnt[gcnt_all_calls]);
Michael Beck's avatar
Michael Beck committed
792
793
794
795

	/* found a call, this function is not a leaf */
	graph->is_leaf = 0;

796
	if (is_SymConst(ptr)) {
Michael Beck's avatar
Michael Beck committed
797
798
799
800
801
802
803
804
		if (get_SymConst_kind(ptr) == symconst_addr_ent) {
			/* ok, we seems to know the entity */
			ent = get_SymConst_entity(ptr);
			callee = get_entity_irg(ent);

			/* it is recursive, if it calls at least once */
			if (callee == graph->irg)
				graph->is_recursive = 1;
805
806
			if (callee == NULL)
				cnt_inc(&graph->cnt[gcnt_external_calls]);
Michael Beck's avatar
Michael Beck committed
807
808
809
		}  /* if */
	} else {
		/* indirect call, be could not predict */
Michael Beck's avatar
Michael Beck committed
810
		cnt_inc(&graph->cnt[gcnt_indirect_calls]);
Michael Beck's avatar
Michael Beck committed
811
812
813
814
815
816

		/* NOT a leaf call */
		graph->is_leaf_call = LCS_NON_LEAF_CALL;
	}  /* if */

	/* check, if it's a chain-call: Then, the call-block
Michael Beck's avatar
Michael Beck committed
817
	 * must dominate the end block. */
Michael Beck's avatar
Michael Beck committed
818
819
820
821
822
823
824
	{
		ir_node *curr = get_irg_end_block(graph->irg);
		int depth = get_Block_dom_depth(block);

		for (; curr != block && get_Block_dom_depth(curr) > depth;) {
			curr = get_Block_idom(curr