1 /*
2  * Copyright (C) 1995-2008 University of Karlsruhe.  All right reserved.
3  *
4  * This file is part of libFirm.
5  *
6  * This file may be distributed and/or modified under the terms of the
7  * GNU General Public License version 2 as published by the Free Software
8  * Foundation and appearing in the file LICENSE.GPL included in the
9  * packaging of this file.
10  *
11  * Licensees holding valid libFirm Professional Edition licenses may use
12  * this file in accordance with the libFirm Commercial License.
13  * Agreement provided with the Software.
14  *
15  * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
16  * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
17  * PURPOSE.
18  */
19 
20 /**
21  * @file
22  * @brief       Interblock liveness analysis.
23  * @author      Sebastian Hack
24  * @date        06.12.2004
25  */
26 #include "config.h"
27 
28 /* statev is expensive here, only enable when needed */
29 #define DISABLE_STATEV
30 
31 #include "iredges_t.h"
32 #include "irgwalk.h"
33 #include "irprintf_t.h"
34 #include "irdump_t.h"
35 #include "irnodeset.h"
36 
37 #include "absgraph.h"
38 #include "statev_t.h"
39 
40 #include "beutil.h"
41 #include "belive_t.h"
42 #include "beirg.h"
43 #include "besched.h"
44 #include "bemodule.h"
45 #include "bedump.h"
46 
47 DEBUG_ONLY(static firm_dbg_module_t *dbg = NULL;)
48 
49 #define LV_STD_SIZE             64
50 
51 /**
52  * Filter out some nodes for which we never need liveness.
53  *
54  * @param irn  the node t check
55  * @return 0 if no liveness info is needed, 1 else
56  */
is_liveness_node(const ir_node * irn)57 static inline int is_liveness_node(const ir_node *irn)
58 {
59 	switch (get_irn_opcode(irn)) {
60 	case iro_Block:
61 	case iro_Bad:
62 	case iro_End:
63 	case iro_Anchor:
64 	case iro_NoMem:
65 		return 0;
66 	default:
67 		return 1;
68 	}
69 }
70 
71 int (be_is_live_in)(const be_lv_t *lv, const ir_node *block, const ir_node *irn)
72 {
73 	return _be_is_live_xxx(lv, block, irn, be_lv_state_in);
74 }
75 
76 int (be_is_live_out)(const be_lv_t *lv, const ir_node *block, const ir_node *irn)
77 {
78 	return _be_is_live_xxx(lv, block, irn, be_lv_state_out);
79 }
80 
81 int (be_is_live_end)(const be_lv_t *lv, const ir_node *block, const ir_node *irn)
82 {
83 	return _be_is_live_xxx(lv, block, irn, be_lv_state_end);
84 }
85 
_be_liveness_bsearch(be_lv_info_t * arr,unsigned idx)86 static inline unsigned _be_liveness_bsearch(be_lv_info_t *arr, unsigned idx)
87 {
88 	be_lv_info_t *payload = arr + 1;
89 
90 	unsigned n   = arr[0].head.n_members;
91 	unsigned res = 0;
92 	int lo       = 0;
93 	int hi       = n;
94 
95 	if (n == 0)
96 		return 0;
97 
98 	do {
99 		int md          = lo + ((hi - lo) >> 1);
100 		unsigned md_idx = payload[md].node.idx;
101 
102 		if (idx > md_idx)
103 			lo = md + 1;
104 		else if (idx < md_idx)
105 			hi = md;
106 		else {
107 			res = md;
108 			assert(payload[res].node.idx == idx);
109 			break;
110 		}
111 
112 		res = lo;
113 	} while (lo < hi);
114 
115 	return res;
116 }
117 
be_lv_get(const be_lv_t * li,const ir_node * bl,const ir_node * irn)118 be_lv_info_node_t *be_lv_get(const be_lv_t *li, const ir_node *bl,
119                              const ir_node *irn)
120 {
121 	be_lv_info_t *irn_live;
122 	be_lv_info_node_t *res = NULL;
123 
124 	stat_ev_tim_push();
125 	irn_live = ir_nodehashmap_get(be_lv_info_t, &li->map, bl);
126 	if (irn_live != NULL) {
127 		unsigned idx = get_irn_idx(irn);
128 
129 		/* Get the position of the index in the array. */
130 		int pos = _be_liveness_bsearch(irn_live, idx);
131 
132 		/* Get the record in question. 1 must be added, since the first record contains information about the array and must be skipped. */
133 		be_lv_info_node_t *rec = &irn_live[pos + 1].node;
134 
135 		/* Check, if the irn is in deed in the array. */
136 		if (rec->idx == idx)
137 			res = rec;
138 	}
139 	stat_ev_tim_pop("be_lv_get");
140 
141 	return res;
142 }
143 
be_lv_get_or_set(be_lv_t * li,ir_node * bl,ir_node * irn)144 static be_lv_info_node_t *be_lv_get_or_set(be_lv_t *li, ir_node *bl,
145                                            ir_node *irn)
146 {
147 	be_lv_info_t *irn_live = ir_nodehashmap_get(be_lv_info_t, &li->map, bl);
148 	if (irn_live == NULL) {
149 		irn_live = OALLOCNZ(&li->obst, be_lv_info_t, LV_STD_SIZE);
150 		irn_live[0].head.n_size = LV_STD_SIZE-1;
151 		ir_nodehashmap_insert(&li->map, bl, irn_live);
152 	}
153 
154 	unsigned idx = get_irn_idx(irn);
155 
156 	/* Get the position of the index in the array. */
157 	unsigned pos = _be_liveness_bsearch(irn_live, idx);
158 
159 	/* Get the record in question. 1 must be added, since the first record contains information about the array and must be skipped. */
160 	be_lv_info_node_t *res = &irn_live[pos + 1].node;
161 
162 	/* Check, if the irn is in deed in the array. */
163 	if (res->idx != idx) {
164 		be_lv_info_t *payload;
165 		unsigned n_members = irn_live[0].head.n_members;
166 		unsigned n_size    = irn_live[0].head.n_size;
167 		unsigned i;
168 
169 		if (n_members + 1 >= n_size) {
170 			/* double the array size. Remember that the first entry is
171 			 * metadata about the array and not a real array element */
172 			unsigned old_size_bytes  = (n_size + 1) * sizeof(irn_live[0]);
173 			unsigned new_size        = (2 * n_size) + 1;
174 			size_t   new_size_bytes  = new_size * sizeof(irn_live[0]);
175 			be_lv_info_t *nw = OALLOCN(&li->obst, be_lv_info_t, new_size);
176 			memcpy(nw, irn_live, old_size_bytes);
177 			memset(((char*) nw) + old_size_bytes, 0,
178 			       new_size_bytes - old_size_bytes);
179 			nw[0].head.n_size = new_size - 1;
180 			irn_live = nw;
181 			ir_nodehashmap_insert(&li->map, bl, nw);
182 		}
183 
184 		payload = &irn_live[1];
185 		for (i = n_members; i > pos; --i) {
186 			payload[i] = payload[i - 1];
187 		}
188 
189 		++irn_live[0].head.n_members;
190 
191 		res = &payload[pos].node;
192 		res->idx    = idx;
193 		res->flags  = 0;
194 	}
195 
196 	return res;
197 }
198 
199 /**
200  * Removes a node from the list of live variables of a block.
201  * @return 1 if the node was live at that block, 0 if not.
202  */
be_lv_remove(be_lv_t * li,const ir_node * bl,const ir_node * irn)203 static int be_lv_remove(be_lv_t *li, const ir_node *bl,
204                         const ir_node *irn)
205 {
206 	be_lv_info_t *irn_live = ir_nodehashmap_get(be_lv_info_t, &li->map, bl);
207 
208 	if (irn_live != NULL) {
209 		unsigned n   = irn_live[0].head.n_members;
210 		unsigned idx = get_irn_idx(irn);
211 		unsigned pos = _be_liveness_bsearch(irn_live, idx);
212 		be_lv_info_t *payload  = irn_live + 1;
213 		be_lv_info_node_t *res = &payload[pos].node;
214 
215 		/* The node is in deed in the block's array. Let's remove it. */
216 		if (res->idx == idx) {
217 			unsigned i;
218 
219 			for (i = pos + 1; i < n; ++i)
220 				payload[i - 1] = payload[i];
221 
222 			payload[n - 1].node.idx   = 0;
223 			payload[n - 1].node.flags = 0;
224 
225 			--irn_live[0].head.n_members;
226 			DBG((dbg, LEVEL_3, "\tdeleting %+F from %+F at pos %d\n", irn, bl, pos));
227 			return 1;
228 		}
229 	}
230 
231 	return 0;
232 }
233 
234 /**
235  * Mark a node as live-in in a block.
236  */
mark_live_in(be_lv_t * lv,ir_node * block,ir_node * irn)237 static inline void mark_live_in(be_lv_t *lv, ir_node *block, ir_node *irn)
238 {
239 	be_lv_info_node_t *n = be_lv_get_or_set(lv, block, irn);
240 	DBG((dbg, LEVEL_2, "marking %+F live in at %+F\n", irn, block));
241 	n->flags |= be_lv_state_in;
242 }
243 
244 /**
245  * Mark a node as live-out in a block.
246  */
mark_live_out(be_lv_t * lv,ir_node * block,ir_node * irn)247 static inline void mark_live_out(be_lv_t *lv, ir_node *block, ir_node *irn)
248 {
249 	be_lv_info_node_t *n = be_lv_get_or_set(lv, block, irn);
250 	DBG((dbg, LEVEL_2, "marking %+F live out at %+F\n", irn, block));
251 	n->flags |= be_lv_state_out | be_lv_state_end;
252 }
253 
254 /**
255  * Mark a node as live-end in a block.
256  */
mark_live_end(be_lv_t * lv,ir_node * block,ir_node * irn)257 static inline void mark_live_end(be_lv_t *lv, ir_node *block, ir_node *irn)
258 {
259 	be_lv_info_node_t *n = be_lv_get_or_set(lv, block, irn);
260 	DBG((dbg, LEVEL_2, "marking %+F live end at %+F\n", irn, block));
261 	n->flags |= be_lv_state_end;
262 }
263 
264 static struct {
265 	be_lv_t  *lv;         /**< The liveness object. */
266 	ir_node  *def;        /**< The node (value). */
267 	ir_node  *def_block;  /**< The block of def. */
268 	bitset_t *visited;    /**< A set were all visited blocks are recorded. */
269 } re;
270 
271 /**
272  * Mark a node (value) live out at a certain block. Do this also
273  * transitively, i.e. if the block is not the block of the value's
274  * definition, all predecessors are also marked live.
275  * @param block The block to mark the value live out of.
276  * @param is_true_out Is the node real out there or only live at the end
277  * of the block.
278  */
live_end_at_block(ir_node * block,int is_true_out)279 static void live_end_at_block(ir_node *block, int is_true_out)
280 {
281 	be_lv_t *lv  = re.lv;
282 	ir_node *def = re.def;
283 	bitset_t *visited;
284 
285 	mark_live_end(lv, block, def);
286 	if (is_true_out)
287 		mark_live_out(lv, block, def);
288 
289 	visited = re.visited;
290 	if (!bitset_is_set(visited, get_irn_idx(block))) {
291 		bitset_set(visited, get_irn_idx(block));
292 
293 		/*
294 		 * If this block is not the definition block, we have to go up
295 		 * further.
296 		 */
297 		if (re.def_block != block) {
298 			int i;
299 
300 			mark_live_in(lv, block, def);
301 
302 			for (i = get_Block_n_cfgpreds(block) - 1; i >= 0; --i)
303 				live_end_at_block(get_Block_cfgpred_block(block, i), 1);
304 		}
305 	}
306 }
307 
308 typedef struct lv_remove_walker_t {
309 	be_lv_t       *lv;
310 	const ir_node *irn;
311 } lv_remove_walker_t;
312 
313 
314 /**
315  * Liveness analysis for a value.
316  * Compute the set of all blocks a value is live in.
317  * @param irn     The node (value).
318  */
liveness_for_node(ir_node * irn)319 static void liveness_for_node(ir_node *irn)
320 {
321 	ir_node *def_block;
322 
323 	bitset_clear_all(re.visited);
324 	def_block = get_nodes_block(irn);
325 
326 	re.def       = irn;
327 	re.def_block = def_block;
328 
329 	/* Go over all uses of the value */
330 	foreach_out_edge(irn, edge) {
331 		ir_node *use = edge->src;
332 		ir_node *use_block;
333 
334 		DBG((dbg, LEVEL_4, "%+F: use at %+F, pos %d in %+F\n", irn, use, edge->pos, get_block(use)));
335 		assert(get_irn_n(use, edge->pos) == irn);
336 
337 		/*
338 		 * If the usage is no data node, skip this use, since it does not
339 		 * affect the liveness of the node.
340 		 */
341 		if (!is_liveness_node(use))
342 			continue;
343 
344 		/* Get the block where the usage is in. */
345 		use_block = get_nodes_block(use);
346 
347 		/*
348 		 * If the use is a phi function, determine the corresponding block
349 		 * through which the value reaches the phi function and mark the
350 		 * value as live out of that block.
351 		 */
352 		if (is_Phi(use)) {
353 			ir_node *pred_block = get_Block_cfgpred_block(use_block, edge->pos);
354 			live_end_at_block(pred_block, 0);
355 		}
356 
357 		/*
358 		 * Else, the value is live in at this block. Mark it and call live
359 		 * out on the predecessors.
360 		 */
361 		else if (def_block != use_block) {
362 			int i;
363 
364 			mark_live_in(re.lv, use_block, irn);
365 
366 			for (i = get_Block_n_cfgpreds(use_block) - 1; i >= 0; --i) {
367 				ir_node *pred_block = get_Block_cfgpred_block(use_block, i);
368 				live_end_at_block(pred_block, 1);
369 			}
370 		}
371 	}
372 }
373 
lv_remove_irn_walker(ir_node * bl,void * data)374 static void lv_remove_irn_walker(ir_node *bl, void *data)
375 {
376 	lv_remove_walker_t *w = (lv_remove_walker_t*)data;
377 	be_lv_remove(w->lv, bl, w->irn);
378 }
379 
380 /**
381  * Walker, collect all nodes for which we want calculate liveness info
382  * on an obstack.
383  */
collect_liveness_nodes(ir_node * irn,void * data)384 static void collect_liveness_nodes(ir_node *irn, void *data)
385 {
386 	ir_node **nodes = (ir_node**)data;
387 	if (is_liveness_node(irn))
388 		nodes[get_irn_idx(irn)] = irn;
389 }
390 
be_liveness_compute_sets(be_lv_t * lv)391 void be_liveness_compute_sets(be_lv_t *lv)
392 {
393 	ir_node **nodes;
394 	int       i;
395 	int       n;
396 
397 	if (lv->sets_valid)
398 		return;
399 
400 	be_timer_push(T_LIVE);
401 	ir_nodehashmap_init(&lv->map);
402 	obstack_init(&lv->obst);
403 
404 	n = get_irg_last_idx(lv->irg);
405 	nodes = NEW_ARR_F(ir_node *, n);
406 	memset(nodes, 0, sizeof(nodes[0]) * n);
407 
408 	/* inserting the variables sorted by their ID is probably
409 	 * more efficient since the binary sorted set insertion
410 	 * will not need to move around the data. */
411 	irg_walk_graph(lv->irg, NULL, collect_liveness_nodes, nodes);
412 
413 	re.lv      = lv;
414 	re.visited = bitset_malloc(n);
415 
416 	for (i = 0; i < n; ++i) {
417 		if (nodes[i] != NULL)
418 			liveness_for_node(nodes[i]);
419 	}
420 
421 	DEL_ARR_F(nodes);
422 	free(re.visited);
423 	register_hook(hook_node_info, &lv->hook_info);
424 
425 	be_timer_pop(T_LIVE);
426 
427 	lv->sets_valid = true;
428 }
429 
be_liveness_compute_chk(be_lv_t * lv)430 void be_liveness_compute_chk(be_lv_t *lv)
431 {
432 	if (lv->lvc != NULL)
433 		return;
434 	lv->lvc = lv_chk_new(lv->irg);
435 }
436 
be_liveness_invalidate_sets(be_lv_t * lv)437 void be_liveness_invalidate_sets(be_lv_t *lv)
438 {
439 	if (!lv->sets_valid)
440 		return;
441 	unregister_hook(hook_node_info, &lv->hook_info);
442 	obstack_free(&lv->obst, NULL);
443 	ir_nodehashmap_destroy(&lv->map);
444 	lv->sets_valid = false;
445 }
446 
be_liveness_invalidate_chk(be_lv_t * lv)447 void be_liveness_invalidate_chk(be_lv_t *lv)
448 {
449 	be_liveness_invalidate_sets(lv);
450 
451 	if (lv->lvc == NULL)
452 		return;
453 	lv_chk_free(lv->lvc);
454 	lv->lvc = NULL;
455 }
456 
be_liveness_new(ir_graph * irg)457 be_lv_t *be_liveness_new(ir_graph *irg)
458 {
459 	be_lv_t *lv = XMALLOCZ(be_lv_t);
460 
461 	lv->irg = irg;
462 	lv->hook_info.context = lv;
463 	lv->hook_info.hook._hook_node_info = be_dump_liveness_block;
464 
465 	return lv;
466 }
467 
be_liveness_free(be_lv_t * lv)468 void be_liveness_free(be_lv_t *lv)
469 {
470 	be_liveness_invalidate_sets(lv);
471 	be_liveness_invalidate_chk(lv);
472 
473 	xfree(lv);
474 }
475 
be_liveness_remove(be_lv_t * lv,const ir_node * irn)476 void be_liveness_remove(be_lv_t *lv, const ir_node *irn)
477 {
478 	if (lv->sets_valid) {
479 		lv_remove_walker_t w;
480 
481 		/*
482 		 * Removes a single irn from the liveness information.
483 		 * Since an irn can only be live at blocks dominated by the block of its
484 		 * definition, we only have to process that dominance subtree.
485 		 */
486 		w.lv  = lv;
487 		w.irn = irn;
488 		dom_tree_walk(get_nodes_block(irn), lv_remove_irn_walker, NULL, &w);
489 	}
490 }
491 
be_liveness_introduce(be_lv_t * lv,ir_node * irn)492 void be_liveness_introduce(be_lv_t *lv, ir_node *irn)
493 {
494 	/* Don't compute liveness information for non-data nodes. */
495 	if (lv->sets_valid && is_liveness_node(irn)) {
496 		re.lv      = lv;
497 		re.visited = bitset_malloc(get_irg_last_idx(lv->irg));
498 		liveness_for_node(irn);
499 		bitset_free(re.visited);
500 	}
501 }
502 
be_liveness_update(be_lv_t * lv,ir_node * irn)503 void be_liveness_update(be_lv_t *lv, ir_node *irn)
504 {
505 	be_liveness_remove(lv, irn);
506 	be_liveness_introduce(lv, irn);
507 }
508 
be_liveness_transfer(const arch_register_class_t * cls,ir_node * node,ir_nodeset_t * nodeset)509 void be_liveness_transfer(const arch_register_class_t *cls,
510                           ir_node *node, ir_nodeset_t *nodeset)
511 {
512 	/* You should better break out of your loop when hitting the first phi
513 	 * function. */
514 	assert(!is_Phi(node) && "liveness_transfer produces invalid results for phi nodes");
515 
516 	be_foreach_definition(node, cls, value,
517 		ir_nodeset_remove(nodeset, value);
518 	);
519 
520 	int arity = get_irn_arity(node);
521 	for (int i = 0; i < arity; ++i) {
522 		ir_node *op = get_irn_n(node, i);
523 		if (!arch_irn_consider_in_reg_alloc(cls, op))
524 			continue;
525 		ir_nodeset_insert(nodeset, op);
526 	}
527 }
528 
529 
530 
be_liveness_end_of_block(const be_lv_t * lv,const arch_register_class_t * cls,const ir_node * block,ir_nodeset_t * live)531 void be_liveness_end_of_block(const be_lv_t *lv,
532                               const arch_register_class_t *cls,
533                               const ir_node *block, ir_nodeset_t *live)
534 {
535 	assert(lv->sets_valid && "live sets must be computed");
536 	be_lv_foreach(lv, block, be_lv_state_end, node) {
537 		if (!arch_irn_consider_in_reg_alloc(cls, node))
538 			continue;
539 
540 		ir_nodeset_insert(live, node);
541 	}
542 }
543 
544 
545 
be_liveness_nodes_live_at(const be_lv_t * lv,const arch_register_class_t * cls,const ir_node * pos,ir_nodeset_t * live)546 void be_liveness_nodes_live_at(const be_lv_t *lv,
547                                const arch_register_class_t *cls,
548                                const ir_node *pos, ir_nodeset_t *live)
549 {
550 	const ir_node *bl = is_Block(pos) ? pos : get_nodes_block(pos);
551 
552 	be_liveness_end_of_block(lv, cls, bl, live);
553 	sched_foreach_reverse(bl, irn) {
554 		/*
555 		 * If we encounter the node we want to insert the Perm after,
556 		 * exit immediately, so that this node is still live
557 		 */
558 		if (irn == pos)
559 			return;
560 
561 		be_liveness_transfer(cls, irn, live);
562 	}
563 }
564 
collect_node(ir_node * irn,void * data)565 static void collect_node(ir_node *irn, void *data)
566 {
567 	struct obstack *obst = (struct obstack*)data;
568 	obstack_ptr_grow(obst, irn);
569 }
570 
be_live_chk_compare(be_lv_t * lv,lv_chk_t * lvc)571 static void be_live_chk_compare(be_lv_t *lv, lv_chk_t *lvc)
572 {
573 	ir_graph *irg    = lv->irg;
574 
575 	struct obstack obst;
576 	ir_node **nodes;
577 	ir_node **blocks;
578 	int i, j;
579 
580 	obstack_init(&obst);
581 
582 	irg_block_walk_graph(irg, collect_node, NULL, &obst);
583 	obstack_ptr_grow(&obst, NULL);
584 	blocks = (ir_node**)obstack_finish(&obst);
585 
586 	irg_walk_graph(irg, collect_node, NULL, &obst);
587 	obstack_ptr_grow(&obst, NULL);
588 	nodes = (ir_node**)obstack_finish(&obst);
589 
590 	stat_ev_ctx_push("be_lv_chk_compare");
591 	for (j = 0; nodes[j]; ++j) {
592 		ir_node *irn = nodes[j];
593 		if (is_Block(irn))
594 			continue;
595 
596 		for (i = 0; blocks[i]; ++i) {
597 			ir_node *bl = blocks[i];
598 			int lvr_in  = be_is_live_in (lv, bl, irn);
599 			int lvr_out = be_is_live_out(lv, bl, irn);
600 			int lvr_end = be_is_live_end(lv, bl, irn);
601 
602 			int lvc_in  = lv_chk_bl_in (lvc, bl, irn);
603 			int lvc_out = lv_chk_bl_out(lvc, bl, irn);
604 			int lvc_end = lv_chk_bl_end(lvc, bl, irn);
605 
606 			if (lvr_in - lvc_in != 0)
607 				ir_fprintf(stderr, "live in  info for %+F at %+F differs: nml: %d, chk: %d\n", irn, bl, lvr_in, lvc_in);
608 
609 			if (lvr_end - lvc_end != 0)
610 				ir_fprintf(stderr, "live end info for %+F at %+F differs: nml: %d, chk: %d\n", irn, bl, lvr_end, lvc_end);
611 
612 			if (lvr_out - lvc_out != 0)
613 				ir_fprintf(stderr, "live out info for %+F at %+F differs: nml: %d, chk: %d\n", irn, bl, lvr_out, lvc_out);
614 		}
615 	}
616 	stat_ev_ctx_pop("be_lv_chk_compare");
617 
618 	obstack_free(&obst, NULL);
619 }
620 
BE_REGISTER_MODULE_CONSTRUCTOR(be_init_live)621 BE_REGISTER_MODULE_CONSTRUCTOR(be_init_live)
622 void be_init_live(void)
623 {
624 	(void)be_live_chk_compare;
625 	FIRM_DBG_REGISTER(dbg, "firm.be.liveness");
626 }
627