add a bitset_copy_into function and use it in belive.c to avoid assertion failures
[libfirm] / ir / be / belive.c
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  * @version     $Id$
26  */
27 #include "config.h"
28
29 /* statev is expensive here, only enable when needed */
30 #define DISABLE_STATEV
31
32 #include "impl.h"
33 #include "iredges_t.h"
34 #include "irgwalk.h"
35 #include "irprintf_t.h"
36 #include "irbitset.h"
37 #include "irdump_t.h"
38 #include "irnodeset.h"
39
40 #include "dfs_t.h"
41 #include "absgraph.h"
42 #include "statev.h"
43
44 #include "beutil.h"
45 #include "belive_t.h"
46 #include "beirg.h"
47 #include "besched.h"
48 #include "bemodule.h"
49
50 DEBUG_ONLY(static firm_dbg_module_t *dbg = NULL;)
51
52 #define LV_STD_SIZE             64
53
54 /* if defined, use binary search for already live nodes, else linear */
55 #define LV_USE_BINARY_SEARCH
56 #undef  LV_INTESIVE_CHECKS
57
58 void be_live_chk_compare(be_lv_t *lv, lv_chk_t *lvc);
59
60 /**
61  * Filter out some nodes for which we never need liveness.
62  *
63  * @param irn  the node t check
64  * @return 0 if no liveness info is needed, 1 else
65  */
66 static inline int is_liveness_node(const ir_node *irn)
67 {
68         switch (get_irn_opcode(irn)) {
69         case iro_Block:
70         case iro_Bad:
71         case iro_End:
72         case iro_Anchor:
73         case iro_NoMem:
74                 return 0;
75         default:
76                 return 1;
77         }
78 }
79
80 int (be_is_live_in)(const be_lv_t *lv, const ir_node *block, const ir_node *irn)
81 {
82         return _be_is_live_xxx(lv, block, irn, be_lv_state_in);
83 }
84
85 int (be_is_live_out)(const be_lv_t *lv, const ir_node *block, const ir_node *irn)
86 {
87         return _be_is_live_xxx(lv, block, irn, be_lv_state_out);
88 }
89
90 int (be_is_live_end)(const be_lv_t *lv, const ir_node *block, const ir_node *irn)
91 {
92         return _be_is_live_xxx(lv, block, irn, be_lv_state_end);
93 }
94
95
96 #ifdef LV_USE_BINARY_SEARCH
97 static inline unsigned _be_liveness_bsearch(struct _be_lv_info_t *arr, unsigned idx)
98 {
99         struct _be_lv_info_t *payload = arr + 1;
100
101         unsigned n   = arr[0].u.head.n_members;
102         unsigned res = 0;
103         int lo       = 0;
104         int hi       = n;
105
106         if (n == 0)
107                 return 0;
108
109         do {
110                 int md          = lo + ((hi - lo) >> 1);
111                 unsigned md_idx = payload[md].u.node.idx;
112
113                 if (idx > md_idx)
114                         lo = md + 1;
115                 else if (idx < md_idx)
116                         hi = md;
117                 else {
118                         res = md;
119                         assert(payload[res].u.node.idx == idx);
120                         break;
121                 }
122
123                 res = lo;
124         } while (lo < hi);
125
126 #ifdef LV_INTESIVE_CHECKS
127         {
128                 unsigned i;
129                 for (i = res; i < n; ++i)
130                         assert(payload[i].u.node.idx >= idx);
131
132                 for (i = 0; i < res; ++i)
133                         assert(payload[i].u.node.idx < idx);
134         }
135 #endif
136
137         return res;
138 }
139
140 #else
141
142 /**
143  * This function searches linearly for the node in the array.
144  */
145 static inline unsigned _be_liveness_bsearch(struct _be_lv_info_t *arr, unsigned idx)
146 {
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;
162         struct _be_lv_info_node_t *res = NULL;
163
164         stat_ev_tim_push();
165         irn_live = phase_get_irn_data(&li->ph, bl);
166         if (irn_live) {
167                 unsigned idx = get_irn_idx(irn);
168
169                 /* Get the position of the index in the array. */
170                 int pos = _be_liveness_bsearch(irn_live, idx);
171
172                 /* Get the record in question. 1 must be added, since the first record contains information about the array and must be skipped. */
173                 struct _be_lv_info_node_t *rec = &irn_live[pos + 1].u.node;
174
175                 /* Check, if the irn is in deed in the array. */
176                 if (rec->idx == idx)
177                         res = rec;
178         }
179         stat_ev_tim_pop("be_lv_get");
180
181         return res;
182 }
183
184 static struct _be_lv_info_node_t *be_lv_get_or_set(struct _be_lv_t *li, ir_node *bl, ir_node *irn)
185 {
186         struct _be_lv_info_t *irn_live = phase_get_or_set_irn_data(&li->ph, bl);
187
188         unsigned idx = get_irn_idx(irn);
189
190         /* Get the position of the index in the array. */
191         unsigned pos = _be_liveness_bsearch(irn_live, idx);
192
193         /* Get the record in question. 1 must be added, since the first record contains information about the array and must be skipped. */
194         struct _be_lv_info_node_t *res = &irn_live[pos + 1].u.node;
195
196         /* Check, if the irn is in deed in the array. */
197         if (res->idx != idx) {
198                 struct _be_lv_info_t *payload;
199                 unsigned n_members = irn_live[0].u.head.n_members;
200                 unsigned n_size    = irn_live[0].u.head.n_size;
201                 unsigned i;
202
203                 if (n_members + 1 >= n_size) {
204                         /* double the array size. Remember that the first entry is
205                          * metadata about the array and not a real array element */
206                         unsigned old_size_bytes  = (n_size + 1) * sizeof(irn_live[0]);
207                         unsigned new_size        = (2 * n_size) + 1;
208                         size_t   new_size_bytes  = new_size * sizeof(irn_live[0]);
209                         struct _be_lv_info_t *nw = phase_alloc(&li->ph, new_size_bytes);
210                         memcpy(nw, irn_live, old_size_bytes);
211                         memset(((char*) nw) + old_size_bytes, 0,
212                                new_size_bytes - old_size_bytes);
213                         nw[0].u.head.n_size = new_size - 1;
214                         irn_live = nw;
215                         phase_set_irn_data(&li->ph, bl, nw);
216                 }
217
218                 payload = &irn_live[1];
219                 for (i = n_members; i > pos; --i) {
220                         payload[i] = payload[i - 1];
221                 }
222
223                 ++irn_live[0].u.head.n_members;
224
225                 res = &payload[pos].u.node;
226                 res->idx    = idx;
227                 res->flags  = 0;
228         }
229
230 #ifdef LV_INTESIVE_CHECKS
231         {
232                 unsigned i;
233                 unsigned n = irn_live[0].u.head.n_members;
234                 unsigned last = 0;
235                 struct _be_lv_info_t *payload = &irn_live[1];
236
237                 for (i = 0; i < n; ++i) {
238                         assert(payload[i].u.node.idx >= last);
239                         last = payload[i].u.node.idx;
240                 }
241         }
242 #endif
243
244         return res;
245 }
246
247 /**
248  * Removes a node from the list of live variables of a block.
249  * @return 1 if the node was live at that block, 0 if not.
250  */
251 static int be_lv_remove(struct _be_lv_t *li, const ir_node *bl,
252                         const ir_node *irn)
253 {
254         struct _be_lv_info_t *irn_live = phase_get_irn_data(&li->ph, bl);
255
256         if (irn_live) {
257                 unsigned n   = irn_live[0].u.head.n_members;
258                 unsigned idx = get_irn_idx(irn);
259                 unsigned pos = _be_liveness_bsearch(irn_live, idx);
260                 struct _be_lv_info_t *payload  = irn_live + 1;
261                 struct _be_lv_info_node_t *res = &payload[pos].u.node;
262
263                 /* The node is in deed in the block's array. Let's remove it. */
264                 if (res->idx == idx) {
265                         unsigned i;
266
267                         for (i = pos + 1; i < n; ++i)
268                                 payload[i - 1] = payload[i];
269
270                         payload[n - 1].u.node.idx   = 0;
271                         payload[n - 1].u.node.flags = 0;
272
273                         --irn_live[0].u.head.n_members;
274                         DBG((dbg, LEVEL_3, "\tdeleting %+F from %+F at pos %d\n", irn, bl, pos));
275                         return 1;
276                 }
277         }
278
279         return 0;
280 }
281
282 static void register_node(be_lv_t *lv, const ir_node *irn)
283 {
284         unsigned idx = get_irn_idx(irn);
285         if (idx >= bitset_size(lv->nodes)) {
286                 bitset_t *nw = bitset_malloc(2 * idx);
287                 bitset_copy_into(nw, lv->nodes);
288                 bitset_free(lv->nodes);
289                 lv->nodes = nw;
290         }
291
292         bitset_set(lv->nodes, idx);
293 }
294
295 /**
296  * Mark a node as live-in in a block.
297  */
298 static inline void mark_live_in(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 in at %+F\n", irn, block));
302         n->flags |= be_lv_state_in;
303         register_node(lv, irn);
304 }
305
306 /**
307  * Mark a node as live-out in a block.
308  */
309 static inline void mark_live_out(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 out at %+F\n", irn, block));
313         n->flags |= be_lv_state_out | be_lv_state_end;
314         register_node(lv, irn);
315 }
316
317 /**
318  * Mark a node as live-end in a block.
319  */
320 static inline void mark_live_end(be_lv_t *lv, ir_node *block, ir_node *irn)
321 {
322         struct _be_lv_info_node_t *n = be_lv_get_or_set(lv, block, irn);
323         DBG((dbg, LEVEL_2, "marking %+F live end at %+F\n", irn, block));
324         n->flags |= be_lv_state_end;
325         register_node(lv, irn);
326 }
327
328 static struct {
329         be_lv_t  *lv;         /**< The liveness object. */
330         ir_node  *def;        /**< The node (value). */
331         ir_node  *def_block;  /**< The block of def. */
332         bitset_t *visited;    /**< A set were all visited blocks are recorded. */
333 } re;
334
335 /**
336  * Mark a node (value) live out at a certain block. Do this also
337  * transitively, i.e. if the block is not the block of the value's
338  * definition, all predecessors are also marked live.
339  * @param block The block to mark the value live out of.
340  * @param is_true_out Is the node real out there or only live at the end
341  * of the block.
342  */
343 static void live_end_at_block(ir_node *block, int is_true_out)
344 {
345         be_lv_t *lv  = re.lv;
346         ir_node *def = re.def;
347         bitset_t *visited;
348
349         mark_live_end(lv, block, def);
350         if (is_true_out)
351                 mark_live_out(lv, block, def);
352
353         visited = re.visited;
354         if (!bitset_contains_irn(visited, block)) {
355                 bitset_add_irn(visited, block);
356
357                 /*
358                  * If this block is not the definition block, we have to go up
359                  * further.
360                  */
361                 if (re.def_block != block) {
362                         int i;
363
364                         mark_live_in(lv, block, def);
365
366                         for (i = get_Block_n_cfgpreds(block) - 1; i >= 0; --i)
367                                 live_end_at_block(get_Block_cfgpred_block(block, i), 1);
368                 }
369         }
370 }
371
372 typedef struct _lv_walker_t {
373         be_lv_t *lv;
374         void *data;
375 } lv_walker_t;
376
377 typedef struct lv_remove_walker_t {
378         be_lv_t       *lv;
379         const ir_node *irn;
380 } lv_remove_walker_t;
381
382
383 /**
384  * Liveness analysis for a value.
385  * Compute the set of all blocks a value is live in.
386  * @param irn     The node (value).
387  */
388 static void liveness_for_node(ir_node *irn)
389 {
390         const ir_edge_t *edge;
391         ir_node *def_block;
392
393         bitset_clear_all(re.visited);
394         def_block = get_nodes_block(irn);
395
396         re.def       = irn;
397         re.def_block = def_block;
398
399         /* Go over all uses of the value */
400         foreach_out_edge(irn, edge) {
401                 ir_node *use = edge->src;
402                 ir_node *use_block;
403
404                 DBG((dbg, LEVEL_4, "%+F: use at %+F, pos %d in %+F\n", irn, use, edge->pos, get_block(use)));
405                 assert(get_irn_n(use, edge->pos) == irn);
406
407                 /*
408                  * If the usage is no data node, skip this use, since it does not
409                  * affect the liveness of the node.
410                  */
411                 if (!is_liveness_node(use))
412                         continue;
413
414                 /* Get the block where the usage is in. */
415                 use_block = get_nodes_block(use);
416
417                 /*
418                  * If the use is a phi function, determine the corresponding block
419                  * through which the value reaches the phi function and mark the
420                  * value as live out of that block.
421                  */
422                 if (is_Phi(use)) {
423                         ir_node *pred_block = get_Block_cfgpred_block(use_block, edge->pos);
424                         live_end_at_block(pred_block, 0);
425                 }
426
427                 /*
428                  * Else, the value is live in at this block. Mark it and call live
429                  * out on the predecessors.
430                  */
431                 else if (def_block != use_block) {
432                         int i;
433
434                         mark_live_in(re.lv, use_block, irn);
435
436                         for (i = get_Block_n_cfgpreds(use_block) - 1; i >= 0; --i) {
437                                 ir_node *pred_block = get_Block_cfgpred_block(use_block, i);
438                                 live_end_at_block(pred_block, 1);
439                         }
440                 }
441         }
442 }
443
444 static void lv_remove_irn_walker(ir_node *bl, void *data)
445 {
446         lv_remove_walker_t *w = data;
447         be_lv_remove(w->lv, bl, w->irn);
448 }
449
450 static const char *lv_flags_to_str(unsigned flags)
451 {
452         static const char *states[] = {
453                 "---",
454                 "i--",
455                 "-e-",
456                 "ie-",
457                 "--o",
458                 "i-o",
459                 "-eo",
460                 "ieo"
461         };
462
463         return states[flags & 7];
464 }
465
466 static void lv_dump_block(void *context, FILE *f, const ir_node *bl)
467 {
468         if (is_Block(bl)) {
469                 be_lv_t *lv = context;
470                 struct _be_lv_info_t *info = phase_get_irn_data(&lv->ph, bl);
471
472                 fprintf(f, "liveness:\n");
473                 if (info) {
474                         unsigned n = info[0].u.head.n_members;
475                         unsigned i;
476
477                         for (i = 0; i < n; ++i) {
478                                 struct _be_lv_info_node_t *n = &info[i+1].u.node;
479                                 ir_fprintf(f, "%s %+F\n", lv_flags_to_str(n->flags), get_idx_irn(lv->irg, n->idx));
480                         }
481                 }
482         }
483 }
484
485 static void *lv_phase_data_init(ir_phase *phase, const ir_node *irn, void *old)
486 {
487         struct _be_lv_info_t *info = phase_alloc(phase, LV_STD_SIZE * sizeof(info[0]));
488         (void) irn;
489         (void) old;
490
491         memset(info, 0, LV_STD_SIZE * sizeof(info[0]));
492         info[0].u.head.n_size = LV_STD_SIZE - 1;
493         return info;
494 }
495
496 /**
497  * Walker, collect all nodes for which we want calculate liveness info
498  * on an obstack.
499  */
500 static void collect_liveness_nodes(ir_node *irn, void *data)
501 {
502         ir_node **nodes = data;
503         if (is_liveness_node(irn))
504                 nodes[get_irn_idx(irn)] = irn;
505 }
506
507 static void compute_liveness(be_lv_t *lv)
508 {
509         ir_node **nodes;
510         int i, n;
511
512         stat_ev_tim_push();
513         n = get_irg_last_idx(lv->irg);
514         nodes = NEW_ARR_F(ir_node *, n);
515         memset(nodes, 0, sizeof(nodes[0]) * n);
516
517         /*
518          * inserting the variables sorted by their ID is probably
519          * more efficient since the binary sorted set insertion
520          * will not need to move around the data.
521          */
522         irg_walk_graph(lv->irg, NULL, collect_liveness_nodes, nodes);
523
524         re.lv      = lv;
525         re.visited = bitset_malloc(n);
526
527         for (i = 0; i < n; ++i) {
528                 if (nodes[i] != NULL)
529                         liveness_for_node(nodes[i]);
530         }
531
532         DEL_ARR_F(nodes);
533         free(re.visited);
534         register_hook(hook_node_info, &lv->hook_info);
535         stat_ev_tim_pop("be_lv_sets_cons");
536 }
537
538 void be_liveness_assure_sets(be_lv_t *lv)
539 {
540         if (!lv->nodes) {
541                 be_timer_push(T_LIVE);
542
543                 lv->nodes = bitset_malloc(2 * get_irg_last_idx(lv->irg));
544                 phase_init(&lv->ph, lv->irg, lv_phase_data_init);
545                 compute_liveness(lv);
546                 /* be_live_chk_compare(lv, lv->lvc); */
547
548                 be_timer_pop(T_LIVE);
549         }
550 }
551
552 void be_liveness_assure_chk(be_lv_t *lv)
553 {
554 #ifndef USE_LIVE_CHK
555         be_timer_push(t_verify);
556         be_liveness_assure_sets(lv);
557         be_timer_pop(t_verify);
558 #else
559         (void) lv;
560 #endif
561 }
562
563 void be_liveness_invalidate(be_lv_t *lv)
564 {
565         if (lv && lv->nodes) {
566                 unregister_hook(hook_node_info, &lv->hook_info);
567                 phase_deinit(&lv->ph);
568                 bitset_free(lv->nodes);
569                 lv->nodes = NULL;
570         }
571 }
572
573 /* Compute the inter block liveness for a graph. */
574 be_lv_t *be_liveness(ir_graph *irg)
575 {
576         be_lv_t *lv = XMALLOCZ(be_lv_t);
577
578         lv->irg  = irg;
579 #ifdef USE_LIVE_CHK
580         lv->dfs  = dfs_new(&absgraph_irg_cfg_succ, irg);
581         lv->lvc  = lv_chk_new(lv->irg, lv->dfs);
582 #endif
583         lv->hook_info.context = lv;
584         lv->hook_info.hook._hook_node_info = lv_dump_block;
585
586         return lv;
587 }
588
589 void be_liveness_recompute(be_lv_t *lv)
590 {
591         unsigned last_idx;
592
593         be_timer_push(T_LIVE);
594         last_idx = get_irg_last_idx(lv->irg);
595         if (last_idx >= bitset_size(lv->nodes)) {
596                 bitset_free(lv->nodes);
597                 lv->nodes = bitset_malloc(last_idx * 2);
598         } else
599                 bitset_clear_all(lv->nodes);
600
601         phase_deinit(&lv->ph);
602         phase_init(&lv->ph, lv->irg, lv_phase_data_init);
603         compute_liveness(lv);
604
605         be_timer_pop(T_LIVE);
606 }
607
608
609 void be_liveness_free(be_lv_t *lv)
610 {
611         be_liveness_invalidate(lv);
612 #ifdef USE_LIVE_CHK
613         lv_chk_free(lv->lvc);
614         dfs_free(lv->dfs);
615 #endif
616         xfree(lv);
617 }
618
619 void be_liveness_remove(be_lv_t *lv, const ir_node *irn)
620 {
621         if (lv->nodes) {
622                 unsigned idx = get_irn_idx(irn);
623                 lv_remove_walker_t w;
624
625                 /*
626                  * Removes a single irn from the liveness information.
627                  * Since an irn can only be live at blocks dominated by the block of its
628                  * definition, we only have to process that dominance subtree.
629                  */
630                 w.lv  = lv;
631                 w.irn = irn;
632                 dom_tree_walk(get_nodes_block(irn), lv_remove_irn_walker, NULL, &w);
633                 if (idx < bitset_size(lv->nodes))
634                         bitset_clear(lv->nodes, idx);
635         }
636 }
637
638 void be_liveness_introduce(be_lv_t *lv, ir_node *irn)
639 {
640         /* Don't compute liveness information for non-data nodes. */
641         if (lv->nodes && is_liveness_node(irn)) {
642                 re.lv      = lv;
643                 re.visited = bitset_malloc(get_irg_last_idx(lv->irg));
644                 liveness_for_node(irn);
645                 bitset_free(re.visited);
646         }
647 }
648
649 void be_liveness_update(be_lv_t *lv, ir_node *irn)
650 {
651         be_liveness_remove(lv, irn);
652         be_liveness_introduce(lv, irn);
653 }
654
655 static void lv_check_walker(ir_node *bl, void *data)
656 {
657         lv_walker_t *w = data;
658         be_lv_t *lv    = w->lv;
659         be_lv_t *fresh = w->data;
660
661         struct _be_lv_info_t *curr = phase_get_irn_data(&lv->ph, bl);
662         struct _be_lv_info_t *fr   = phase_get_irn_data(&fresh->ph, bl);
663
664         if (!fr && curr && curr[0].u.head.n_members > 0) {
665                 unsigned i;
666
667                 ir_fprintf(stderr, "%+F liveness should be empty but current liveness contains:\n", bl);
668                 for (i = 0; i < curr[0].u.head.n_members; ++i) {
669                         ir_fprintf(stderr, "\t%+F\n", get_idx_irn(lv->irg, curr[1 + i].u.node.idx));
670                 }
671         }
672
673         else if (curr) {
674                 unsigned n_curr  = curr[0].u.head.n_members;
675                 unsigned n_fresh = fr[0].u.head.n_members;
676
677                 unsigned i;
678
679                 if (n_curr != n_fresh) {
680                         ir_fprintf(stderr, "%+F: liveness set sizes differ. curr %d, correct %d\n", bl, n_curr, n_fresh);
681
682                         ir_fprintf(stderr, "current:\n");
683                         for (i = 0; i < n_curr; ++i) {
684                                 struct _be_lv_info_node_t *n = &curr[1 + i].u.node;
685                                 ir_fprintf(stderr, "%+F %u %+F %s\n", bl, i, get_idx_irn(lv->irg, n->idx), lv_flags_to_str(n->flags));
686                         }
687
688                         ir_fprintf(stderr, "correct:\n");
689                         for (i = 0; i < n_fresh; ++i) {
690                                 struct _be_lv_info_node_t *n = &fr[1 + i].u.node;
691                                 ir_fprintf(stderr, "%+F %u %+F %s\n", bl, i, get_idx_irn(lv->irg, n->idx), lv_flags_to_str(n->flags));
692                         }
693                 }
694         }
695 }
696
697 void be_liveness_check(be_lv_t *lv)
698 {
699         lv_walker_t w;
700         be_lv_t *fresh = be_liveness(lv->irg);
701
702         w.lv   = lv;
703         w.data = fresh;
704         irg_block_walk_graph(lv->irg, lv_check_walker, NULL, &w);
705         be_liveness_free(fresh);
706 }
707
708
709 static void lv_dump_block_walker(ir_node *irn, void *data)
710 {
711         lv_walker_t *w = data;
712         if (is_Block(irn))
713                 lv_dump_block(w->lv, w->data, irn);
714 }
715
716
717 /* Dump the liveness information for a graph. */
718 void be_liveness_dump(const be_lv_t *lv, FILE *f)
719 {
720         lv_walker_t w;
721
722         w.lv   = (be_lv_t *) lv;
723         w.data = f;
724         irg_block_walk_graph(lv->irg, lv_dump_block_walker, NULL, &w);
725 }
726
727 /* Dump the liveness information for a graph. */
728 void be_liveness_dumpto(const be_lv_t *lv, const char *cls_name)
729 {
730         FILE *f;
731         char buf[128];
732         ir_snprintf(buf, sizeof(buf), "%F_%s-live.txt", lv->irg, cls_name);
733         if ((f = fopen(buf, "wt")) != NULL) {
734                 be_liveness_dump(lv, f);
735                 fclose(f);
736         }
737 }
738
739 /**
740  * Walker: checks the every predecessors of a node dominate
741  * the note.
742  */
743 static void dom_check(ir_node *irn, void *data)
744 {
745         int *problem_found = data;
746
747         if (!is_Block(irn) && irn != get_irg_end(get_irn_irg(irn))) {
748                 int i, n;
749                 ir_node *bl = get_nodes_block(irn);
750
751                 for (i = 0, n = get_irn_arity(irn); i < n; ++i) {
752                         ir_node *op     = get_irn_n(irn, i);
753                         ir_node *def_bl = get_nodes_block(op);
754                         ir_node *use_bl = bl;
755
756                         if (is_Phi(irn))
757                                 use_bl = get_Block_cfgpred_block(bl, i);
758
759                         if (get_irn_opcode(use_bl) != iro_Bad
760                              && get_irn_opcode(def_bl) != iro_Bad
761                              && !block_dominates(def_bl, use_bl)) {
762                                 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)));
763                                 *problem_found = 1;
764                         }
765                 }
766         }
767 }
768
769 /* Check, if the SSA dominance property is fulfilled. */
770 int be_check_dominance(ir_graph *irg)
771 {
772         int problem_found = 0;
773
774         assure_doms(irg);
775         irg_walk_graph(irg, dom_check, NULL, &problem_found);
776
777         return !problem_found;
778 }
779
780 void be_liveness_transfer(const arch_register_class_t *cls,
781                           ir_node *node, ir_nodeset_t *nodeset)
782 {
783         int i, arity;
784
785         /* You should better break out of your loop when hitting the first phi
786          * function. */
787         assert(!is_Phi(node) && "liveness_transfer produces invalid results for phi nodes");
788
789         if (get_irn_mode(node) == mode_T) {
790                 const ir_edge_t *edge;
791
792                 foreach_out_edge(node, edge) {
793                         ir_node *proj = get_edge_src_irn(edge);
794
795                         if (arch_irn_consider_in_reg_alloc(cls, proj)) {
796                                 ir_nodeset_remove(nodeset, proj);
797                         }
798                 }
799         } else if (arch_irn_consider_in_reg_alloc(cls, node)) {
800                 ir_nodeset_remove(nodeset, node);
801         }
802
803         arity = get_irn_arity(node);
804         for (i = 0; i < arity; ++i) {
805                 ir_node *op = get_irn_n(node, i);
806
807                 if (arch_irn_consider_in_reg_alloc(cls, op))
808                         ir_nodeset_insert(nodeset, op);
809         }
810 }
811
812
813
814 void be_liveness_end_of_block(const be_lv_t *lv,
815                               const arch_register_class_t *cls,
816                               const ir_node *block, ir_nodeset_t *live)
817 {
818         int i;
819
820         assert(lv->nodes && "live sets must be computed");
821         be_lv_foreach(lv, block, be_lv_state_end, i) {
822                 ir_node *node = be_lv_get_irn(lv, block, i);
823                 if (!arch_irn_consider_in_reg_alloc(cls, node))
824                         continue;
825
826                 ir_nodeset_insert(live, node);
827         }
828 }
829
830
831
832 void be_liveness_nodes_live_at(const be_lv_t *lv,
833                                const arch_register_class_t *cls,
834                                const ir_node *pos, ir_nodeset_t *live)
835 {
836         const ir_node *bl = is_Block(pos) ? pos : get_nodes_block(pos);
837         ir_node *irn;
838
839         be_liveness_end_of_block(lv, cls, bl, live);
840         sched_foreach_reverse(bl, irn) {
841                 /*
842                  * If we encounter the node we want to insert the Perm after,
843                  * exit immediately, so that this node is still live
844                  */
845                 if (irn == pos)
846                         return;
847
848                 be_liveness_transfer(cls, irn, live);
849         }
850 }
851
852 static void collect_node(ir_node *irn, void *data)
853 {
854         struct obstack *obst = data;
855         obstack_ptr_grow(obst, irn);
856 }
857
858 void be_live_chk_compare(be_lv_t *lv, lv_chk_t *lvc)
859 {
860         ir_graph *irg    = lv->irg;
861
862         struct obstack obst;
863         ir_node **nodes;
864         ir_node **blocks;
865         int i, j;
866
867         obstack_init(&obst);
868
869         irg_block_walk_graph(irg, collect_node, NULL, &obst);
870         obstack_ptr_grow(&obst, NULL);
871         blocks = obstack_finish(&obst);
872
873         irg_walk_graph(irg, collect_node, NULL, &obst);
874         obstack_ptr_grow(&obst, NULL);
875         nodes = obstack_finish(&obst);
876
877         stat_ev_ctx_push("be_lv_chk_compare");
878         for (j = 0; nodes[j]; ++j) {
879                 ir_node *irn = nodes[j];
880                 for (i = 0; blocks[i]; ++i) {
881                         ir_node *bl = blocks[i];
882
883                         if (!is_Block(irn)) {
884                                 int lvr_in  = be_is_live_in (lv, bl, irn);
885                                 int lvr_out = be_is_live_out(lv, bl, irn);
886                                 int lvr_end = be_is_live_end(lv, bl, irn);
887
888                                 int lvc_in  = lv_chk_bl_in (lvc, bl, irn);
889                                 int lvc_out = lv_chk_bl_out(lvc, bl, irn);
890                                 int lvc_end = lv_chk_bl_end(lvc, bl, irn);
891
892                                 if (lvr_in - lvc_in != 0)
893                                         ir_fprintf(stderr, "live in  info for %+F at %+F differs: nml: %d, chk: %d\n", irn, bl, lvr_in, lvc_in);
894
895                                 if (lvr_end - lvc_end != 0)
896                                         ir_fprintf(stderr, "live end info for %+F at %+F differs: nml: %d, chk: %d\n", irn, bl, lvr_end, lvc_end);
897
898                                 if (lvr_out - lvc_out != 0)
899                                         ir_fprintf(stderr, "live out info for %+F at %+F differs: nml: %d, chk: %d\n", irn, bl, lvr_out, lvc_out);
900                         }
901                 }
902         }
903         stat_ev_ctx_pop("be_lv_chk_compare");
904
905         obstack_free(&obst, NULL);
906 }
907
908 BE_REGISTER_MODULE_CONSTRUCTOR(be_init_live);
909 void be_init_live(void)
910 {
911         FIRM_DBG_REGISTER(dbg, "firm.be.liveness");
912 }