unified mein file comments
[libfirm] / ir / be / belive.c
1 /*
2  * Copyright (C) 1995-2007 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  * @version     $Id$
26  */
27 #ifdef HAVE_CONFIG_H
28 #include "config.h"
29 #endif
30
31 #include "impl.h"
32 #include "iredges_t.h"
33 #include "irgwalk.h"
34 #include "irprintf_t.h"
35 #include "irbitset.h"
36 #include "irdump_t.h"
37
38 #include "beutil.h"
39 #include "belive_t.h"
40 #include "besched_t.h"
41 #include "bemodule.h"
42
43 DEBUG_ONLY(static firm_dbg_module_t *dbg = NULL;)
44
45 #define LV_STD_SIZE             128
46 #define LV_USE_BINARY_SEARCH
47 #undef  LV_INTESIVE_CHECKS
48
49 static INLINE int is_liveness_node(const ir_node *irn)
50 {
51         switch(get_irn_opcode(irn)) {
52         case iro_Block:
53         case iro_Bad:
54         case iro_End:
55                 return 0;
56         default:;
57         }
58
59         return 1;
60 }
61
62 int (be_lv_next_irn)(const struct _be_lv_t *lv, const ir_node *bl, unsigned flags, int i)
63 {
64         return _be_lv_next_irn(lv, bl, flags, i);
65 }
66
67 const ir_node * (be_lv_get_irn)(const struct _be_lv_t *lv, const ir_node *bl, int i)
68 {
69         return _be_lv_get_irn(lv, bl, i);
70 }
71
72 int (be_is_live_in)(const be_lv_t *lv, const ir_node *block, const ir_node *irn)
73 {
74         return _be_is_live_xxx(lv, block, irn, be_lv_state_in);
75 }
76
77 int (be_is_live_out)(const be_lv_t *lv, const ir_node *block, const ir_node *irn)
78 {
79         return _be_is_live_xxx(lv, block, irn, be_lv_state_out);
80 }
81
82 int (be_is_live_end)(const be_lv_t *lv, const ir_node *block, const ir_node *irn)
83 {
84         return _be_is_live_xxx(lv, block, irn, be_lv_state_end);
85 }
86
87
88 #ifdef LV_USE_BINARY_SEARCH
89 static INLINE unsigned _be_liveness_bsearch(struct _be_lv_info_t *arr, unsigned idx)
90 {
91         struct _be_lv_info_t *payload = arr + 1;
92
93         unsigned n   = arr[0].u.head.n_members;
94         unsigned res = 0;
95         int lo       = 0;
96         int hi       = n;
97
98         if(n == 0)
99                 return 0;
100
101 #if 0
102         if(idx < payload[0].u.node.idx)
103                 return 0;
104
105         if(idx > payload[n - 1].u.node.idx)
106                 return n - 1;
107 #endif
108
109         /* start a binary search for the requested node. */
110         while(lo < hi) {
111                 int md          = lo + ((hi - lo) >> 1);
112                 unsigned md_idx = payload[md].u.node.idx;
113
114                 if(idx > md_idx)
115                         lo = md + 1;
116                 else if(idx < md_idx)
117                         hi = md;
118                 else {
119                         res = md;
120                         assert(payload[res].u.node.idx == idx);
121                         break;
122                 }
123
124                 res = lo;
125         }
126
127 #ifdef LV_INTESIVE_CHECKS
128         {
129                 unsigned i;
130                 for(i = res; i < n; ++i)
131                         assert(payload[i].u.node.idx >= idx);
132
133                 for(i = 0; i < res; ++i)
134                         assert(payload[i].u.node.idx < idx);
135         }
136 #endif
137
138         return res;
139 }
140
141 #else
142
143 /**
144  * This function searches linearly for the node in the array.
145  */
146 static INLINE unsigned _be_liveness_bsearch(struct _be_lv_info_t *arr, unsigned idx) {
147         unsigned n  = arr[0].u.head.n_members;
148         unsigned i;
149
150         for(i = 0; i < n; ++i) {
151                 if(arr[i + 1].u.node.idx == idx)
152                         return i;
153         }
154
155         return i;
156 }
157 #endif
158
159 struct _be_lv_info_node_t *be_lv_get(const struct _be_lv_t *li, const ir_node *bl, const ir_node *irn)
160 {
161         struct _be_lv_info_t *irn_live = phase_get_irn_data(&li->ph, bl);
162
163         if(irn_live) {
164                 unsigned idx = get_irn_idx(irn);
165
166                 /* Get the position of the index in the array. */
167                 int pos = _be_liveness_bsearch(irn_live, idx);
168
169                 /* Get the record in question. 1 must be added, since the first record contains information about the array and must be skipped. */
170                 struct _be_lv_info_node_t *res = &irn_live[pos + 1].u.node;
171
172                 /* Check, if the irn is in deed in the array. */
173                 if(res->idx == idx)
174                         return res;
175         }
176
177         return NULL;
178 }
179
180 static struct _be_lv_info_node_t *be_lv_get_or_set(struct _be_lv_t *li, ir_node *bl, ir_node *irn)
181 {
182         struct _be_lv_info_t *irn_live = phase_get_or_set_irn_data(&li->ph, bl);
183
184         unsigned idx = get_irn_idx(irn);
185
186         /* Get the position of the index in the array. */
187         unsigned pos = _be_liveness_bsearch(irn_live, idx);
188
189         /* Get the record in question. 1 must be added, since the first record contains information about the array and must be skipped. */
190         struct _be_lv_info_node_t *res = &irn_live[pos + 1].u.node;
191
192         /* Check, if the irn is in deed in the array. */
193         if(res->idx != idx) {
194                 struct _be_lv_info_t *payload;
195                 unsigned n_members = irn_live[0].u.head.n_members;
196                 unsigned n_size    = irn_live[0].u.head.n_size;
197                 unsigned i;
198
199                 if(n_members == n_size - 1) {
200                         unsigned new_size = 2 * n_size * sizeof(irn_live[0]);
201                         struct _be_lv_info_t *nw = phase_alloc(&li->ph, new_size);
202                         memcpy(nw, irn_live, new_size);
203                         nw[0].u.head.n_size = new_size;
204                         irn_live = nw;
205                         phase_set_irn_data(&li->ph, irn, nw);
206                 }
207
208                 payload = &irn_live[1];
209                 for(i = n_members; i > pos; --i) {
210                         payload[i] = payload[i - 1];
211                 }
212
213                 ++irn_live[0].u.head.n_members;
214
215                 res = &payload[pos].u.node;
216                 res->idx    = idx;
217                 res->flags  = 0;
218         }
219
220 #ifdef LV_INTESIVE_CHECKS
221         {
222                 unsigned i;
223                 unsigned n = irn_live[0].u.head.n_members;
224                 unsigned last = 0;
225                 struct _be_lv_info_t *payload = &irn_live[1];
226
227                 for(i = 0; i < n; ++i) {
228                         assert(payload[i].u.node.idx >= last);
229                         last = payload[i].u.node.idx;
230                 }
231         }
232 #endif
233
234         return res;
235 }
236
237 /**
238  * Removes a node from the list of live variables of a block.
239  * @return 1 if the node was live at that block, 0 if not.
240  */
241 static int be_lv_remove(struct _be_lv_t *li, ir_node *bl, ir_node *irn)
242 {
243         struct _be_lv_info_t *irn_live = phase_get_irn_data(&li->ph, bl);
244
245         if(irn_live) {
246                 unsigned n   = irn_live[0].u.head.n_members;
247                 unsigned idx = get_irn_idx(irn);
248                 unsigned pos = _be_liveness_bsearch(irn_live, idx);
249                 struct _be_lv_info_t *payload  = irn_live + 1;
250                 struct _be_lv_info_node_t *res = &payload[pos].u.node;
251
252                 /* The node is in deed in the block's array. Let's remove it. */
253                 if(res->idx == idx) {
254                         unsigned i;
255
256                         for(i = pos + 1; i < n; ++i)
257                                 payload[i - 1] = payload[i];
258
259                         payload[n - 1].u.node.idx   = 0;
260                         payload[n - 1].u.node.flags = 0;
261
262                         --irn_live[0].u.head.n_members;
263                         DBG((dbg, LEVEL_3, "\tdeleting %+F from %+F at pos %d\n", irn, bl, pos));
264                         return 1;
265                 }
266         }
267
268         return 0;
269 }
270
271 static void register_node(be_lv_t *lv, const ir_node *irn)
272 {
273         unsigned idx = get_irn_idx(irn);
274         if(idx >= bitset_size(lv->nodes)) {
275                 bitset_t *nw = bitset_malloc(2 * idx);
276                 bitset_copy(nw, lv->nodes);
277                 bitset_free(lv->nodes);
278                 lv->nodes = nw;
279         }
280
281         bitset_set(lv->nodes, idx);
282 }
283
284 /**
285  * Mark a node as live-in in a block.
286  */
287 static INLINE void mark_live_in(be_lv_t *lv, ir_node *block, ir_node *irn)
288 {
289         struct _be_lv_info_node_t *n = be_lv_get_or_set(lv, block, irn);
290         DBG((dbg, LEVEL_2, "marking %+F live in at %+F\n", irn, block));
291         n->flags |= be_lv_state_in;
292         register_node(lv, irn);
293 }
294
295 /**
296  * Mark a node as live-out in a block.
297  */
298 static INLINE void mark_live_out(be_lv_t *lv, ir_node *block, ir_node *irn)
299 {
300         struct _be_lv_info_node_t *n = be_lv_get_or_set(lv, block, irn);
301         DBG((dbg, LEVEL_2, "marking %+F live out at %+F\n", irn, block));
302         n->flags |= be_lv_state_out | be_lv_state_end;
303         register_node(lv, irn);
304 }
305
306 /**
307  * Mark a node as live-end in a block.
308  */
309 static INLINE void mark_live_end(be_lv_t *lv, ir_node *block, ir_node *irn)
310 {
311         struct _be_lv_info_node_t *n = be_lv_get_or_set(lv, block, irn);
312         DBG((dbg, LEVEL_2, "marking %+F live end at %+F\n", irn, block));
313         n->flags |= be_lv_state_end;
314         register_node(lv, irn);
315 }
316
317 /**
318  * Mark a node (value) live out at a certain block. Do this also
319  * transitively, i.e. if the block is not the block of the value's
320  * definition, all predecessors are also marked live.
321  * @param def The node (value).
322  * @param block The block to mark the value live out of.
323  * @param visited A set were all visited blocks are recorded.
324  * @param is_true_out Is the node real out there or only live at the end
325  * of the block.
326  */
327 static void live_end_at_block(be_lv_t *lv, ir_node *def, ir_node *block, bitset_t *visited, int is_true_out)
328 {
329         mark_live_end(lv, block, def);
330         if(is_true_out)
331                 mark_live_out(lv, block, def);
332
333         if(!bitset_contains_irn(visited, block)) {
334                 bitset_add_irn(visited, block);
335
336                 /*
337                 * If this block is not the definition block, we have to go up
338                 * further.
339                 */
340                 if(get_nodes_block(def) != block) {
341                         int i, n;
342
343                         mark_live_in(lv, block, def);
344
345                         for(i = 0, n = get_Block_n_cfgpreds(block); i < n; ++i)
346                                 live_end_at_block(lv, def, get_Block_cfgpred_block(block, i), visited, 1);
347                 }
348
349         }
350 }
351
352 struct _lv_walker_t {
353         be_lv_t *lv;
354         void *data;
355 };
356
357 /**
358  * Liveness analysis for a value.
359  * This functions is meant to be called by a firm walker, to compute the
360  * set of all blocks a value is live in.
361  * @param irn The node (value).
362  * @param env Ignored.
363  */
364 static void liveness_for_node(ir_node *irn, void *data)
365 {
366         struct _lv_walker_t *walker = data;
367         be_lv_t *lv       = walker->lv;
368         bitset_t *visited = walker->data;
369         const ir_edge_t *edge;
370         ir_node *def_block;
371
372         /* Don't compute liveness information for non-data nodes. */
373         if(!is_liveness_node(irn))
374                 return;
375
376         bitset_clear_all(visited);
377         def_block = get_nodes_block(irn);
378
379         /* Go over all uses of the value */
380         foreach_out_edge(irn, edge) {
381                 ir_node *use = edge->src;
382                 ir_node *use_block;
383
384                 /*
385                  * If the usage is no data node, skip this use, since it does not
386                  * affect the liveness of the node.
387                  */
388                 if(!is_liveness_node(use))
389                         continue;
390
391                 /* Get the block where the usage is in. */
392                 use_block = get_nodes_block(use);
393
394                 /*
395                  * If the use is a phi function, determine the corresponding block
396                  * through which the value reaches the phi function and mark the
397                  * value as live out of that block.
398                  */
399                 if(is_Phi(use)) {
400                         ir_node *pred_block = get_Block_cfgpred_block(use_block, edge->pos);
401                         live_end_at_block(lv, irn, pred_block, visited, 0);
402                 }
403
404                 /*
405                  * Else, the value is live in at this block. Mark it and call live
406                  * out on the predecessors.
407                  */
408                 else if(def_block != use_block) {
409                         int i, n;
410
411                         mark_live_in(lv, use_block, irn);
412
413                         for(i = 0, n = get_Block_n_cfgpreds(use_block); i < n; ++i) {
414                                 ir_node *pred_block = get_Block_cfgpred_block(use_block, i);
415                                 live_end_at_block(lv, irn, pred_block, visited, 1);
416                         }
417                 }
418         }
419 }
420
421 static void lv_remove_irn_walker(ir_node *bl, void *data)
422 {
423         struct _lv_walker_t *w = data;
424         be_lv_t *lv  = w->lv;
425         ir_node *irn = w->data;
426         be_lv_remove(lv, bl, irn);
427 }
428
429 static const char *lv_flags_to_str(unsigned flags)
430 {
431         static const char *states[] = {
432                 "---",
433                 "i--",
434                 "-e-",
435                 "ie-",
436                 "--o",
437                 "i-o",
438                 "-eo",
439                 "ieo"
440         };
441
442         return states[flags & 7];
443 }
444
445 static void lv_dump_block(void *context, FILE *f, const ir_node *bl)
446 {
447         if(is_Block(bl)) {
448                 be_lv_t *lv = context;
449                 struct _be_lv_info_t *info = phase_get_irn_data(&lv->ph, bl);
450
451                 fprintf(f, "liveness:\n");
452                 if(info) {
453                         unsigned n = info[0].u.head.n_members;
454                         unsigned i;
455
456                         for(i = 0; i < n; ++i) {
457                                 struct _be_lv_info_node_t *n = &info[i+1].u.node;
458                                 ir_fprintf(f, "%s %+F\n", lv_flags_to_str(n->flags), get_idx_irn(lv->irg, n->idx));
459                         }
460                 }
461         }
462 }
463
464 static void *lv_phase_data_init(ir_phase *phase, ir_node *irn, void *old)
465 {
466         struct _be_lv_info_t *info = phase_alloc(phase, LV_STD_SIZE * sizeof(info[0]));
467         memset(info, 0, LV_STD_SIZE * sizeof(info[0]));
468         info[0].u.head.n_size = LV_STD_SIZE - 1;
469         return info;
470 }
471
472 static void compute_liveness(be_lv_t *lv)
473 {
474         struct _lv_walker_t w;
475         w.lv   = lv;
476         w.data = bitset_malloc(get_irg_last_idx(lv->irg));
477         irg_walk_graph(lv->irg, liveness_for_node, NULL, &w);
478         bitset_free(w.data);
479 }
480
481 /* Compute the inter block liveness for a graph. */
482 be_lv_t *be_liveness(ir_graph *irg)
483 {
484         be_lv_t *lv = xmalloc(sizeof(lv[0]));
485
486         memset(lv, 0, sizeof(lv[0]));
487         lv->irg = irg;
488         lv->nodes = bitset_malloc(2 * get_irg_last_idx(irg));
489         lv->hook_info.context = lv;
490         lv->hook_info.hook._hook_node_info = lv_dump_block;
491         register_hook(hook_node_info, &lv->hook_info);
492         phase_init(&lv->ph, "liveness", irg, PHASE_DEFAULT_GROWTH, lv_phase_data_init, NULL);
493         compute_liveness(lv);
494
495         return lv;
496 }
497
498 void be_liveness_recompute(be_lv_t *lv)
499 {
500         unsigned last_idx = get_irg_last_idx(lv->irg);
501         if(last_idx >= bitset_size(lv->nodes)) {
502                 bitset_free(lv->nodes);
503                 lv->nodes = bitset_malloc(last_idx * 2);
504         }
505
506         else
507                 bitset_clear_all(lv->nodes);
508
509         phase_free(&lv->ph);
510         phase_init(&lv->ph, "liveness", lv->irg, PHASE_DEFAULT_GROWTH, lv_phase_data_init, NULL);
511         compute_liveness(lv);
512 }
513
514
515 void be_liveness_free(be_lv_t *lv)
516 {
517         unregister_hook(hook_node_info, &lv->hook_info);
518         phase_free(&lv->ph);
519         bitset_free(lv->nodes);
520         free(lv);
521 }
522
523 void be_liveness_remove(be_lv_t *lv, ir_node *irn)
524 {
525         unsigned idx = get_irn_idx(irn);
526         struct _lv_walker_t w;
527
528         /*
529          * Removes a single irn from the liveness information.
530          * Since an irn can only be live at blocks dominated by the block of its
531          * definition, we only have to process that dominance subtree.
532          */
533         w.lv   = lv;
534         w.data = irn;
535         dom_tree_walk(get_nodes_block(irn), lv_remove_irn_walker, NULL, &w);
536         if(idx <= bitset_size(lv->nodes))
537                 bitset_clear(lv->nodes, idx);
538 }
539
540 void be_liveness_introduce(be_lv_t *lv, ir_node *irn)
541 {
542         struct _lv_walker_t w;
543         w.lv   = lv;
544         w.data = bitset_malloc(get_irg_last_idx(lv->irg));
545         liveness_for_node(irn, &w);
546         bitset_free(w.data);
547 }
548
549 void be_liveness_update(be_lv_t *lv, ir_node *irn)
550 {
551         be_liveness_remove(lv, irn);
552         be_liveness_introduce(lv, irn);
553 }
554
555 static void lv_add_missing_walker(ir_node *irn, void *data)
556 {
557         struct _lv_walker_t *w = data;
558         if(!is_Block(irn) && !bitset_contains_irn(w->lv->nodes, irn)) {
559                 liveness_for_node(irn, w);
560         }
561 }
562
563 void be_liveness_add_missing(be_lv_t *lv)
564 {
565         struct _lv_walker_t w;
566         w.lv   = lv;
567         w.data = bitset_malloc(get_irg_last_idx(lv->irg));
568         irg_walk_graph(lv->irg, lv_add_missing_walker, NULL, &w);
569         bitset_free(w.data);
570 }
571
572 static void lv_check_walker(ir_node *bl, void *data)
573 {
574         struct _lv_walker_t *w = data;
575         be_lv_t *lv    = w->lv;
576         be_lv_t *fresh = w->data;
577
578         struct _be_lv_info_t *curr = phase_get_irn_data(&lv->ph, bl);
579         struct _be_lv_info_t *fr   = phase_get_irn_data(&fresh->ph, bl);
580
581         if(!fr && curr && curr[0].u.head.n_members > 0) {
582                 unsigned i;
583
584                 ir_fprintf(stderr, "%+F liveness should be empty but current liveness contains:\n", bl);
585                 for(i = 0; i < curr[0].u.head.n_members; ++i) {
586                         ir_fprintf(stderr, "\t%+F\n", get_idx_irn(lv->irg, curr[1 + i].u.node.idx));
587                 }
588         }
589
590         else if(curr) {
591                 unsigned n_curr  = curr[0].u.head.n_members;
592                 unsigned n_fresh = fr[0].u.head.n_members;
593
594                 unsigned i;
595
596                 if(n_curr != n_fresh) {
597                         ir_fprintf(stderr, "%+F: liveness set sizes differ. curr %d, correct %d\n", bl, n_curr, n_fresh);
598
599                         ir_fprintf(stderr, "current:\n");
600                         for(i = 0; i < n_curr; ++i) {
601                                 struct _be_lv_info_node_t *n = &curr[1 + i].u.node;
602                                 ir_fprintf(stderr, "%+F %u %+F %s\n", bl, i, get_idx_irn(lv->irg, n->idx), lv_flags_to_str(n->flags));
603                         }
604
605                         ir_fprintf(stderr, "correct:\n");
606                         for(i = 0; i < n_fresh; ++i) {
607                                 struct _be_lv_info_node_t *n = &fr[1 + i].u.node;
608                                 ir_fprintf(stderr, "%+F %u %+F %s\n", bl, i, get_idx_irn(lv->irg, n->idx), lv_flags_to_str(n->flags));
609                         }
610                 }
611         }
612 }
613
614 void be_liveness_check(be_lv_t *lv)
615 {
616         struct _lv_walker_t w;
617         be_lv_t *fresh = be_liveness(lv->irg);
618
619         w.lv   = lv;
620         w.data = fresh;
621         irg_block_walk_graph(lv->irg, lv_check_walker, NULL, &w);
622         be_liveness_free(fresh);
623 }
624
625
626 static void lv_dump_block_walker(ir_node *irn, void *data)
627 {
628         struct _lv_walker_t *w = data;
629         if(is_Block(irn))
630                 lv_dump_block(w->lv, w->data, irn);
631 }
632
633
634 /* Dump the liveness information for a graph. */
635 void be_liveness_dump(const be_lv_t *lv, FILE *f)
636 {
637         struct _lv_walker_t w;
638
639         w.lv   = (be_lv_t *) lv;
640         w.data = f;
641         irg_block_walk_graph(lv->irg, lv_dump_block_walker, NULL, &w);
642 }
643
644 /* Dump the liveness information for a graph. */
645 void be_liveness_dumpto(const be_lv_t *lv, const char *cls_name)
646 {
647         FILE *f;
648         char buf[128];
649         ir_snprintf(buf, sizeof(buf), "%F_%s-live.txt", lv->irg, cls_name);
650         if((f = fopen(buf, "wt")) != NULL) {
651                 be_liveness_dump(lv, f);
652                 fclose(f);
653         }
654 }
655
656 /**
657  * Walker: checks the every predecessors of a node dominate
658  * the note.
659  */
660 static void dom_check(ir_node *irn, void *data)
661 {
662         int *problem_found = data;
663
664         if(!is_Block(irn) && irn != get_irg_end(get_irn_irg(irn))) {
665                 int i, n;
666                 ir_node *bl = get_nodes_block(irn);
667
668                 for(i = 0, n = get_irn_arity(irn); i < n; ++i) {
669                         ir_node *op     = get_irn_n(irn, i);
670                         ir_node *def_bl = get_nodes_block(op);
671                         ir_node *use_bl = bl;
672
673                         if(is_Phi(irn))
674                                 use_bl = get_Block_cfgpred_block(bl, i);
675
676                         if(get_irn_opcode(use_bl) != iro_Bad
677                              && get_irn_opcode(def_bl) != iro_Bad
678                              && !block_dominates(def_bl, use_bl)) {
679                                 ir_fprintf(stderr, "Verify warning: %+F in %+F must dominate %+F for user %+F (%s)\n", op, def_bl, use_bl, irn, get_irg_dump_name(get_irn_irg(op)));
680                                 *problem_found = 1;
681                         }
682                 }
683         }
684 }
685
686 /* Check, if the SSA dominance property is fulfilled. */
687 int be_check_dominance(ir_graph *irg)
688 {
689         int problem_found = 0;
690
691         assure_doms(irg);
692         irg_walk_graph(irg, dom_check, NULL, &problem_found);
693
694         return !problem_found;
695 }
696
697 pset *be_liveness_transfer(const arch_env_t *arch_env, const arch_register_class_t *cls, ir_node *irn, pset *live)
698 {
699         int i, n;
700
701         /* You should better break out of your loop when hitting the first phi function. */
702         assert(!is_Phi(irn) && "liveness_transfer produces invalid results for phi nodes");
703
704         if(arch_irn_consider_in_reg_alloc(arch_env, cls, irn)) {
705                 ir_node *del = pset_remove_ptr(live, irn);
706                 (void) del;
707                 assert(irn == del);
708         }
709
710         for(i = 0, n = get_irn_arity(irn); i < n; ++i) {
711                 ir_node *op = get_irn_n(irn, i);
712
713                 if(arch_irn_consider_in_reg_alloc(arch_env, cls, op))
714                         pset_insert_ptr(live, op);
715         }
716
717         return live;
718 }
719
720 pset *be_liveness_end_of_block(const be_lv_t *lv, const arch_env_t *arch_env, const arch_register_class_t *cls, const ir_node *bl, pset *live)
721 {
722         int i;
723         be_lv_foreach(lv, bl, be_lv_state_end, i) {
724                 ir_node *irn = be_lv_get_irn(lv, bl, i);
725                 if(arch_irn_consider_in_reg_alloc(arch_env, cls, irn))
726                         pset_insert_ptr(live, irn);
727         }
728
729         return live;
730 }
731
732 pset *be_liveness_nodes_live_at(const be_lv_t *lv, const arch_env_t *arch_env, const arch_register_class_t *cls, const ir_node *pos, pset *live)
733 {
734         const ir_node *bl = is_Block(pos) ? pos : get_nodes_block(pos);
735         ir_node *irn;
736
737         be_liveness_end_of_block(lv, arch_env, cls, bl, live);
738         sched_foreach_reverse(bl, irn) {
739                 /*
740                  * If we encounter the node we want to insert the Perm after,
741                  * exit immediately, so that this node is still live
742                  */
743                 if(irn == pos)
744                         return live;
745
746                 be_liveness_transfer(arch_env, cls, irn, live);
747         }
748
749         return live;
750 }
751
752 pset *be_liveness_nodes_live_at_input(const be_lv_t *lv, const arch_env_t *arch_env, const arch_register_class_t *cls, const ir_node *pos, pset *live)
753 {
754         const ir_node *bl = is_Block(pos) ? pos : get_nodes_block(pos);
755         ir_node *irn;
756
757         be_liveness_end_of_block(lv, arch_env, cls, bl, live);
758         sched_foreach_reverse(bl, irn) {
759                 be_liveness_transfer(arch_env, cls, irn, live);
760                 if(irn == pos)
761                         return live;
762         }
763
764         return live;
765 }
766
767 void be_init_live(void)
768 {
769         FIRM_DBG_REGISTER(dbg, "firm.be.liveness");
770 }
771
772 BE_REGISTER_MODULE_CONSTRUCTOR(be_init_live);