belive.c 15.2 KB
Newer Older
Christian Würdig's avatar
Christian Würdig committed
1
/*
Michael Beck's avatar
Michael Beck committed
2
 * Copyright (C) 1995-2008 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.
 */

20
/**
Christian Würdig's avatar
Christian Würdig committed
21
22
23
24
 * @file
 * @brief       Interblock liveness analysis.
 * @author      Sebastian Hack
 * @date        06.12.2004
25
 */
26
#include "config.h"
27

28
29
30
/* statev is expensive here, only enable when needed */
#define DISABLE_STATEV

Sebastian Hack's avatar
Sebastian Hack committed
31
#include "iredges_t.h"
32
#include "irgwalk.h"
33
#include "irprintf.h"
34
#include "irdump_t.h"
35
#include "irnodeset.h"
36

Sebastian Hack's avatar
Sebastian Hack committed
37
#include "absgraph.h"
Matthias Braun's avatar
Matthias Braun committed
38
#include "statev_t.h"
39
#include "be_t.h"
40
#include "bearch.h"
41
42
#include "beutil.h"
#include "belive_t.h"
43
#include "besched.h"
Matthias Braun's avatar
Matthias Braun committed
44
#include "bemodule.h"
Sebastian Hack's avatar
Sebastian Hack committed
45

Matthias Braun's avatar
Matthias Braun committed
46
DEBUG_ONLY(static firm_dbg_module_t *dbg = NULL;)
47

48
#define LV_STD_SIZE             64
49

50
51
52
53
54
55
/**
 * Filter out some nodes for which we never need liveness.
 *
 * @param irn  the node t check
 * @return 0 if no liveness info is needed, 1 else
 */
56
static inline int is_liveness_node(const ir_node *irn)
57
{
58
	switch (get_irn_opcode(irn)) {
59
60
61
	case iro_Block:
	case iro_Bad:
	case iro_End:
62
	case iro_Anchor:
63
	case iro_NoMem:
64
		return 0;
65
66
	default:
		return 1;
67
	}
68
69
}

Sebastian Hack's avatar
Sebastian Hack committed
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
int (be_is_live_in)(const be_lv_t *lv, const ir_node *block, const ir_node *irn)
{
	return _be_is_live_xxx(lv, block, irn, be_lv_state_in);
}

int (be_is_live_out)(const be_lv_t *lv, const ir_node *block, const ir_node *irn)
{
	return _be_is_live_xxx(lv, block, irn, be_lv_state_out);
}

int (be_is_live_end)(const be_lv_t *lv, const ir_node *block, const ir_node *irn)
{
	return _be_is_live_xxx(lv, block, irn, be_lv_state_end);
}

85
static inline unsigned _be_liveness_bsearch(be_lv_info_t *arr, const ir_node *node)
Sebastian Hack's avatar
Sebastian Hack committed
86
{
87
	be_lv_info_t *payload = arr + 1;
Sebastian Hack's avatar
Sebastian Hack committed
88

89
	unsigned n   = arr[0].head.n_members;
Sebastian Hack's avatar
Sebastian Hack committed
90
91
92
93
	unsigned res = 0;
	int lo       = 0;
	int hi       = n;

Michael Beck's avatar
Michael Beck committed
94
	if (n == 0)
Sebastian Hack's avatar
Sebastian Hack committed
95
96
		return 0;

Michael Beck's avatar
Michael Beck committed
97
	do {
98
99
		int md           = lo + ((hi - lo) >> 1);
		ir_node *md_node = payload[md].node.node;
Sebastian Hack's avatar
Sebastian Hack committed
100

101
		if (node > md_node)
Sebastian Hack's avatar
Sebastian Hack committed
102
			lo = md + 1;
103
		else if (node < md_node)
Sebastian Hack's avatar
Sebastian Hack committed
104
105
106
107
108
109
110
			hi = md;
		else {
			res = md;
			break;
		}

		res = lo;
Michael Beck's avatar
Michael Beck committed
111
	} while (lo < hi);
Sebastian Hack's avatar
Sebastian Hack committed
112
113
114
115

	return res;
}

116
117
be_lv_info_node_t *be_lv_get(const be_lv_t *li, const ir_node *bl,
                             const ir_node *irn)
118
{
119
120
	be_lv_info_t *irn_live;
	be_lv_info_node_t *res = NULL;
Sebastian Hack's avatar
Sebastian Hack committed
121

Sebastian Hack's avatar
Sebastian Hack committed
122
	stat_ev_tim_push();
123
	irn_live = ir_nodehashmap_get(be_lv_info_t, &li->map, bl);
124
	if (irn_live != NULL) {
Sebastian Hack's avatar
Sebastian Hack committed
125
		/* Get the position of the index in the array. */
126
		int pos = _be_liveness_bsearch(irn_live, irn);
Sebastian Hack's avatar
Sebastian Hack committed
127
128

		/* Get the record in question. 1 must be added, since the first record contains information about the array and must be skipped. */
129
		be_lv_info_node_t *rec = &irn_live[pos + 1].node;
Sebastian Hack's avatar
Sebastian Hack committed
130
131

		/* Check, if the irn is in deed in the array. */
132
		if (rec->node == irn)
Sebastian Hack's avatar
Sebastian Hack committed
133
			res = rec;
Sebastian Hack's avatar
Sebastian Hack committed
134
	}
Sebastian Hack's avatar
Sebastian Hack committed
135
	stat_ev_tim_pop("be_lv_get");
Sebastian Hack's avatar
Sebastian Hack committed
136

Sebastian Hack's avatar
Sebastian Hack committed
137
	return res;
Sebastian Hack's avatar
Sebastian Hack committed
138
139
}

140
141
static be_lv_info_node_t *be_lv_get_or_set(be_lv_t *li, ir_node *bl,
                                           ir_node *irn)
Sebastian Hack's avatar
Sebastian Hack committed
142
{
143
	be_lv_info_t *irn_live = ir_nodehashmap_get(be_lv_info_t, &li->map, bl);
144
145
146
147
148
	if (irn_live == NULL) {
		irn_live = OALLOCNZ(&li->obst, be_lv_info_t, LV_STD_SIZE);
		irn_live[0].head.n_size = LV_STD_SIZE-1;
		ir_nodehashmap_insert(&li->map, bl, irn_live);
	}
Sebastian Hack's avatar
Sebastian Hack committed
149
150

	/* Get the position of the index in the array. */
151
	unsigned pos = _be_liveness_bsearch(irn_live, irn);
Sebastian Hack's avatar
Sebastian Hack committed
152
153

	/* Get the record in question. 1 must be added, since the first record contains information about the array and must be skipped. */
154
	be_lv_info_node_t *res = &irn_live[pos + 1].node;
Sebastian Hack's avatar
Sebastian Hack committed
155
156

	/* Check, if the irn is in deed in the array. */
157
	if (res->node != irn) {
158
		be_lv_info_t *payload;
159
160
		unsigned n_members = irn_live[0].head.n_members;
		unsigned n_size    = irn_live[0].head.n_size;
Sebastian Hack's avatar
Sebastian Hack committed
161
162
		unsigned i;

163
		if (n_members + 1 >= n_size) {
164
165
166
167
168
			/* double the array size. Remember that the first entry is
			 * metadata about the array and not a real array element */
			unsigned old_size_bytes  = (n_size + 1) * sizeof(irn_live[0]);
			unsigned new_size        = (2 * n_size) + 1;
			size_t   new_size_bytes  = new_size * sizeof(irn_live[0]);
169
			be_lv_info_t *nw = OALLOCN(&li->obst, be_lv_info_t, new_size);
170
171
172
			memcpy(nw, irn_live, old_size_bytes);
			memset(((char*) nw) + old_size_bytes, 0,
			       new_size_bytes - old_size_bytes);
173
			nw[0].head.n_size = new_size - 1;
Sebastian Hack's avatar
Sebastian Hack committed
174
			irn_live = nw;
175
			ir_nodehashmap_insert(&li->map, bl, nw);
Sebastian Hack's avatar
Sebastian Hack committed
176
177
178
		}

		payload = &irn_live[1];
179
		for (i = n_members; i > pos; --i) {
Sebastian Hack's avatar
Sebastian Hack committed
180
181
182
			payload[i] = payload[i - 1];
		}

183
		++irn_live[0].head.n_members;
Sebastian Hack's avatar
Sebastian Hack committed
184

185
186
187
		res        = &payload[pos].node;
		res->node  = irn;
		res->flags = 0;
Sebastian Hack's avatar
Sebastian Hack committed
188
189
190
191
192
193
194
195
196
	}

	return res;
}

/**
 * Removes a node from the list of live variables of a block.
 * @return 1 if the node was live at that block, 0 if not.
 */
197
static int be_lv_remove(be_lv_t *li, const ir_node *bl,
198
                        const ir_node *irn)
Sebastian Hack's avatar
Sebastian Hack committed
199
{
200
	be_lv_info_t *irn_live = ir_nodehashmap_get(be_lv_info_t, &li->map, bl);
Sebastian Hack's avatar
Sebastian Hack committed
201

202
203
	if (irn_live != NULL) {
		unsigned n   = irn_live[0].head.n_members;
204
		unsigned pos = _be_liveness_bsearch(irn_live, irn);
205
		be_lv_info_t *payload  = irn_live + 1;
206
		be_lv_info_node_t *res = &payload[pos].node;
Sebastian Hack's avatar
Sebastian Hack committed
207
208

		/* The node is in deed in the block's array. Let's remove it. */
209
		if (res->node == irn) {
Sebastian Hack's avatar
Sebastian Hack committed
210
211
			unsigned i;

212
			for (i = pos + 1; i < n; ++i)
Sebastian Hack's avatar
Sebastian Hack committed
213
214
				payload[i - 1] = payload[i];

215
			payload[n - 1].node.node  = NULL;
216
			payload[n - 1].node.flags = 0;
Sebastian Hack's avatar
Sebastian Hack committed
217

218
			--irn_live[0].head.n_members;
Matthias Braun's avatar
Matthias Braun committed
219
			DBG((dbg, LEVEL_3, "\tdeleting %+F from %+F at pos %d\n", irn, bl, pos));
Sebastian Hack's avatar
Sebastian Hack committed
220
221
222
223
224
225
226
			return 1;
		}
	}

	return 0;
}

Michael Beck's avatar
Michael Beck committed
227
228
229
/**
 * Mark a node as live-in in a block.
 */
230
static inline void mark_live_in(be_lv_t *lv, ir_node *block, ir_node *irn)
231
{
232
	be_lv_info_node_t *n = be_lv_get_or_set(lv, block, irn);
Matthias Braun's avatar
Matthias Braun committed
233
	DBG((dbg, LEVEL_2, "marking %+F live in at %+F\n", irn, block));
Sebastian Hack's avatar
Sebastian Hack committed
234
	n->flags |= be_lv_state_in;
235
236
}

Michael Beck's avatar
Michael Beck committed
237
238
239
/**
 * Mark a node as live-out in a block.
 */
240
static inline void mark_live_out(be_lv_t *lv, ir_node *block, ir_node *irn)
241
{
242
	be_lv_info_node_t *n = be_lv_get_or_set(lv, block, irn);
Matthias Braun's avatar
Matthias Braun committed
243
	DBG((dbg, LEVEL_2, "marking %+F live out at %+F\n", irn, block));
Sebastian Hack's avatar
Sebastian Hack committed
244
	n->flags |= be_lv_state_out | be_lv_state_end;
245
246
}

Michael Beck's avatar
Michael Beck committed
247
248
249
/**
 * Mark a node as live-end in a block.
 */
250
static inline void mark_live_end(be_lv_t *lv, ir_node *block, ir_node *irn)
251
{
252
	be_lv_info_node_t *n = be_lv_get_or_set(lv, block, irn);
Matthias Braun's avatar
Matthias Braun committed
253
	DBG((dbg, LEVEL_2, "marking %+F live end at %+F\n", irn, block));
Sebastian Hack's avatar
Sebastian Hack committed
254
	n->flags |= be_lv_state_end;
255
256
}

257
258
static struct {
	be_lv_t  *lv;         /**< The liveness object. */
259
	ir_node  *def;        /**< The node (value). */
260
261
262
263
	ir_node  *def_block;  /**< The block of def. */
	bitset_t *visited;    /**< A set were all visited blocks are recorded. */
} re;

264
265
266
267
268
/**
 * Mark a node (value) live out at a certain block. Do this also
 * transitively, i.e. if the block is not the block of the value's
 * definition, all predecessors are also marked live.
 * @param block The block to mark the value live out of.
269
270
 * @param is_true_out Is the node real out there or only live at the end
 * of the block.
271
 */
272
static void live_end_at_block(ir_node *block, int is_true_out)
273
{
274
275
276
277
	be_lv_t *lv  = re.lv;
	ir_node *def = re.def;
	bitset_t *visited;

Sebastian Hack's avatar
Sebastian Hack committed
278
	mark_live_end(lv, block, def);
279
	if (is_true_out)
Sebastian Hack's avatar
Sebastian Hack committed
280
		mark_live_out(lv, block, def);
281

282
	visited = re.visited;
Matthias Braun's avatar
Matthias Braun committed
283
284
	if (!bitset_is_set(visited, get_irn_idx(block))) {
		bitset_set(visited, get_irn_idx(block));
285

Sebastian Hack's avatar
Sebastian Hack committed
286
		/*
287
288
289
290
291
		 * If this block is not the definition block, we have to go up
		 * further.
		 */
		if (re.def_block != block) {
			int i;
292

Sebastian Hack's avatar
Sebastian Hack committed
293
			mark_live_in(lv, block, def);
294

295
296
			for (i = get_Block_n_cfgpreds(block) - 1; i >= 0; --i)
				live_end_at_block(get_Block_cfgpred_block(block, i), 1);
Sebastian Hack's avatar
Sebastian Hack committed
297
298
		}
	}
299
300
}

301
302
303
304
305
306
typedef struct lv_remove_walker_t {
	be_lv_t       *lv;
	const ir_node *irn;
} lv_remove_walker_t;


307
308
/**
 * Liveness analysis for a value.
309
310
 * Compute the set of all blocks a value is live in.
 * @param irn     The node (value).
311
 */
312
static void liveness_for_node(ir_node *irn)
313
{
Sebastian Hack's avatar
Sebastian Hack committed
314
315
	ir_node *def_block;

316
	bitset_clear_all(re.visited);
Sebastian Hack's avatar
Sebastian Hack committed
317
318
	def_block = get_nodes_block(irn);

319
320
321
	re.def       = irn;
	re.def_block = def_block;

Sebastian Hack's avatar
Sebastian Hack committed
322
323
324
325
326
	/* Go over all uses of the value */
	foreach_out_edge(irn, edge) {
		ir_node *use = edge->src;
		ir_node *use_block;

Sebastian Hack's avatar
Sebastian Hack committed
327
328
329
		DBG((dbg, LEVEL_4, "%+F: use at %+F, pos %d in %+F\n", irn, use, edge->pos, get_block(use)));
		assert(get_irn_n(use, edge->pos) == irn);

Sebastian Hack's avatar
Sebastian Hack committed
330
		/*
331
332
333
		 * If the usage is no data node, skip this use, since it does not
		 * affect the liveness of the node.
		 */
334
		if (!is_liveness_node(use))
Sebastian Hack's avatar
Sebastian Hack committed
335
336
337
338
339
340
			continue;

		/* Get the block where the usage is in. */
		use_block = get_nodes_block(use);

		/*
341
342
343
344
		 * If the use is a phi function, determine the corresponding block
		 * through which the value reaches the phi function and mark the
		 * value as live out of that block.
		 */
345
		if (is_Phi(use)) {
Sebastian Hack's avatar
Sebastian Hack committed
346
			ir_node *pred_block = get_Block_cfgpred_block(use_block, edge->pos);
347
			live_end_at_block(pred_block, 0);
Sebastian Hack's avatar
Sebastian Hack committed
348
		}
Sebastian Hack's avatar
Sebastian Hack committed
349

Sebastian Hack's avatar
Sebastian Hack committed
350
		/*
351
352
353
		 * Else, the value is live in at this block. Mark it and call live
		 * out on the predecessors.
		 */
354
		else if (def_block != use_block) {
355
			int i;
Sebastian Hack's avatar
Sebastian Hack committed
356

357
			mark_live_in(re.lv, use_block, irn);
Sebastian Hack's avatar
Sebastian Hack committed
358

359
			for (i = get_Block_n_cfgpreds(use_block) - 1; i >= 0; --i) {
Sebastian Hack's avatar
Sebastian Hack committed
360
				ir_node *pred_block = get_Block_cfgpred_block(use_block, i);
361
				live_end_at_block(pred_block, 1);
Sebastian Hack's avatar
Sebastian Hack committed
362
363
364
			}
		}
	}
365
366
}

Sebastian Hack's avatar
Sebastian Hack committed
367
static void lv_remove_irn_walker(ir_node *bl, void *data)
368
{
369
	lv_remove_walker_t *w = (lv_remove_walker_t*)data;
370
	be_lv_remove(w->lv, bl, w->irn);
371
}
Sebastian Hack's avatar
Sebastian Hack committed
372

373
374
375
376
/**
 * Walker, collect all nodes for which we want calculate liveness info
 * on an obstack.
 */
Michael Beck's avatar
Michael Beck committed
377
static void collect_liveness_nodes(ir_node *irn, void *data)
378
{
379
	ir_node **nodes = (ir_node**)data;
380
	if (is_liveness_node(irn))
381
		nodes[get_irn_idx(irn)] = irn;
382
383
}

384
void be_liveness_compute_sets(be_lv_t *lv)
Sebastian Hack's avatar
Sebastian Hack committed
385
{
386
	ir_node **nodes;
387
388
389
390
391
392
393
394
395
	int       i;
	int       n;

	if (lv->sets_valid)
		return;

	be_timer_push(T_LIVE);
	ir_nodehashmap_init(&lv->map);
	obstack_init(&lv->obst);
396

397
398
399
	n = get_irg_last_idx(lv->irg);
	nodes = NEW_ARR_F(ir_node *, n);
	memset(nodes, 0, sizeof(nodes[0]) * n);
400

401
	/* inserting the variables sorted by their ID is probably
402
	 * more efficient since the binary sorted set insertion
403
	 * will not need to move around the data. */
404
	irg_walk_graph(lv->irg, NULL, collect_liveness_nodes, nodes);
405

406
407
	re.lv      = lv;
	re.visited = bitset_malloc(n);
408

409
410
411
412
	for (i = 0; i < n; ++i) {
		if (nodes[i] != NULL)
			liveness_for_node(nodes[i]);
	}
413

414
415
	DEL_ARR_F(nodes);
	free(re.visited);
416

417
	be_timer_pop(T_LIVE);
Matthias Braun's avatar
Matthias Braun committed
418

419
420
	lv->sets_valid = true;
}
Matthias Braun's avatar
Matthias Braun committed
421

422
423
424
425
426
void be_liveness_compute_chk(be_lv_t *lv)
{
	if (lv->lvc != NULL)
		return;
	lv->lvc = lv_chk_new(lv->irg);
Sebastian Hack's avatar
Sebastian Hack committed
427
428
}

429
void be_liveness_invalidate_sets(be_lv_t *lv)
Sebastian Hack's avatar
Sebastian Hack committed
430
{
431
432
433
434
435
	if (!lv->sets_valid)
		return;
	obstack_free(&lv->obst, NULL);
	ir_nodehashmap_destroy(&lv->map);
	lv->sets_valid = false;
Sebastian Hack's avatar
Sebastian Hack committed
436
437
}

438
void be_liveness_invalidate_chk(be_lv_t *lv)
Sebastian Hack's avatar
Sebastian Hack committed
439
{
440
441
442
443
444
445
	be_liveness_invalidate_sets(lv);

	if (lv->lvc == NULL)
		return;
	lv_chk_free(lv->lvc);
	lv->lvc = NULL;
Sebastian Hack's avatar
Sebastian Hack committed
446
447
}

448
be_lv_t *be_liveness_new(ir_graph *irg)
Sebastian Hack's avatar
Sebastian Hack committed
449
{
450
	be_lv_t *lv = XMALLOCZ(be_lv_t);
Sebastian Hack's avatar
Sebastian Hack committed
451

452
	lv->irg = irg;
Sebastian Hack's avatar
Sebastian Hack committed
453
454
455

	return lv;
}
Sebastian Hack's avatar
Sebastian Hack committed
456

Sebastian Hack's avatar
Sebastian Hack committed
457
458
void be_liveness_free(be_lv_t *lv)
{
459
460
461
	be_liveness_invalidate_sets(lv);
	be_liveness_invalidate_chk(lv);

yb9976's avatar
yb9976 committed
462
	xfree(lv);
Sebastian Hack's avatar
Sebastian Hack committed
463
}
Sebastian Hack's avatar
Sebastian Hack committed
464

465
void be_liveness_remove(be_lv_t *lv, const ir_node *irn)
Sebastian Hack's avatar
Sebastian Hack committed
466
{
467
	if (lv->sets_valid) {
468
		lv_remove_walker_t w;
Sebastian Hack's avatar
Sebastian Hack committed
469

Sebastian Hack's avatar
Sebastian Hack committed
470
471
472
473
474
		/*
		 * Removes a single irn from the liveness information.
		 * Since an irn can only be live at blocks dominated by the block of its
		 * definition, we only have to process that dominance subtree.
		 */
475
476
		w.lv  = lv;
		w.irn = irn;
Sebastian Hack's avatar
Sebastian Hack committed
477
478
		dom_tree_walk(get_nodes_block(irn), lv_remove_irn_walker, NULL, &w);
	}
Sebastian Hack's avatar
Sebastian Hack committed
479
}
Sebastian Hack's avatar
Sebastian Hack committed
480

Sebastian Hack's avatar
Sebastian Hack committed
481
482
void be_liveness_introduce(be_lv_t *lv, ir_node *irn)
{
483
	/* Don't compute liveness information for non-data nodes. */
484
	if (lv->sets_valid && is_liveness_node(irn)) {
485
486
487
488
		re.lv      = lv;
		re.visited = bitset_malloc(get_irg_last_idx(lv->irg));
		liveness_for_node(irn);
		bitset_free(re.visited);
Sebastian Hack's avatar
Sebastian Hack committed
489
	}
Sebastian Hack's avatar
Sebastian Hack committed
490
491
492
493
494
495
496
497
}

void be_liveness_update(be_lv_t *lv, ir_node *irn)
{
	be_liveness_remove(lv, irn);
	be_liveness_introduce(lv, irn);
}

498
void be_liveness_transfer(const arch_register_class_t *cls,
499
                          ir_node *node, ir_nodeset_t *nodeset)
500
501
502
503
504
{
	/* You should better break out of your loop when hitting the first phi
	 * function. */
	assert(!is_Phi(node) && "liveness_transfer produces invalid results for phi nodes");

505
506
507
	be_foreach_definition(node, cls, value,
		ir_nodeset_remove(nodeset, value);
	);
508

509
510
	int arity = get_irn_arity(node);
	for (int i = 0; i < arity; ++i) {
511
512
513
514
515
		const arch_register_req_t *in_req = arch_get_irn_register_req_in(node, i);
		if (in_req->cls != cls)
			continue;
		ir_node                   *op     = get_irn_n(node, i);
		const arch_register_req_t *op_req = arch_get_irn_register_req(op);
516
		if (arch_register_req_is(op_req, ignore))
517
518
			continue;
		ir_nodeset_insert(nodeset, op);
519
520
521
522
523
	}
}



524
void be_liveness_end_of_block(const be_lv_t *lv,
525
526
                              const arch_register_class_t *cls,
                              const ir_node *block, ir_nodeset_t *live)
527
{
Matthias Braun's avatar
Matthias Braun committed
528
	assert(lv->sets_valid && "live sets must be computed");
529
	be_lv_foreach(lv, block, be_lv_state_end, node) {
530
		if (!arch_irn_consider_in_reg_alloc(cls, node))
531
532
533
534
535
536
537
538
			continue;

		ir_nodeset_insert(live, node);
	}
}



539
void be_liveness_nodes_live_before(be_lv_t const *const lv, arch_register_class_t const *const cls, ir_node const *const pos, ir_nodeset_t *const live)
Sebastian Hack's avatar
Sebastian Hack committed
540
{
541
	ir_node const *const bl = get_nodes_block(pos);
542
	be_liveness_end_of_block(lv, cls, bl, live);
Sebastian Hack's avatar
Sebastian Hack committed
543
	sched_foreach_reverse(bl, irn) {
544
		be_liveness_transfer(cls, irn, live);
545
		if (irn == pos)
546
			return;
Sebastian Hack's avatar
Sebastian Hack committed
547
548
	}
}
549

550
551
static void collect_node(ir_node *irn, void *data)
{
552
	struct obstack *obst = (struct obstack*)data;
553
554
555
	obstack_ptr_grow(obst, irn);
}

556
static void be_live_chk_compare(be_lv_t *lv, lv_chk_t *lvc)
557
{
Sebastian Hack's avatar
Sebastian Hack committed
558
	ir_graph *irg    = lv->irg;
559
560
561
562
563
564
565
566
567
568

	struct obstack obst;
	ir_node **nodes;
	ir_node **blocks;
	int i, j;

	obstack_init(&obst);

	irg_block_walk_graph(irg, collect_node, NULL, &obst);
	obstack_ptr_grow(&obst, NULL);
569
	blocks = (ir_node**)obstack_finish(&obst);
570
571
572

	irg_walk_graph(irg, collect_node, NULL, &obst);
	obstack_ptr_grow(&obst, NULL);
573
	nodes = (ir_node**)obstack_finish(&obst);
574

Sebastian Hack's avatar
Sebastian Hack committed
575
576
577
	stat_ev_ctx_push("be_lv_chk_compare");
	for (j = 0; nodes[j]; ++j) {
		ir_node *irn = nodes[j];
578
579
580
		if (is_Block(irn))
			continue;

Sebastian Hack's avatar
Sebastian Hack committed
581
582
		for (i = 0; blocks[i]; ++i) {
			ir_node *bl = blocks[i];
583
584
585
			int lvr_in  = be_is_live_in (lv, bl, irn);
			int lvr_out = be_is_live_out(lv, bl, irn);
			int lvr_end = be_is_live_end(lv, bl, irn);
586

587
588
589
			int lvc_in  = lv_chk_bl_in (lvc, bl, irn);
			int lvc_out = lv_chk_bl_out(lvc, bl, irn);
			int lvc_end = lv_chk_bl_end(lvc, bl, irn);
590

591
592
			if (lvr_in - lvc_in != 0)
				ir_fprintf(stderr, "live in  info for %+F at %+F differs: nml: %d, chk: %d\n", irn, bl, lvr_in, lvc_in);
593

594
595
			if (lvr_end - lvc_end != 0)
				ir_fprintf(stderr, "live end info for %+F at %+F differs: nml: %d, chk: %d\n", irn, bl, lvr_end, lvc_end);
596

597
598
			if (lvr_out - lvc_out != 0)
				ir_fprintf(stderr, "live out info for %+F at %+F differs: nml: %d, chk: %d\n", irn, bl, lvr_out, lvc_out);
599
600
		}
	}
Sebastian Hack's avatar
Sebastian Hack committed
601
	stat_ev_ctx_pop("be_lv_chk_compare");
602
603
604
605

	obstack_free(&obst, NULL);
}

Matthias Braun's avatar
Matthias Braun committed
606
BE_REGISTER_MODULE_CONSTRUCTOR(be_init_live)
Matthias Braun's avatar
Matthias Braun committed
607
608
void be_init_live(void)
{
609
	(void)be_live_chk_compare;
Matthias Braun's avatar
Matthias Braun committed
610
611
	FIRM_DBG_REGISTER(dbg, "firm.be.liveness");
}