38b2418d0466d59c85411edff3d609d5e186df64
[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                                         add_node(bl, p_node);
470                                         /* do not threat Constants like live-ins */
471                                         if (! is_irn_constlike(irn)) {
472                                                 p_node->is_input = 1;
473                                                 if (! is_Phi(irn))
474                                                         add_pair(bl, irn, i, env);
475                                         }
476                                 } else if (! irn_visited_else_mark(pred)) {
477                                         /* not yet visited, ok */
478                                         p_node = create_node(pred, env);
479                                         add_node(bl, p_node);
480
481                                         if (is_Phi(pred)) {
482                                                 /* update the Phi list */
483                                                 add_phi(bl, pred, env);
484                                         }
485                                 }
486                         }
487                 } else {
488                         DB((dbg, LEVEL_3, "  propagate Input %+F\n", node->node));
489                 }
490
491                 /* Add bl to map[opcode(bl)]. */
492                 id          = opcode(node, env);
493                 entry       = listmap_find(&map, id);
494                 bl->next    = entry->list;
495                 entry->list = bl;
496         }
497
498         /* split out ready blocks */
499         if (n_ready > 0) {
500                 partition_t *Z;
501
502                 if (n_ready < part->n_blocks)
503                         Z = split(part, ready_blocks, env);
504                 else
505                         Z = part;
506                 list_del(&Z->part_list);
507
508                 if (Z->n_blocks > 1) {
509                         DB((dbg, LEVEL_1, "Partition %u is ready\n", Z->nr));
510                         list_add(&Z->part_list, &env->ready);
511                 } else {
512                         DB((dbg, LEVEL_1, "Partition %u contains only one block, killed\n", Z->nr));
513                 }
514         }
515
516         /* for all sets S except one in the range of map do */
517         for (iter = map.values; iter != NULL; iter = iter->next) {
518                 block_t *S;
519
520                 if (iter->next == NULL) {
521                         /* this is the last entry, ignore */
522                         break;
523                 }
524                 S = iter->list;
525
526                 /* Add SPLIT( X, S ) to P. */
527                 split(part, S, env);
528         }
529         listmap_term(&map);
530 }  /* propagate_blocks */
531
532 /**
533  * Propagate nodes on all wait queues.
534  *
535  * @param env    the environment
536  */
537 void propagate(environment_t *env) {
538         partition_t *part, *next;
539
540         list_for_each_entry_safe(partition_t, part, next, &env->partitions, part_list) {
541                 if (part->n_blocks < 2) {
542                         /* zero or one block left, kill this partition */
543                         list_del(&part->part_list);
544                         DB((dbg, LEVEL_1, "Partition %u contains less than 2 blocks, killed\n", part->nr));
545                 } else
546                         propagate_blocks(part, env);
547         }
548 }  /* propagate */
549
550 /**
551  * Apply analysis results by replacing all blocks of a partition
552  * by one representative.
553  *
554  * Route all inputs from all block of the partition to the one
555  * representative.
556  * Enhance all existing Phis by combining them.
557  * Create new Phis for all previous input nodes.
558  *
559  * @param part  the partition to process
560  */
561 static void apply(ir_graph *irg, partition_t *part) {
562         block_t *repr = list_entry(part->blocks.next, block_t, block_list);
563         block_t *bl;
564         ir_node *block, *end, *end_block;
565         ir_node **ins;
566         phi_t   *repr_phi, *phi;
567         pair_t  *repr_pair, *pair;
568         int     i, j, n, block_nr;
569
570         list_del(&repr->block_list);
571
572         /* prepare new in arrays for the block ... */
573         block = repr->block;
574         n     = get_Block_n_cfgpreds(block);
575         ins   = NEW_ARR_F(ir_node *, n);
576
577         for (i = 0; i < n; ++i) {
578                 ins[i] = get_Block_cfgpred(block, i);
579         }
580
581         /* ... for all existing Phis ... */
582         for (repr_phi = repr->phis; repr_phi != NULL; repr_phi = repr_phi->next) {
583                 repr_phi->ins = NEW_ARR_F(ir_node *, n);
584
585                 for (i = 0; i < n; ++i)
586                         repr_phi->ins[i] = get_Phi_pred(repr_phi->phi, i);
587         }
588
589         /* ... and all newly created Phis */
590         for (repr_pair = repr->input_pairs; repr_pair != NULL; repr_pair = repr_pair->next) {
591                 ir_node *input = get_irn_n(repr_pair->irn, repr_pair->index);
592
593                 repr_pair->ins = NEW_ARR_F(ir_node *, n);
594                 for (i = 0; i < n; ++i)
595                         repr_pair->ins[i] = input;
596         }
597
598         /* collect new in arrays */
599         end = get_irg_end(irg);
600         block_nr = 0;
601         list_for_each_entry(block_t, bl, &part->blocks, block_list) {
602                 block = bl->block;
603                 ++block_nr;
604
605                 /* first step: kill any keep-alive from this block */
606                 for (i = get_End_n_keepalives(end) - 1; i >= 0; --i) {
607                         ir_node *ka = get_End_keepalive(end, i);
608
609                         if (is_Block(ka)) {
610                                 if (ka == block)
611                                         remove_End_keepalive(end, ka);
612                         } else {
613                                 if (get_nodes_block(ka) == block)
614                                         remove_End_keepalive(end, ka);
615                         }
616                 }
617
618                 /* second step: update control flow */
619                 n = get_Block_n_cfgpreds(block);
620                 for (i = 0; i < n; ++i) {
621                         ir_node *pred = get_Block_cfgpred(block, i);
622                         ARR_APP1(ir_node *, ins, pred);
623                 }
624
625                 /* third step: update Phis */
626                 for (repr_phi = repr->phis, phi = bl->phis;
627                      repr_phi != NULL;
628                      repr_phi = repr_phi->next, phi = phi->next) {
629                         for (i = 0; i < n; ++i) {
630                                 ir_node *pred = get_Phi_pred(phi->phi, i);
631                                 ARR_APP1(ir_node *, repr_phi->ins, pred);
632                         }
633                 }
634
635                 /* fourth step: update inputs for new Phis */
636                 for (repr_pair = repr->input_pairs, pair = bl->input_pairs;
637                      repr_pair != NULL;
638                      repr_pair = repr_pair->next, pair = pair->next) {
639                         ir_node *input = get_irn_n(pair->irn, pair->index);
640
641                         for (i = 0; i < n; ++i)
642                                 ARR_APP1(ir_node *, repr_pair->ins, input);
643                 }
644         }
645
646
647         /* rewire block input ... */
648         n = ARR_LEN(ins);
649         block = repr->block;
650         set_irn_in(block, n, ins);
651         DEL_ARR_F(ins);
652
653         /* ... existing Phis ... */
654         for (repr_phi = repr->phis; repr_phi != NULL; repr_phi = repr_phi->next) {
655                 set_irn_in(repr_phi->phi, n, repr_phi->ins);
656                 DEL_ARR_F(repr_phi->ins);
657         }
658
659         /* ... and all inputs by creating new Phis ... */
660         for (repr_pair = repr->input_pairs; repr_pair != NULL; repr_pair = repr_pair->next) {
661                 ir_node *input = get_irn_n(repr_pair->irn, repr_pair->index);
662                 ir_mode *mode  = get_irn_mode(input);
663                 ir_node *phi   = new_r_Phi(current_ir_graph, block, n, repr_pair->ins, mode);
664
665                 set_irn_n(repr_pair->irn, repr_pair->index, phi);
666                 DEL_ARR_F(repr_pair->ins);
667         }
668
669         /* ... finally rewire the end block */
670         end_block = get_irg_end_block(irg);
671         n         = get_Block_n_cfgpreds(end_block);
672
673         ins = NEW_ARR_F(ir_node *, n);
674
675         for (i = j = 0; i < n; ++i) {
676                 ir_node *out = get_Block_cfgpred(end_block, i);
677
678                 list_for_each_entry(block_t, bl, &part->blocks, block_list) {
679                         node_t *root;
680
681                         for (root = bl->roots; root != NULL; root = root->next) {
682                                 if (root->node == out)
683                                         goto found;
684                         }
685                 }
686                 ins[j++] = out;
687 found:
688                         ;
689         }
690         set_irn_in(end_block, j, ins);
691         DEL_ARR_F(ins);
692
693         /* control flow changed */
694         set_irg_outs_inconsistent(irg);
695         set_irg_extblk_inconsistent(irg);
696         set_irg_doms_inconsistent(irg);
697         /* Hmm, only the root loop is inconsistent */
698         set_irg_loopinfo_inconsistent(irg);
699 }  /* apply */
700
701 /* Combines congruent end blocks into one. */
702 int melt_end_blocks(ir_graph *irg) {
703         ir_graph      *rem;
704         ir_node       *end;
705         environment_t env;
706         partition_t   *part;
707         int           i, res;
708
709         rem = current_ir_graph;
710         current_ir_graph = irg;
711
712         /* register a debug mask */
713         FIRM_DBG_REGISTER(dbg, "firm.opt.blocks");
714
715         DEBUG_ONLY(part_nr = 0);
716         DB((dbg, LEVEL_1, "Melting end blocks for %+F\n", irg));
717
718         ir_reserve_resources(irg, IR_RESOURCE_IRN_VISITED);
719         inc_irg_visited(irg);
720
721         obstack_init(&env.obst);
722         INIT_LIST_HEAD(&env.partitions);
723         INIT_LIST_HEAD(&env.ready);
724         env.opcode2id_map  = new_set(cmp_opcode, iro_Last * 4);
725
726         part = create_partition(&env);
727
728         /* collect all no-return blocks */
729         end = get_irg_end(irg);
730         for (i = get_End_n_keepalives(end) - 1; i >= 0; --i) {
731                 ir_node *ka    = get_End_keepalive(end, i);
732                 ir_node *block;
733                 block_t *bl;
734                 node_t  *node;
735
736                 if (! is_Call(ka))
737                         continue;
738                 mark_irn_visited(ka);
739
740                 /* found one */
741                 block = get_nodes_block(ka);
742                 bl    = create_block(block, &env);
743                 add_block(part, bl);
744                 node  = create_node(ka, &env);
745                 add_node(bl, node);
746
747                 node->next = bl->roots;
748                 bl->roots  = node;
749         }
750
751         /* collect normal blocks */
752         end = get_irg_end_block(irg);
753         for (i = get_Block_n_cfgpreds(end) - 1; i >= 0; --i) {
754                 ir_node *pred = get_Block_cfgpred(end, i);
755                 ir_node *block;
756                 block_t *bl;
757                 node_t  *node;
758
759                 mark_irn_visited(pred);
760
761                 block = get_nodes_block(pred);
762                 bl    = create_block(block, &env);
763                 add_block(part, bl);
764                 node  = create_node(pred, &env);
765                 add_node(bl, node);
766
767                 node->next = bl->roots;
768                 bl->roots  = node;
769         }
770
771         while (! list_empty(&env.partitions))
772                 propagate(&env);
773
774         res = !list_empty(&env.ready);
775
776         list_for_each_entry(partition_t, part, &env.ready, part_list) {
777                 dump_partition("Ready Partition", part);
778                 apply(irg, part);
779         }
780         ir_free_resources(irg, IR_RESOURCE_IRN_VISITED);
781         del_set(env.opcode2id_map);
782         obstack_free(&env.obst, NULL);
783         current_ir_graph = rem;
784
785         return res;
786 }  /* melt_end_blocks */