deactivate debug output
[libfirm] / ir / opt / opt_blocks.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   Combining congruent blocks
23  * @author  Michael Beck
24  * @version $Id$
25  *
26  * This phase find congruent blocks. Works currently for
27  * predecessors of the end block only.
28  * Two block are congruent, if they contains only equal calculations.
29  */
30 #include "config.h"
31 #include "ircons.h"
32 #include "irgmod.h"
33 #include "irgraph_t.h"
34 #include "irnode_t.h"
35 #include "iropt_t.h"
36 #include "set.h"
37 #include "debug.h"
38
39 typedef struct partition_t     partition_t;
40 typedef struct block_t         block_t;
41 typedef struct node_t          node_t;
42 typedef struct pair_t          pair_t;
43 typedef struct phi_t           phi_t;
44 typedef struct opcode_key_t    opcode_key_t;
45 typedef struct listmap_entry_t listmap_entry_t;
46 typedef struct environment_t   environment_t;
47
48 /** An opcode map key. */
49 struct opcode_key_t {
50         ir_opcode   code;   /**< The Firm opcode. */
51         ir_mode     *mode;  /**< The mode of all nodes in the partition. */
52         int         arity;  /**< The arity of this opcode (needed for Phi etc. */
53         union {
54                 long      proj;   /**< For Proj nodes, its proj number */
55                 ir_entity *ent;   /**< For Sel Nodes, its entity */
56         } u;
57 };
58
59 /** A partition contains all congruent blocks. */
60 struct partition_t {
61         list_head part_list;     /**< Double linked list of partitions. */
62         list_head blocks;        /**< List of blocks in this partition. */
63         unsigned  n_blocks;      /**< Number of block in this partition. */
64 #ifdef DEBUG_libfirm
65         unsigned  nr;            /**< For debugging: number of this partition. */
66 #endif
67 };
68
69 /** A block. */
70 struct block_t {
71         list_head  block_list;   /**< Double linked list of block inside a partition. */
72         list_head  nodes;        /**< Wait-queue of nodes that must be checked for congruence. */
73         block_t    *next;        /**< Next block of a split list. */
74         ir_node    *block;       /**< Pointer to the associated IR-node block. */
75         node_t     *roots;       /**< The list of all root nodes. */
76         pair_t     *input_pairs; /**< The list of inputs to this block. */
77         phi_t      *phis;        /**< The list of Phis in this block. */
78 };
79
80 /** A node. */
81 struct node_t {
82         list_head  node_list;    /**< Double linked list of block inside a partition. */
83         ir_node    *node;        /**< Pointer to the associated IR-node or NULL for block inputs. */
84         node_t     *next;        /**< Link to the next node in the root set. */
85         char       is_input;     /**< Set if this node is an input from other block. */
86 };
87
88 /** The environment. */
89 struct environment_t {
90         list_head       partitions;     /**< list of partitions. */
91         list_head       ready;          /**< list of ready partitions. */
92         set             *opcode2id_map; /**< The opcodeMode->id map. */
93         struct obstack  obst;           /** obstack for temporary data */
94 };
95
96 /** A node, input index pair. */
97 struct pair_t {
98         pair_t  *next;    /**< Points to the next pair entry. */
99         ir_node *irn;     /**< The IR-node. */
100         int     index;    /**< An input index. */
101         ir_node **ins;    /**< A new in array once allocated. */
102 };
103
104 /** A Phi, inputs pair. */
105 struct phi_t {
106         phi_t   *next;    /**< Points to the next Phi pair entry. */
107         ir_node *phi;     /**< The Phi node. */
108         ir_node **ins;    /**< A new in array once allocated. */
109 };
110
111 /**
112  * An entry in the list_map.
113  */
114 struct listmap_entry_t {
115         void            *id;    /**< The id. */
116         block_t         *list;  /**< The associated list for this id. */
117         listmap_entry_t *next;  /**< Link to the next entry in the map. */
118 };
119
120 /** We must map id's to lists. */
121 typedef struct listmap_t {
122         set             *map;    /**< Map id's to listmap_entry_t's */
123         listmap_entry_t *values; /**< List of all values in the map. */
124 } listmap_t;
125
126 /** The debug module handle. */
127 DEBUG_ONLY(static firm_dbg_module_t *dbg;)
128
129 /** Next partition number. */
130 DEBUG_ONLY(static unsigned part_nr = 0);
131
132 #ifdef DEBUG_libfirm
133 /**
134  * Dump partition to output.
135  */
136 static void dump_partition(const char *msg, const partition_t *part) {
137         const block_t *block;
138         int           first = 1;
139
140         DB((dbg, LEVEL_2, "%s part%u (%u) {\n  ", msg, part->nr, part->n_blocks));
141         list_for_each_entry(block_t, block, &part->blocks, block_list) {
142                 DB((dbg, LEVEL_2, "%s%+F", first ? "" : ", ", block->block));
143                 first = 0;
144         }
145         DB((dbg, LEVEL_2, "\n}\n"));
146 }  /* dump_partition */
147
148 /**
149  * Dumps a list.
150  */
151 static void dump_list(const char *msg, const block_t *block) {
152         const block_t *p;
153         int           first = 1;
154
155         DB((dbg, LEVEL_3, "%s = {\n  ", msg));
156         for (p = block; p != NULL; p = p->next) {
157                 DB((dbg, LEVEL_3, "%s%+F", first ? "" : ", ", p->block));
158                 first = 0;
159         }
160         DB((dbg, LEVEL_3, "\n}\n"));
161 }  /* do_dump_list */
162 #else
163 #define dump_partition(msg, part)
164 #define dump_list(msg, block)
165 #endif
166
167 /**
168  * Compare two pointer values of a listmap.
169  */
170 static int listmap_cmp_ptr(const void *elt, const void *key, size_t size) {
171         const listmap_entry_t *e1 = elt;
172         const listmap_entry_t *e2 = key;
173
174         (void) size;
175         return e1->id != e2->id;
176 }  /* listmap_cmp_ptr */
177
178 /**
179  * Initializes a listmap.
180  *
181  * @param map  the listmap
182  */
183 static void listmap_init(listmap_t *map) {
184         map->map    = new_set(listmap_cmp_ptr, 16);
185         map->values = NULL;
186 }  /* listmap_init */
187
188 /**
189  * Terminates a listmap.
190  *
191  * @param map  the listmap
192  */
193 static void listmap_term(listmap_t *map) {
194         del_set(map->map);
195 }  /* listmap_term */
196
197 /**
198  * Return the associated listmap entry for a given id.
199  *
200  * @param map  the listmap
201  * @param id   the id to search for
202  *
203  * @return the associated listmap entry for the given id
204  */
205 static listmap_entry_t *listmap_find(listmap_t *map, void *id) {
206         listmap_entry_t key, *entry;
207
208         key.id   = id;
209         key.list = NULL;
210         key.next = NULL;
211         entry = set_insert(map->map, &key, sizeof(key), HASH_PTR(id));
212
213         if (entry->list == NULL) {
214                 /* a new entry, put into the list */
215                 entry->next = map->values;
216                 map->values = entry;
217         }
218         return entry;
219 }  /* listmap_find */
220
221 /**
222  * Calculate the hash value for an opcode map entry.
223  *
224  * @param entry  an opcode map entry
225  *
226  * @return a hash value for the given opcode map entry
227  */
228 static unsigned opcode_hash(const opcode_key_t *entry) {
229         return (entry->mode - (ir_mode *)0) * 9 + entry->code + entry->u.proj * 3 + HASH_PTR(entry->u.ent) + entry->arity;
230 }  /* opcode_hash */
231
232 /**
233  * Compare two entries in the opcode map.
234  */
235 static int cmp_opcode(const void *elt, const void *key, size_t size) {
236         const opcode_key_t *o1 = elt;
237         const opcode_key_t *o2 = key;
238
239         (void) size;
240         return o1->code != o2->code || o1->mode != o2->mode ||
241                o1->arity != o2->arity ||
242                o1->u.proj != o2->u.proj || o1->u.ent != o2->u.ent;
243 }  /* cmp_opcode */
244
245 /**
246  * Creates a new empty partition.
247  */
248 static partition_t *create_partition(environment_t *env) {
249         partition_t *part = obstack_alloc(&env->obst, sizeof(*part));
250
251         INIT_LIST_HEAD(&part->blocks);
252         part->n_blocks = 0;
253         DEBUG_ONLY(part->nr = part_nr++);
254         list_add_tail(&part->part_list, &env->partitions);
255         return part;
256 }  /* create_partition */
257
258 /**
259  * Allocate a new block.
260  *
261  * @param block  the IR-node
262  * @param env    the environment
263  */
264 static block_t *create_block(ir_node *block, environment_t *env) {
265         block_t *bl = obstack_alloc(&env->obst, sizeof(*bl));
266
267         INIT_LIST_HEAD(&bl->nodes);
268         bl->next        = NULL;
269         bl->block       = block;
270         bl->roots       = NULL;
271         bl->input_pairs = NULL;
272         bl->phis        = NULL;
273         return bl;
274 }  /* create_block */
275
276 /**
277  * Adds a block to a partition.
278  *
279  * @param partition  the partition to add to
280  * @param block      the block to add
281  */
282 static void add_block(partition_t *partition, block_t *block) {
283         list_add_tail(&block->block_list, &partition->blocks);
284         ++partition->n_blocks;
285 }  /* add_block */
286
287 /**
288  * Allocate a new node.
289  *
290  * @param irn    the IR-node
291  * @param env    the environment
292  */
293 static node_t *create_node(ir_node *irn, environment_t *env) {
294         node_t *node = obstack_alloc(&env->obst, sizeof(*node));
295
296         node->node     = irn;
297         node->next     = NULL;
298         node->is_input = 0;
299         return node;
300 }  /* create_node */
301
302 /**
303  * Adds a node to a block wait queue.
304  *
305  * @param block  the block to add to
306  * @param node   the node to add
307  */
308 static void add_node(block_t *block, node_t *node) {
309         list_add_tail(&node->node_list, &block->nodes);
310 }  /* add_node */
311
312 /**
313  * Add an input pair to a block.
314  *
315  * @param block  the block
316  * @param irn    the IR-node that has an block input
317  * @param idx    the index of the block input in node's predecessors
318  * @param env    the environment
319  */
320 static void add_pair(block_t *block, ir_node *irn, int idx, environment_t *env) {
321         pair_t *pair = obstack_alloc(&env->obst, sizeof(*pair));
322
323         pair->next  = block->input_pairs;
324         pair->irn   = irn;
325         pair->index = idx;
326         pair->ins   = NULL;
327
328         block->input_pairs = pair;
329 }  /* add_pair */
330
331 /**
332  * Add a Phi to a block.
333  *
334  * @param block  the block
335  * @param phi    the Phi node
336  * @param env    the environment
337  */
338 static void add_phi(block_t *block, ir_node *phi, environment_t *env) {
339         phi_t *node = obstack_alloc(&env->obst, sizeof(*node));
340
341         node->next = block->phis;
342         node->phi  = phi;
343         node->ins  = NULL;
344
345         block->phis = node;
346 }  /** add_phi */
347
348 /**
349  * Creates an opcode from a node.
350  */
351 static opcode_key_t *opcode(const node_t *node, environment_t *env) {
352         opcode_key_t key, *entry;
353         ir_node      *irn = node->node;
354
355         if (node->is_input) {
356                 /* Node: as Block nodes are never propagated, it is safe to
357                    use its code for "input" node */
358                 key.code   = iro_Block;
359                 key.arity  = 0;
360         } else {
361                 key.code   = get_irn_opcode(irn);
362                 key.arity  = get_irn_arity(irn);
363         }
364         key.mode   = get_irn_mode(node->node);
365         key.u.proj = 0;
366         key.u.ent  = NULL;
367
368         switch (key.code) {
369         case iro_Proj:
370                 key.u.proj = get_Proj_proj(irn);
371                 break;
372         case iro_Sel:
373                 key.u.ent = get_Sel_entity(irn);
374                 break;
375         default:
376                 break;
377         }
378
379         entry = set_insert(env->opcode2id_map, &key, sizeof(key), opcode_hash(&key));
380         return entry;
381 }  /* opcode */
382
383 /**
384  * Split a partition by a local list.
385  *
386  * @param Z    partition to split
387  * @param g    a (non-empty) block list
388  * @param env  the environment
389  *
390  * @return  a new partition containing the nodes of g
391  */
392 static partition_t *split(partition_t *Z, block_t *g, environment_t *env) {
393         partition_t *Z_prime;
394         block_t     *block;
395         unsigned    n = 0;
396
397         dump_partition("Splitting ", Z);
398         dump_list("by list ", g);
399
400         assert(g != NULL);
401
402         /* Remove g from Z. */
403         for (block = g; block != NULL; block = block->next) {
404                 list_del(&block->block_list);
405                 ++n;
406         }
407         assert(n < Z->n_blocks);
408         Z->n_blocks -= n;
409
410         /* Move g to a new partition, Z'. */
411         Z_prime = create_partition(env);
412         for (block = g; block != NULL; block = block->next) {
413                 list_add_tail(&block->block_list, &Z_prime->blocks);
414         }
415         Z_prime->n_blocks = n;
416
417         dump_partition("Now ", Z);
418         dump_partition("Created new ", Z_prime);
419         return Z_prime;
420 }  /* split */
421
422 /**
423  * Propagate nodes on all wait queues of the given partition.
424  *
425  * @param part  the partition
426  * @param env    the environment
427  */
428 void propagate_blocks(partition_t *part, environment_t *env) {
429         block_t         *ready_blocks = NULL;
430         unsigned        n_ready       = 0;
431         block_t         *bl, *next;
432         listmap_t       map;
433         listmap_entry_t *iter;
434
435         DB((dbg, LEVEL_2, "Propagate blocks on part%u\n", part->nr));
436
437         /* Let map be an empty mapping from the range of Opcodes to (local) list of Nodes. */
438         listmap_init(&map);
439         list_for_each_entry_safe(block_t, bl, next, &part->blocks, block_list) {
440                 opcode_key_t    *id;
441                 listmap_entry_t *entry;
442                 node_t          *node;
443
444                 if (list_empty(&bl->nodes)) {
445                         bl->next     = ready_blocks;
446                         ready_blocks = bl;
447                         ++n_ready;
448                         DB((dbg, LEVEL_1, "Block %+F completely processed\n", bl->block));
449                         continue;
450                 }
451
452                 /* get the first node from the wait queue */
453                 node = list_entry(bl->nodes.next, node_t, node_list);
454                 list_del(&node->node_list);
455
456                 /* put all not-visited predecessors to the wait queue */
457                 if (! node->is_input) {
458                         ir_node *irn = node->node;
459                         int     i;
460
461                         DB((dbg, LEVEL_3, "  propagate %+F\n", node->node));
462                         ir_normalize_node(node->node);
463                         for (i = get_irn_arity(irn) - 1; i >= 0; --i) {
464                                 ir_node *pred  = get_irn_n(irn, i);
465                                 ir_node *block = get_nodes_block(skip_Proj(pred));
466                                 node_t *p_node;
467
468                                 if (block != bl->block) {
469                                         p_node = create_node(pred, env);
470                                         p_node->is_input = 1;
471                                         add_node(bl, p_node);
472                                         if (! is_Phi(irn))
473                                                 add_pair(bl, node->node, i, env);
474                                 } else if (! irn_visited_else_mark(pred)) {
475                                         /* not yet visited, ok */
476                                         p_node = create_node(pred, env);
477                                         add_node(bl, p_node);
478
479                                         if (is_Phi(pred)) {
480                                                 /* update the Phi list */
481                                                 add_phi(bl, pred, env);
482                                         }
483                                 }
484                         }
485                 } else {
486                         DB((dbg, LEVEL_3, "  propagate Input %+F\n", node->node));
487                 }
488
489                 /* Add bl to map[opcode(bl)]. */
490                 id          = opcode(node, env);
491                 entry       = listmap_find(&map, id);
492                 bl->next    = entry->list;
493                 entry->list = bl;
494         }
495
496         /* split out ready blocks */
497         if (n_ready > 0) {
498                 partition_t *Z;
499
500                 if (n_ready < part->n_blocks)
501                         Z = split(part, ready_blocks, env);
502                 else
503                         Z = part;
504                 list_del(&Z->part_list);
505
506                 if (Z->n_blocks > 1) {
507                         DB((dbg, LEVEL_1, "Partition %u is ready\n", Z->nr));
508                         list_add(&Z->part_list, &env->ready);
509                 } else {
510                         DB((dbg, LEVEL_1, "Partition %u contains only one block, killed\n", Z->nr));
511                 }
512         }
513
514         /* for all sets S except one in the range of map do */
515         for (iter = map.values; iter != NULL; iter = iter->next) {
516                 block_t *S;
517
518                 if (iter->next == NULL) {
519                         /* this is the last entry, ignore */
520                         break;
521                 }
522                 S = iter->list;
523
524                 /* Add SPLIT( X, S ) to P. */
525                 split(part, S, env);
526         }
527         listmap_term(&map);
528 }  /* propagate_blocks */
529
530 /**
531  * Propagate nodes on all wait queues.
532  *
533  * @param env    the environment
534  */
535 void propagate(environment_t *env) {
536         partition_t *part, *next;
537
538         list_for_each_entry_safe(partition_t, part, next, &env->partitions, part_list) {
539                 if (part->n_blocks == 1) {
540                         /* only one block left, move to ready */
541                         list_del(&part->part_list);
542                         DB((dbg, LEVEL_1, "Partition %u contains only one block, killed\n", part->nr));
543                 } else
544                         propagate_blocks(part, env);
545         }
546 }  /* propagate */
547
548 /**
549  * Apply analysis results by replacing all blocks of a partition
550  * by one representative.
551  *
552  * Route all inputs from all block of the partition to the one
553  * representative.
554  * Enhance all existing Phis by combining them.
555  * Create new Phis for all previous input nodes.
556  *
557  * @param part  the partition to process
558  */
559 static void apply(ir_graph *irg, partition_t *part) {
560         block_t *repr = list_entry(part->blocks.next, block_t, block_list);
561         block_t *bl;
562         ir_node *block, *end, *end_block;
563         ir_node **ins;
564         phi_t   *repr_phi, *phi;
565         pair_t  *repr_pair, *pair;
566         int     i, j, n, block_nr;
567
568         list_del(&repr->block_list);
569
570         /* prepare new in arrays for the block ... */
571         block = repr->block;
572         n     = get_Block_n_cfgpreds(block);
573         ins   = NEW_ARR_F(ir_node *, n);
574
575         for (i = 0; i < n; ++i)
576                 ins[i] = get_Block_cfgpred(block, i);
577
578         /* ... for all existing Phis ... */
579         for (repr_phi = repr->phis; repr_phi != NULL; repr_phi = repr_phi->next) {
580                 repr_phi->ins = NEW_ARR_F(ir_node *, n);
581
582                 for (i = 0; i < n; ++i)
583                         ins[i] = get_Phi_pred(repr_phi->phi, i);
584         }
585
586         /* ... and all newly created Phis */
587         for (repr_pair = repr->input_pairs; repr_pair != NULL; repr_pair = repr_pair->next) {
588                 repr_pair->ins = NEW_ARR_F(ir_node *, part->n_blocks);
589                 repr_pair->ins[0] = get_irn_n(repr_pair->irn, repr_pair->index);
590         }
591
592         /* collect new in arrays */
593         end = get_irg_end(irg);
594         block_nr = 0;
595         list_for_each_entry(block_t, bl, &part->blocks, block_list) {
596                 block = bl->block;
597                 ++block_nr;
598
599                 /* first step: kill any keep-alive from this block */
600                 for (i = get_End_n_keepalives(end) - 1; i >= 0; --i) {
601                         ir_node *ka = get_End_keepalive(end, i);
602
603                         if (is_Block(ka)) {
604                                 if (ka == block)
605                                         remove_End_keepalive(end, ka);
606                         } else {
607                                 if (get_nodes_block(ka) == block)
608                                         remove_End_keepalive(end, ka);
609                         }
610                 }
611
612                 /* second step: update control flow */
613                 n = get_Block_n_cfgpreds(block);
614                 for (i = 0; i < n; ++i) {
615                         ARR_APP1(ir_node *, ins, get_Block_cfgpred(block, i));
616                 }
617
618                 /* third step: update Phis */
619                 for (repr_phi = repr->phis, phi = bl->phis;
620                      repr_phi != NULL;
621                      repr_phi = repr_phi->next, phi = phi->next) {
622                         for (i = 0; i < n; ++i)
623                                 ARR_APP1(ir_node *, repr_phi->ins, get_Phi_pred(phi->phi, i));
624                 }
625
626                 /* fourth step: update inputs for new Phis */
627                 for (repr_pair = repr->input_pairs, pair = bl->input_pairs;
628                      repr_pair != NULL;
629                      repr_pair = repr_pair->next, pair = pair->next) {
630                         repr_pair->ins[block_nr] = get_irn_n(pair->irn, pair->index);
631                 }
632         }
633
634
635         /* rewire block input ... */
636         n = ARR_LEN(ins);
637         block = repr->block;
638         set_irn_in(block, n, ins);
639         DEL_ARR_F(ins);
640
641         /* ... existing Phis ... */
642         for (repr_phi = repr->phis; repr_phi != NULL; repr_phi = repr_phi->next) {
643                 set_irn_in(repr_phi->phi, n, repr_phi->ins);
644                 DEL_ARR_F(repr_phi->ins);
645         }
646
647         /* ... and all inputs by creating new Phis ... */
648         n = part->n_blocks;
649         for (repr_pair = repr->input_pairs; repr_pair != NULL; repr_pair = repr_pair->next) {
650                 ir_node *input = get_irn_n(repr_pair->irn, repr_pair->index);
651                 ir_mode *mode  = get_irn_mode(input);
652                 ir_node *phi   = new_r_Phi(current_ir_graph, block, n, repr_pair->ins, mode);
653
654                 set_irn_n(repr_pair->irn, repr_pair->index, phi);
655                 DEL_ARR_F(repr_pair->ins);
656         }
657
658         /* ... finally rewire the end block */
659         end_block = get_irg_end_block(irg);
660         n         = get_Block_n_cfgpreds(end_block);
661
662         ins = NEW_ARR_F(ir_node *, n);
663
664         for (i = j = 0; i < n; ++i) {
665                 ir_node *out = get_Block_cfgpred(end_block, i);
666
667                 list_for_each_entry(block_t, bl, &part->blocks, block_list) {
668                         node_t *root;
669
670                         for (root = bl->roots; root != NULL; root = root->next) {
671                                 if (root->node == out)
672                                         goto found;
673                         }
674                 }
675                 ins[j++] = out;
676 found:
677                         ;
678         }
679         set_irn_in(end_block, j, ins);
680         DEL_ARR_F(ins);
681
682         /* control flow changed */
683         set_irg_outs_inconsistent(irg);
684         set_irg_extblk_inconsistent(irg);
685         set_irg_doms_inconsistent(irg);
686         /* Hmm, only the root loop is inconsistent */
687         set_irg_loopinfo_inconsistent(irg);
688 }  /* apply */
689
690 /* Combines congruent end blocks into one. */
691 int melt_end_blocks(ir_graph *irg) {
692         ir_graph      *rem;
693         ir_node       *end;
694         environment_t env;
695         partition_t   *part;
696         int           i, res;
697
698         rem = current_ir_graph;
699         current_ir_graph = irg;
700
701         /* register a debug mask */
702         FIRM_DBG_REGISTER(dbg, "firm.opt.blocks");
703
704         DEBUG_ONLY(part_nr = 0);
705         DB((dbg, LEVEL_1, "Melting end blocks for %+F\n", irg));
706
707         ir_reserve_resources(irg, IR_RESOURCE_IRN_VISITED);
708         inc_irg_visited(irg);
709
710         obstack_init(&env.obst);
711         INIT_LIST_HEAD(&env.partitions);
712         INIT_LIST_HEAD(&env.ready);
713         env.opcode2id_map  = new_set(cmp_opcode, iro_Last * 4);
714
715         part = create_partition(&env);
716
717         /* collect all no-return blocks */
718         end = get_irg_end(irg);
719         for (i = get_End_n_keepalives(end) - 1; i >= 0; --i) {
720                 ir_node *ka    = get_End_keepalive(end, i);
721                 ir_node *block;
722                 block_t *bl;
723                 node_t  *node;
724
725                 if (! is_Call(ka))
726                         continue;
727                 mark_irn_visited(ka);
728
729                 /* found one */
730                 block = get_nodes_block(ka);
731                 bl    = create_block(block, &env);
732                 add_block(part, bl);
733                 node  = create_node(ka, &env);
734                 add_node(bl, node);
735
736                 node->next = bl->roots;
737                 bl->roots  = node;
738         }
739
740         /* collect normal blocks */
741         end = get_irg_end_block(irg);
742         for (i = get_Block_n_cfgpreds(end) - 1; i >= 0; --i) {
743                 ir_node *pred = get_Block_cfgpred(end, i);
744                 ir_node *block;
745                 block_t *bl;
746                 node_t  *node;
747
748                 mark_irn_visited(pred);
749
750                 block = get_nodes_block(pred);
751                 bl    = create_block(block, &env);
752                 add_block(part, bl);
753                 node  = create_node(pred, &env);
754                 add_node(bl, node);
755
756                 node->next = bl->roots;
757                 bl->roots  = node;
758         }
759
760         while (! list_empty(&env.partitions))
761                 propagate(&env);
762
763         res = !list_empty(&env.ready);
764
765         list_for_each_entry(partition_t, part, &env.ready, part_list) {
766                 dump_partition("Ready Partition", part);
767                 apply(irg, part);
768         }
769         ir_free_resources(irg, IR_RESOURCE_IRN_VISITED);
770         del_set(env.opcode2id_map);
771         obstack_free(&env.obst, NULL);
772         current_ir_graph = rem;
773
774         return res;
775 }  /* melt_end_blocks */