irlivechk.c 13.7 KB
Newer Older
Michael Beck's avatar
Michael Beck committed
1
2
/*
 * This file is part of libFirm.
3
 * Copyright (C) 2012 Inria Rhone-Alpes.
Michael Beck's avatar
Michael Beck committed
4
5
 */

6
/**
7
 * @file
Michael Beck's avatar
Michael Beck committed
8
9
 * @date    21.04.2007
 * @author  Sebastian Hack
yb9976's avatar
yb9976 committed
10
 * @brief
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
 *
 * Liveness checks as developed by Benoit Boissinot, Fabrice Rastello and myself.
 *
 * The speciality here is, that nothing has to be recomputed if new nodes are created
 * or old ones deleted.
 *
 * This algo has one core routine check_live_end_internal() which performs the liveness check.
 * It only relies on the precomputation done in the constructor, which in turn needs:
 * - out edges
 * - the dominance tree
 * - data obtained from a depth-first-search
 *
 * The precomputation remains valid as long as the CFG is not altered.
 */
#include <stdio.h>

Matthias Braun's avatar
Matthias Braun committed
27
28
29
/* statev is expensive here, only enable when needed */
#define DISABLE_STATEV

30
#include "irgraph_t.h"
31
#include "irnode_t.h"
32
#include "irnodemap.h"
33
#include "iredges_t.h"
34
#include "irgraph_t.h"
35
#include "irdom.h"
36
37
38
39
40
41
#include "irdump.h"

#include "dfs_t.h"
#include "bitset.h"
#include "irlivechk.h"

Matthias Braun's avatar
Matthias Braun committed
42
#include "statev_t.h"
43

44
typedef struct bl_info_t {
45
	const ir_node *block;      /**< The block. */
46

Matthias Braun's avatar
Matthias Braun committed
47
48
	unsigned be_tgt_calc : 1;
	unsigned id : 31;          /**< a tight number for the block.
49
50
51
52
53
								 we're just reusing the pre num from
								 the DFS. */
	bitset_t *red_reachable;   /**< Holds all id's if blocks reachable
								 in the CFG modulo back edges. */

54
	bitset_t *be_tgt_reach;    /**< target blocks of back edges whose
55
56
57
58
								 sources are reachable from this block
								 in the reduced graph. */
} bl_info_t;

59
struct lv_chk_t {
60
61
	ir_nodemap     block_infos;
	struct obstack obst;
62
	dfs_t         *dfs;
63
64
65
66
	int            n_blocks;
	bitset_t      *back_edge_src;
	bitset_t      *back_edge_tgt;
	bl_info_t    **map;
Michael Beck's avatar
Michael Beck committed
67
	DEBUG_ONLY(firm_dbg_module_t *dbg;)
68
69
};

70
static bl_info_t *get_block_info(lv_chk_t *lv, const ir_node *block)
71
{
72
	bl_info_t *info = ir_nodemap_get(bl_info_t, &lv->block_infos, block);
73
	if (info == NULL) {
74
		info                = OALLOC(&lv->obst, bl_info_t);
75
76
77
78
79
80
81
82
		info->id            = get_Block_dom_tree_pre_num(block);
		info->block         = block;
		info->red_reachable = bitset_obstack_alloc(&lv->obst, lv->n_blocks);
		info->be_tgt_reach  = bitset_obstack_alloc(&lv->obst, lv->n_blocks);
		info->be_tgt_calc   = 0;
		ir_nodemap_insert(&lv->block_infos, block, info);
	}
	return info;
83
84
85
86
87
88
89
90
91
92
93
94
95
}

/**
 * Compute the transitive closure on the reduced graph.
 * The reduced graph is the original graph without back edges.
 * Since that is a DAG, a reverse post order of the graph gives a toposort
 * which is ideally suited to compute the transitive closure.
 * Note also, that the DFS tree of the reduced graph is the same than the one
 * of the original graph. This saves us computing a new reverse post order.
 * We also can re-use the DFS tree of the original graph.
 */
static void red_trans_closure(lv_chk_t *lv)
{
Matthias Braun's avatar
Matthias Braun committed
96
	for (int i = 0, n = dfs_get_n_nodes(lv->dfs); i < n; ++i) {
97
		const ir_node *bl = (const ir_node*) dfs_get_post_num_node(lv->dfs, i);
Matthias Braun's avatar
Matthias Braun committed
98
		bl_info_t     *bi = get_block_info(lv, bl);
99

100
		bitset_set(bi->red_reachable, bi->id);
Matthias Braun's avatar
Matthias Braun committed
101
102
103
		foreach_block_succ(bl, edge) {
			ir_node        *succ = get_edge_src_irn(edge);
			bl_info_t      *si   = get_block_info(lv, succ);
104
105
106
107
108
109
110
			dfs_edge_kind_t kind = dfs_get_edge_kind(lv->dfs, bl, succ);

			/*
			 * if the successor is no back edge, include all reachable
			 * blocks from there into the reachable set of the current node
			 */
			if (kind != DFS_EDGE_BACK) {
111
				assert(dfs_get_post_num(lv->dfs, bl) > dfs_get_post_num(lv->dfs, succ));
112
				bitset_or(bi->red_reachable, si->red_reachable);
Matthias Braun's avatar
Matthias Braun committed
113
114
			} else {
				/* mark block as a back edge src and succ as back edge tgt. */
115
116
117
118
119
120
121
122
123
				bitset_set(lv->back_edge_src, bi->id);
				bitset_set(lv->back_edge_tgt, si->id);
			}
		}

	}

}

124
static void compute_back_edge_chain(lv_chk_t *lv, const ir_node *bl)
125
{
126
127
	bl_info_t *bi = get_block_info(lv, bl);
	DBG((lv->dbg, LEVEL_2, "computing T_%d\n", bi->id));
128

129
	/* put all back edge sources reachable (reduced) from here in tmp */
Matthias Braun's avatar
Matthias Braun committed
130
	bitset_t *tmp = bitset_alloca(lv->n_blocks);
131
132
133
	bitset_copy(tmp, bi->red_reachable);
	bitset_set(tmp, bi->id);
	bitset_and(tmp, lv->back_edge_src);
Matthias Braun's avatar
Matthias Braun committed
134
	bi->be_tgt_calc = true;
135
136
137
138
139
140

	DBG((lv->dbg, LEVEL_2, "\treachable be src: %B\n", tmp));

	/* iterate over them ... */
	bitset_foreach(tmp, elm) {
		bl_info_t *si = lv->map[elm];
141

142
		/* and find back edge targets which are not reduced reachable from bl */
Matthias Braun's avatar
Matthias Braun committed
143
144
145
		foreach_block_succ(si->block, edge) {
			ir_node        *tgt  = get_edge_src_irn(edge);
			bl_info_t      *ti   = get_block_info(lv, tgt);
146
147
148
149
150
151
152
153
154
155
156
157
158
			dfs_edge_kind_t kind = dfs_get_edge_kind(lv->dfs, si->block, tgt);

			if (kind == DFS_EDGE_BACK && !bitset_is_set(bi->red_reachable, ti->id)) {
				if (!ti->be_tgt_calc)
					compute_back_edge_chain(lv, tgt);
				bitset_set(bi->be_tgt_reach, ti->id);
				bitset_or(bi->be_tgt_reach, ti->be_tgt_reach);
			}
		}
		bitset_clear(bi->be_tgt_reach, bi->id);
	}
}

159

160
static inline void compute_back_edge_chains(lv_chk_t *lv)
161
162
163
164
165
166
{
	DBG((lv->dbg, LEVEL_2, "back edge sources: %B\n", lv->back_edge_src));
	bitset_foreach(lv->back_edge_src, elm) {
		compute_back_edge_chain(lv, lv->map[elm]->block);
	}

Matthias Braun's avatar
Matthias Braun committed
167
	for (int i = 0, n = dfs_get_n_nodes(lv->dfs); i < n; ++i) {
168
		const ir_node *bl = (const ir_node*) dfs_get_post_num_node(lv->dfs, i);
Matthias Braun's avatar
Matthias Braun committed
169
		bl_info_t     *bi = get_block_info(lv, bl);
170
171

		if (!bitset_is_set(lv->back_edge_tgt, bi->id)) {
Matthias Braun's avatar
Matthias Braun committed
172
173
174
			foreach_block_succ(bl, edge) {
				ir_node   *succ = get_edge_src_irn(edge);
				bl_info_t *si   = get_block_info(lv, succ);
175
176
177
178
179
180
				dfs_edge_kind_t kind = dfs_get_edge_kind(lv->dfs, bl, succ);

				if (kind != DFS_EDGE_BACK) {
					assert(dfs_get_post_num(lv->dfs, bl) > dfs_get_post_num(lv->dfs, succ));
					bitset_or(bi->be_tgt_reach, si->be_tgt_reach);
				}
181
182
183
			}
		}
	}
Sebastian Hack's avatar
Sebastian Hack committed
184

Matthias Braun's avatar
Matthias Braun committed
185
	for (int i = 0, n = dfs_get_n_nodes(lv->dfs); i < n; ++i) {
186
		const ir_node *bl = (const ir_node*) dfs_get_post_num_node(lv->dfs, i);
Matthias Braun's avatar
Matthias Braun committed
187
		bl_info_t     *bi = get_block_info(lv, bl);
Sebastian Hack's avatar
Sebastian Hack committed
188
189
		bitset_set(bi->be_tgt_reach, bi->id);
	}
190
191
}

192
lv_chk_t *lv_chk_new(ir_graph *irg)
193
{
194
195
	assure_irg_properties(irg, IR_GRAPH_PROPERTY_CONSISTENT_DOMINANCE);

Sebastian Hack's avatar
Sebastian Hack committed
196
	stat_ev_tim_push();
Matthias Braun's avatar
Matthias Braun committed
197
198
	lv_chk_t *res = XMALLOC(lv_chk_t);
	FIRM_DBG_REGISTER(res->dbg, "ir.ana.lvchk");
199
200
	ir_nodemap_init(&res->block_infos, irg);
	obstack_init(&res->obst);
201
	res->dfs           = dfs_new(&absgraph_irg_cfg_succ, irg);
202
	res->n_blocks      = dfs_get_n_nodes(res->dfs);
203
204
205
	res->back_edge_src = bitset_obstack_alloc(&res->obst, res->n_blocks);
	res->back_edge_tgt = bitset_obstack_alloc(&res->obst, res->n_blocks);
	res->map           = OALLOCNZ(&res->obst, bl_info_t*, res->n_blocks);
206
207

	/* fill the map which maps pre_num to block infos */
Matthias Braun's avatar
Matthias Braun committed
208
209
210
	for (int i = res->n_blocks; i-- > 0; ) {
		ir_node   *irn = (ir_node*)dfs_get_pre_num_node(res->dfs, i);
		bl_info_t *bi  = get_block_info(res, irn);
211
212
		assert(bi->id < res->n_blocks);
		assert(res->map[bi->id] == NULL);
213
		res->map[bi->id] = bi;
214
215
216
217
218
	}

	/* first of all, compute the transitive closure of the CFG *without* back edges */
	red_trans_closure(res);

219
220
	/* compute back edge chains */
	compute_back_edge_chains(res);
221

yb9976's avatar
yb9976 committed
222
#ifdef DEBUG_libfirm
Sebastian Hack's avatar
Sebastian Hack committed
223
	DBG((res->dbg, LEVEL_1, "liveness chk in %+F\n", irg));
Matthias Braun's avatar
Matthias Braun committed
224
225
226
	for (int i = res->n_blocks; i-- > 0; ) {
		const ir_node   *irn = (const ir_node*) dfs_get_pre_num_node(res->dfs, i);
		const bl_info_t *bi  = get_block_info(res, irn);
Sebastian Hack's avatar
Sebastian Hack committed
227
228
229
230
231
		DBG((res->dbg, LEVEL_1, "lv_chk for %d -> %+F\n", i, irn));
		DBG((res->dbg, LEVEL_1, "\tred reach: %B\n", bi->red_reachable));
		DBG((res->dbg, LEVEL_1, "\ttgt reach: %B\n", bi->be_tgt_reach));
	}
#endif
232
233
234
235

	DBG((res->dbg, LEVEL_1, "back edge src: %B\n", res->back_edge_src));
	DBG((res->dbg, LEVEL_1, "back edge tgt: %B\n", res->back_edge_tgt));

Sebastian Hack's avatar
Sebastian Hack committed
236
	stat_ev_tim_pop("lv_chk_cons_time");
237
238
239
240
241
	return res;
}

void lv_chk_free(lv_chk_t *lv)
{
242
	dfs_free(lv->dfs);
243
244
	obstack_free(&lv->obst, NULL);
	ir_nodemap_destroy(&lv->block_infos);
245
	free(lv);
246
247
}

248
unsigned lv_chk_bl_xxx(lv_chk_t *lv, const ir_node *bl, const ir_node *var)
249
{
Matthias Braun's avatar
Matthias Braun committed
250
	assert(is_Block(bl));
Michael Beck's avatar
Michael Beck committed
251
252
	stat_ev_cnt_decl(uses);
	stat_ev_cnt_decl(iter);
253

254
255
	/* If the variable ist no liveness related var, bail out. */
	if (!is_liveness_node(var))
256
257
		return 0;

Sebastian Hack's avatar
Sebastian Hack committed
258
259
	stat_ev_ctx_push_fmt("lv_chk", "%u", get_irn_idx(var));
	stat_ev_tim_push();
260

261
	/* If there is no dominance relation, go out, too */
Matthias Braun's avatar
Matthias Braun committed
262
263
	int            res    = 0;
	const ir_node *def_bl = get_nodes_block(var);
264
	if (!block_dominates(def_bl, bl)) {
265
266
		stat_ev("lv_chk_no_dom");
		goto end;
267
	}
268
269
270

	/*
	 * If the block in question is the same as the definition block,
271
	 * the algorithm is simple. Just check for uses not inside this block.
272
	 */
273
	if (def_bl == bl) {
274
		stat_ev("lv_chk_def_block");
275
		DBG((lv->dbg, LEVEL_2, "lv check same block %+F in %+F\n", var, bl));
Matthias Braun's avatar
Matthias Braun committed
276
277
		foreach_out_edge(var, edge) {
			ir_node *use = get_edge_src_irn(edge);
278
279
280
			if (!is_liveness_node(use))
				continue;

281
			stat_ev_cnt_inc(uses);
Matthias Braun's avatar
Matthias Braun committed
282
			ir_node *use_bl = get_nodes_block(use);
283
284
285
286
			if (is_Phi(use)) {
				int pos = get_edge_src_pos(edge);
				use_bl  = get_Block_cfgpred_block(use_bl, pos);

287
				if (use_bl == bl) {
288
					DBG((lv->dbg, LEVEL_2, "\tphi %+F in succ %+F,%d -> live end\n", use, use_bl, pos));
289
					res |= lv_chk_state_end;
290
291
292
				}
			}

293
			if (use_bl != def_bl) {
294
295
296
				res = lv_chk_state_end | lv_chk_state_out;
				goto end;
			}
297
298
		}

299
		goto end;
Matthias Braun's avatar
Matthias Braun committed
300
301
302
303
304
	} else {
		/*
		 * this is the more complicated case.
		 * We try to gather as much information as possible during looking
		 * at the uses.
305
		 *
Matthias Braun's avatar
Matthias Braun committed
306
307
		 * Note that we know for sure that bl != def_bl. That is sometimes
		 * silently exploited below.
308
		 */
Matthias Braun's avatar
Matthias Braun committed
309
310
		const bl_info_t *bli = get_block_info(lv, bl);
		const bl_info_t *def = get_block_info(lv, def_bl);
Sebastian Hack's avatar
Sebastian Hack committed
311
		(void) def;
Matthias Braun's avatar
Matthias Braun committed
312
313
314
		DBG((lv->dbg, LEVEL_2,
		     "lv check %+F (def in %+F #%d) in different block %+F #%d\n",
		     var, def_bl, def->id, bl, bli->id));
315

Matthias Braun's avatar
Matthias Braun committed
316
317
		bitset_t *uses = bitset_alloca(lv->n_blocks);
		foreach_out_edge(var, edge) {
318
			ir_node *user = get_edge_src_irn(edge);
319

320
			/* if the user is no liveness node, the use does not count */
321
322
323
			if (!is_liveness_node(user))
				continue;

324
			stat_ev_cnt_inc(uses);
325
326
327
328
329

			/* if the user is a phi, the use is in the predecessor
			 * furthermore, prepare a mask so that in the case where
			 * bl (the block in question) coincides with a use, it
			 * can be marked live_end there. */
Matthias Braun's avatar
Matthias Braun committed
330
331
			int      mask   = lv_chk_state_in;
			ir_node *use_bl = get_nodes_block(user);
332
			if (is_Phi(user)) {
333
334
				int pos = get_edge_src_pos(edge);
				use_bl  = get_Block_cfgpred_block(use_bl, pos);
335
336
				if (use_bl == NULL)
					continue;
337
338
				mask   |= lv_chk_state_end;
			}
339

340

341
342
343
344
345
346
			/* if the use block coincides with the query block, we
			 * already gather a little liveness information.
			 * The variable is surely live there, since bl != def_bl
			 * (that case is treated above). */
			if (use_bl == bl)
				res |= mask;
347

Matthias Braun's avatar
Matthias Braun committed
348
349
			const bl_info_t *bi = get_block_info(lv, use_bl);
			bitset_set(uses, bi->id);
350
		}
Matthias Braun's avatar
Matthias Braun committed
351
		DBG((lv->dbg, LEVEL_2, "\tuses: %B\n", uses));
352

353
354
355
356
		/* get the dominance range which really matters. all uses outside
		 * the definition's dominance range are not to consider. note,
		 * that the definition itself is also not considered. The case
		 * where bl == def_bl is considered above. */
Matthias Braun's avatar
Matthias Braun committed
357
358
		unsigned min_dom = get_Block_dom_tree_pre_num(def_bl) + 1;
		unsigned max_dom = get_Block_dom_max_subtree_pre_num(def_bl);
359
360
361

		/* prepare a set with all reachable back edge targets.
		 * this will determine our "looking points" from where
Sebastian Hack's avatar
Sebastian Hack committed
362
		 * we will search/find the calculated uses. */
Matthias Braun's avatar
Matthias Braun committed
363
		const bitset_t *Tq = bli->be_tgt_reach;
364
365
366
367
368

		/* now, visit all viewing points in the temporary bitset lying
		 * in the dominance range of the variable. Note that for reducible
		 * flow-graphs the first iteration is sufficient and the loop
		 * will be left. */
Matthias Braun's avatar
Matthias Braun committed
369
370
371
		DBG((lv->dbg, LEVEL_2, "\tbe tgt reach: %B, dom span: [%u, %u]\n", Tq,
		     min_dom, max_dom));
		size_t i = bitset_next_set(Tq, min_dom);
372
		while (i <= max_dom) {
Matthias Braun's avatar
Matthias Braun committed
373
374
			const bl_info_t *ti                   = lv->map[i];
			bool             use_in_current_block = bitset_is_set(uses, ti->id);
375

Sebastian Hack's avatar
Sebastian Hack committed
376
377
			stat_ev_cnt_inc(iter);

378
			/*
Michael Beck's avatar
Michael Beck committed
379
			 * This is somewhat tricky. Since this routine handles both, live in
380
381
382
			 * and end/out we have to handle all the border cases correctly.
			 * Each node is in its own red_reachable set (see calculation
			 * function above). That means, that in the case where bl == t, the
Michael Beck's avatar
Michael Beck committed
383
			 * intersection check of uses and reachability below will always
384
385
386
387
388
389
390
391
392
393
394
395
			 * find an intersection, namely t.
			 *
			 * However, if a block contains a use and the variable is dead
			 * afterwards, it is not live end/out at that block. Besides
			 * back-edge target. If a var is live-in at a back-edge target it
			 * is also live out/end there since the variable is live in the
			 * underlying loop. So in the case where t == bl and that is not
			 * a back-edge target, we have to remove that use from consideration
			 * to determine if the var is live out/end there.
			 *
			 * Note that the live in information has been calculated by the
			 * uses iteration above.
396
			 */
397
398
399
400
401
402
			if (ti == bli && !bitset_is_set(lv->back_edge_tgt, ti->id)) {
				DBG((lv->dbg, LEVEL_2, "\tlooking not from a back edge target and q == t. removing use: %d\n", ti->id));
				bitset_clear(uses, ti->id);
			}

			/* If we can reach a use, the variable is live there and we say goodbye */
Matthias Braun's avatar
Matthias Braun committed
403
404
			DBG((lv->dbg, LEVEL_2, "\tlooking from %d: seeing %B\n",
			     ti->id, ti->red_reachable));
405
406
			if (bitset_intersect(ti->red_reachable, uses)) {
				res |= lv_chk_state_in | lv_chk_state_out | lv_chk_state_end;
407
408
				goto end;
			}
409
410

			/*
411
412
413
			 * if we deleted a use do to the commentary above, we have to
			 * re-add it since it might be visible from further view points
			 * (we only need that in the non-reducible case).
414
			 */
415
416
			if (use_in_current_block)
				bitset_set(uses, ti->id);
Sebastian Hack's avatar
Sebastian Hack committed
417
418

			i = bitset_next_set(Tq, get_Block_dom_max_subtree_pre_num(ti->block) + 1);
419
		}
420
421
422

	}

423
end:
Sebastian Hack's avatar
Sebastian Hack committed
424
	stat_ev_tim_pop("lv_chk_query_time");
425
426
	stat_ev_cnt_done(uses, "lv_chk_uses");
	stat_ev_cnt_done(iter, "lv_chk_iter");
Sebastian Hack's avatar
Sebastian Hack committed
427
	stat_ev_ctx_pop("lv_chk");
428
429

	return res;
430
}