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