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