beifg: Simplify the implementation of be_ifg_foreach_node().
[libfirm] / ir / opt / opt_blocks.c
index 7b7c4a9..3d70682 100644 (file)
@@ -1,35 +1,20 @@
 /*
- * Copyright (C) 1995-2008 University of Karlsruhe.  All right reserved.
- *
  * This file is part of libFirm.
- *
- * This file may be distributed and/or modified under the terms of the
- * GNU General Public License version 2 as published by the Free Software
- * Foundation and appearing in the file LICENSE.GPL included in the
- * packaging of this file.
- *
- * Licensees holding valid libFirm Professional Edition licenses may use
- * this file in accordance with the libFirm Commercial License.
- * Agreement provided with the Software.
- *
- * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
- * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE.
+ * Copyright (C) 2012 University of Karlsruhe.
  */
 
 /**
  * @file
  * @brief   Combining congruent blocks
  * @author  Michael Beck
- * @version $Id$
  *
- * This phase find congruent blocks. Works currently for
- * predecessors of the end block only.
+ * This phase find congruent blocks.
  * Two block are congruent, if they contains only equal calculations.
  */
 #include "config.h"
-#include "ircons.h"
+
 #include "iroptimize.h"
+#include "ircons.h"
 #include "irgmod.h"
 #include "irgraph_t.h"
 #include "irnode_t.h"
 #include "trouts.h"
 #include "irgwalk.h"
 #include "set.h"
+#include "irpass.h"
 #include "debug.h"
+#include "util.h"
 
-/* define this for gneral block shaping */
+/* define this for general block shaping: congruent blocks
+   are found not only before the end block but anywhere in the graph */
 #define GENERAL_SHAPE
 
 typedef struct partition_t     partition_t;
@@ -55,15 +43,16 @@ typedef struct pred_t          pred_t;
 
 /** An opcode map key. */
 struct opcode_key_t {
-       ir_opcode   code;   /**< The Firm opcode. */
+       unsigned    code;   /**< The Firm opcode. */
        ir_mode     *mode;  /**< The mode of all nodes in the partition. */
        int         arity;  /**< The arity of this opcode (needed for Phi etc. */
        union {
                long            proj;   /**< For Proj nodes, its proj number */
                ir_entity       *ent;   /**< For Sel nodes, its entity */
-               tarval          *tv;    /**< For Const nodes, its tarval */
+               ir_tarval       *tv;    /**< For Const nodes, its tarval */
                symconst_symbol sym;    /**< For SymConst nodes, its symbol .*/
                void            *addr;  /**< Alias all addresses. */
+               int             intVal; /**< For Conv/Div nodes: strict/remainderless. */
        } u;
 };
 
@@ -109,7 +98,7 @@ struct environment_t {
        struct obstack  obst;           /** obstack for temporary data */
 };
 
-/** A node, input index pair. */
+/** A (node, input index) pair. */
 struct pair_t {
        pair_t  *next;    /**< Points to the next pair entry. */
        ir_node *irn;     /**< The IR-node. */
@@ -151,15 +140,15 @@ typedef struct listmap_t {
 DEBUG_ONLY(static firm_dbg_module_t *dbg;)
 
 /** Next partition number. */
-DEBUG_ONLY(static unsigned part_nr = 0);
+DEBUG_ONLY(static unsigned part_nr = 0;)
 
 #ifdef DEBUG_libfirm
 /**
  * Dump partition to output.
  */
-static void dump_partition(const char *msg, const partition_t *part) {
-       const block_t *block;
-       int           first = 1;
+static void dump_partition(const char *msg, const partition_t *part)
+{
+       int first = 1;
 
        DB((dbg, LEVEL_2, " %s part%u (%u blocks) {\n  ", msg, part->nr, part->n_blocks));
        list_for_each_entry(block_t, block, &part->blocks, block_list) {
@@ -167,12 +156,13 @@ static void dump_partition(const char *msg, const partition_t *part) {
                first = 0;
        }
        DB((dbg, LEVEL_2, "\n }\n"));
-}  /* dump_partition */
+}
 
 /**
  * Dumps a list.
  */
-static void dump_list(const char *msg, const block_t *block) {
+static void dump_list(const char *msg, const block_t *block)
+{
        const block_t *p;
        int           first = 1;
 
@@ -182,7 +172,7 @@ static void dump_list(const char *msg, const block_t *block) {
                first = 0;
        }
        DB((dbg, LEVEL_3, "\n  }\n"));
-}  /* do_dump_list */
+}
 #else
 #define dump_partition(msg, part)
 #define dump_list(msg, block)
@@ -191,32 +181,35 @@ static void dump_list(const char *msg, const block_t *block) {
 /**
  * Compare two pointer values of a listmap.
  */
-static int listmap_cmp_ptr(const void *elt, const void *key, size_t size) {
-       const listmap_entry_t *e1 = elt;
-       const listmap_entry_t *e2 = key;
+static int listmap_cmp_ptr(const void *elt, const void *key, size_t size)
+{
+       const listmap_entry_t *e1 = (const listmap_entry_t*)elt;
+       const listmap_entry_t *e2 = (const listmap_entry_t*)key;
 
        (void) size;
        return e1->id != e2->id;
-}  /* listmap_cmp_ptr */
+}
 
 /**
  * Initializes a listmap.
  *
  * @param map  the listmap
  */
-static void listmap_init(listmap_t *map) {
+static void listmap_init(listmap_t *map)
+{
        map->map    = new_set(listmap_cmp_ptr, 16);
        map->values = NULL;
-}  /* listmap_init */
+}
 
 /**
  * Terminates a listmap.
  *
  * @param map  the listmap
  */
-static void listmap_term(listmap_t *map) {
+static void listmap_term(listmap_t *map)
+{
        del_set(map->map);
-}  /* listmap_term */
+}
 
 /**
  * Return the associated listmap entry for a given id.
@@ -226,13 +219,14 @@ static void listmap_term(listmap_t *map) {
  *
  * @return the associated listmap entry for the given id
  */
-static listmap_entry_t *listmap_find(listmap_t *map, void *id) {
+static listmap_entry_t *listmap_find(listmap_t *map, void *id)
+{
        listmap_entry_t key, *entry;
 
        key.id   = id;
        key.list = NULL;
        key.next = NULL;
-       entry = set_insert(map->map, &key, sizeof(key), HASH_PTR(id));
+       entry    = set_insert(listmap_entry_t, map->map, &key, sizeof(key), hash_ptr(id));
 
        if (entry->list == NULL) {
                /* a new entry, put into the list */
@@ -240,7 +234,7 @@ static listmap_entry_t *listmap_find(listmap_t *map, void *id) {
                map->values = entry;
        }
        return entry;
-}  /* listmap_find */
+}
 
 /**
  * Calculate the hash value for an opcode map entry.
@@ -249,40 +243,44 @@ static listmap_entry_t *listmap_find(listmap_t *map, void *id) {
  *
  * @return a hash value for the given opcode map entry
  */
-static unsigned opcode_hash(const opcode_key_t *entry) {
-       return (entry->mode - (ir_mode *)0) * 9 + entry->code + entry->u.proj * 3 + HASH_PTR(entry->u.addr) + entry->arity;
-}  /* opcode_hash */
+static unsigned opcode_hash(const opcode_key_t *entry)
+{
+       /* assume long >= int */
+       return (unsigned)(PTR_TO_INT(entry->mode) * 9 + entry->code + entry->u.proj * 3 + hash_ptr(entry->u.addr) + entry->arity);
+}
 
 /**
  * Compare two entries in the opcode map.
  */
-static int cmp_opcode(const void *elt, const void *key, size_t size) {
-       const opcode_key_t *o1 = elt;
-       const opcode_key_t *o2 = key;
+static int cmp_opcode(const void *elt, const void *key, size_t size)
+{
+       const opcode_key_t *o1 = (opcode_key_t*)elt;
+       const opcode_key_t *o2 = (opcode_key_t*)key;
 
        (void) size;
        return o1->code != o2->code || o1->mode != o2->mode ||
               o1->arity != o2->arity ||
               o1->u.proj != o2->u.proj || o1->u.addr != o2->u.addr;
-}  /* cmp_opcode */
+}
 
 /**
  * Creates a new empty partition and put in on the
  * partitions list.
  *
- * @param meet_block  the control flow meet block of thi partition
+ * @param meet_block  the control flow meet block of this partition
  * @param env         the environment
  */
-static partition_t *create_partition(ir_node *meet_block, environment_t *env) {
-       partition_t *part = obstack_alloc(&env->obst, sizeof(*part));
+static partition_t *create_partition(ir_node *meet_block, environment_t *env)
+{
+       partition_t *part = OALLOC(&env->obst, partition_t);
 
        INIT_LIST_HEAD(&part->blocks);
        part->meet_block = meet_block;
        part->n_blocks   = 0;
-       DEBUG_ONLY(part->nr = part_nr++);
+       DEBUG_ONLY(part->nr = part_nr++;)
        list_add_tail(&part->part_list, &env->partitions);
        return part;
-}  /* create_partition */
+}
 
 /**
  * Allocate a new block in the given partition.
@@ -292,8 +290,9 @@ static partition_t *create_partition(ir_node *meet_block, environment_t *env) {
  * @param partition  the partition to add to
  * @param env        the environment
  */
-static block_t *create_block(ir_node *block, int meet_input, partition_t *partition, environment_t *env) {
-       block_t *bl = obstack_alloc(&env->obst, sizeof(*bl));
+static block_t *create_block(ir_node *block, int meet_input, partition_t *partition, environment_t *env)
+{
+       block_t *bl = OALLOC(&env->obst, block_t);
 
        set_irn_link(block, bl);
 
@@ -315,7 +314,7 @@ static block_t *create_block(ir_node *block, int meet_input, partition_t *partit
        env->all_blocks = bl;
 
        return bl;
-}  /* create_block */
+}
 
 /**
  * Allocate a new node and add it to a blocks wait queue.
@@ -324,8 +323,9 @@ static block_t *create_block(ir_node *block, int meet_input, partition_t *partit
  * @param block  the block to add to
  * @param env    the environment
  */
-static node_t *create_node(ir_node *irn, block_t *block, environment_t *env) {
-       node_t *node = obstack_alloc(&env->obst, sizeof(*node));
+static node_t *create_node(ir_node *irn, block_t *block, environment_t *env)
+{
+       node_t *node = OALLOC(&env->obst, node_t);
 
        node->node     = irn;
        node->is_input = 0;
@@ -333,7 +333,7 @@ static node_t *create_node(ir_node *irn, block_t *block, environment_t *env) {
        list_add_tail(&node->node_list, &block->nodes);
 
        return node;
-}  /* create_node */
+}
 
 /**
  * Add an input pair to a block.
@@ -343,8 +343,9 @@ static node_t *create_node(ir_node *irn, block_t *block, environment_t *env) {
  * @param idx    the index of the block input in node's predecessors
  * @param env    the environment
  */
-static void add_pair(block_t *block, ir_node *irn, int idx, environment_t *env) {
-       pair_t *pair = obstack_alloc(&env->obst, sizeof(*pair));
+static void add_pair(block_t *block, ir_node *irn, int idx, environment_t *env)
+{
+       pair_t *pair = OALLOC(&env->obst, pair_t);
 
        pair->next  = block->input_pairs;
        pair->irn   = irn;
@@ -352,7 +353,7 @@ static void add_pair(block_t *block, ir_node *irn, int idx, environment_t *env)
        pair->ins   = NULL;
 
        block->input_pairs = pair;
-}  /* add_pair */
+}
 
 /**
  * Add a Phi to a block.
@@ -361,20 +362,22 @@ static void add_pair(block_t *block, ir_node *irn, int idx, environment_t *env)
  * @param phi    the Phi node
  * @param env    the environment
  */
-static void add_phi(block_t *block, ir_node *phi, environment_t *env) {
-       phi_t *node = obstack_alloc(&env->obst, sizeof(*node));
+static void add_phi(block_t *block, ir_node *phi, environment_t *env)
+{
+       phi_t *node = OALLOC(&env->obst, phi_t);
 
        node->next = block->phis;
        node->phi  = phi;
        node->ins  = NULL;
 
        block->phis = node;
-}  /** add_phi */
+}
 
 /**
  * Creates an opcode from a node.
  */
-static opcode_key_t *opcode(const node_t *node, environment_t *env) {
+static opcode_key_t *opcode(const node_t *node, environment_t *env)
+{
        opcode_key_t key, *entry;
        ir_node      *irn = node->node;
 
@@ -404,13 +407,22 @@ static opcode_key_t *opcode(const node_t *node, environment_t *env) {
        case iro_Const:
                key.u.tv  = get_Const_tarval(irn);
                break;
+       case iro_Load:
+               key.mode = get_Load_mode(irn);
+               break;
+       case iro_Div:
+               key.u.intVal = get_Div_no_remainder(irn);
+               break;
+       case iro_Builtin:
+               key.u.intVal = get_Builtin_kind(irn);
+               break;
        default:
                break;
        }
 
-       entry = set_insert(env->opcode2id_map, &key, sizeof(key), opcode_hash(&key));
+       entry = set_insert(opcode_key_t, env->opcode2id_map, &key, sizeof(key), opcode_hash(&key));
        return entry;
-}  /* opcode */
+}
 
 /**
  * Split a partition by a local list.
@@ -421,7 +433,8 @@ static opcode_key_t *opcode(const node_t *node, environment_t *env) {
  *
  * @return  a new partition containing the nodes of g
  */
-static partition_t *split(partition_t *Z, block_t *g, environment_t *env) {
+static partition_t *split(partition_t *Z, block_t *g, environment_t *env)
+{
        partition_t *Z_prime;
        block_t     *block;
        unsigned    n = 0;
@@ -449,12 +462,13 @@ static partition_t *split(partition_t *Z, block_t *g, environment_t *env) {
        dump_partition("Now ", Z);
        dump_partition("Created new ", Z_prime);
        return Z_prime;
-}  /* split */
+}
 
 /**
- * Rteurn non-zero if pred should be tread as a input node.
+ * Return non-zero if pred should be tread as a input node.
  */
-static int is_input_node(ir_node *pred, ir_node *irn, int index) {
+static int is_input_node(ir_node *pred, ir_node *irn, int index)
+{
        /* for now, do NOT turn direct calls into indirect one */
        if (index != 1)
                return 1;
@@ -463,7 +477,7 @@ static int is_input_node(ir_node *pred, ir_node *irn, int index) {
        if (! is_Call(irn))
                return 1;
        return 0;
-}  /* is_input_node */
+}
 
 /**
  * Propagate nodes on all wait queues of the given partition.
@@ -471,10 +485,10 @@ static int is_input_node(ir_node *pred, ir_node *irn, int index) {
  * @param part  the partition
  * @param env   the environment
  */
-void propagate_blocks(partition_t *part, environment_t *env) {
+static void propagate_blocks(partition_t *part, environment_t *env)
+{
        block_t         *ready_blocks = NULL;
        unsigned        n_ready       = 0;
-       block_t         *bl, *next;
        listmap_t       map;
        listmap_entry_t *iter;
 
@@ -509,10 +523,9 @@ void propagate_blocks(partition_t *part, environment_t *env) {
                        for (i = get_irn_arity(irn) - 1; i >= 0; --i) {
                                ir_node *pred  = get_irn_n(irn, i);
                                ir_node *block = get_nodes_block(skip_Proj(pred));
-                               node_t *p_node;
 
                                if (block != bl->block) {
-                                       p_node = create_node(pred, bl, env);
+                                       node_t *p_node = create_node(pred, bl, env);
                                        if (is_input_node(pred, irn, i)) {
                                                /* is a block live input */
                                                p_node->is_input = 1;
@@ -524,7 +537,7 @@ void propagate_blocks(partition_t *part, environment_t *env) {
                                        }
                                } else if (! irn_visited_else_mark(pred)) {
                                        /* not yet visited, ok */
-                                       p_node = create_node(pred, bl, env);
+                                       create_node(pred, bl, env);
 
                                        if (is_Phi(pred)) {
                                                /* update the Phi list */
@@ -536,7 +549,7 @@ void propagate_blocks(partition_t *part, environment_t *env) {
                        DB((dbg, LEVEL_3, "  propagate Input %+F\n", node->node));
                }
 
-               /* Add bl to map[opcode(bl)]. */
+               /* Add bl to map[opcode(n)]. */
                id          = opcode(node, env);
                entry       = listmap_find(&map, id);
                bl->next    = entry->list;
@@ -575,16 +588,15 @@ void propagate_blocks(partition_t *part, environment_t *env) {
                split(part, S, env);
        }
        listmap_term(&map);
-}  /* propagate_blocks */
+}
 
 /**
  * Propagate nodes on all wait queues.
  *
  * @param env    the environment
  */
-void propagate(environment_t *env) {
-       partition_t *part, *next;
-
+static void propagate(environment_t *env)
+{
        list_for_each_entry_safe(partition_t, part, next, &env->partitions, part_list) {
                if (part->n_blocks < 2) {
                        /* zero or one block left, kill this partition */
@@ -593,12 +605,13 @@ void propagate(environment_t *env) {
                } else
                        propagate_blocks(part, env);
        }
-}  /* propagate */
+}
 
 /**
  * Map a block to the phi[block->input] live-trough.
  */
-static void *live_throughs(const block_t *bl, const ir_node *phi) {
+static void *live_throughs(const block_t *bl, const ir_node *phi)
+{
        ir_node *input = get_Phi_pred(phi, bl->meet_input);
 
        /* If this input is inside our block, this
@@ -608,7 +621,7 @@ static void *live_throughs(const block_t *bl, const ir_node *phi) {
        if (get_nodes_block(input) == bl->block)
                return NULL;
        return input;
-}  /* live_throughs */
+}
 
 /**
  * Split partition by live-outs and live-troughs.
@@ -616,9 +629,9 @@ static void *live_throughs(const block_t *bl, const ir_node *phi) {
  * @param part  the partition
  * @param env   the environment
  */
-void propagate_blocks_live_troughs(partition_t *part, environment_t *env) {
+static void propagate_blocks_live_troughs(partition_t *part, environment_t *env)
+{
        const ir_node   *meet_block = part->meet_block;
-       block_t         *bl, *next;
        listmap_t       map;
        listmap_entry_t *iter;
        const ir_node   *phi;
@@ -642,7 +655,7 @@ void propagate_blocks_live_troughs(partition_t *part, environment_t *env) {
                        listmap_entry_t *entry;
 
                        /* Add bl to map[live_trough(bl)]. */
-                       id          = live_throughs(bl, phi);
+                       id          = (opcode_key_t*)live_throughs(bl, phi);
                        entry       = listmap_find(&map, id);
                        bl->next    = entry->list;
                        entry->list = bl;
@@ -663,20 +676,19 @@ void propagate_blocks_live_troughs(partition_t *part, environment_t *env) {
                }
                listmap_term(&map);
        }
-}  /* propagate_blocks_live_troughs */
+}
 
 /**
  * Propagate live-troughs on all partitions on the partition list.
  *
  * @param env    the environment
  */
-void propagate_live_troughs(environment_t *env) {
-       partition_t *part, *next;
-
+static void propagate_live_troughs(environment_t *env)
+{
        list_for_each_entry_safe(partition_t, part, next, &env->partitions, part_list) {
                propagate_blocks_live_troughs(part, env);
        }
-}  /* propagate_live_troughs */
+}
 
 /**
  * Apply analysis results by replacing all blocks of a partition
@@ -689,14 +701,14 @@ void propagate_live_troughs(environment_t *env) {
  *
  * @param part  the partition to process
  */
-static void apply(ir_graph *irg, partition_t *part) {
+static void apply(ir_graph *irg, partition_t *part)
+{
        block_t *repr = list_entry(part->blocks.next, block_t, block_list);
-       block_t *bl;
        ir_node *block, *end, *meet_block, *p, *next;
        ir_node **ins, **phi_ins;
        phi_t   *repr_phi, *phi;
        pair_t  *repr_pair, *pair;
-       int     i, j, k, n, block_nr, n_phis;
+       int     i, j, k, n, n_phis;
 
        list_del(&repr->block_list);
 
@@ -730,10 +742,8 @@ static void apply(ir_graph *irg, partition_t *part) {
 
        /* collect new in arrays */
        end = get_irg_end(irg);
-       block_nr = 0;
        list_for_each_entry(block_t, bl, &part->blocks, block_list) {
                block = bl->block;
-               ++block_nr;
 
                DB((dbg, LEVEL_1, "%+F, ", block));
 
@@ -812,7 +822,7 @@ static void apply(ir_graph *irg, partition_t *part) {
                if (is_op_forking(cfop)) {
                        /* a critical edge */
                        ir_node *block = new_r_Block(irg, 1, &ins[i]);
-                       ir_node *jmp   = new_r_Jmp(irg, block);
+                       ir_node *jmp   = new_r_Jmp(block);
                        ins[i] = jmp;
                }
        }
@@ -831,7 +841,7 @@ static void apply(ir_graph *irg, partition_t *part) {
        for (repr_pair = repr->input_pairs; repr_pair != NULL; repr_pair = repr_pair->next) {
                ir_node *input = get_irn_n(repr_pair->irn, repr_pair->index);
                ir_mode *mode  = get_irn_mode(input);
-               ir_node *phi   = new_r_Phi(current_ir_graph, block, n, repr_pair->ins, mode);
+               ir_node *phi   = new_r_Phi(block, n, repr_pair->ins, mode);
 
                set_irn_n(repr_pair->irn, repr_pair->index, phi);
                DEL_ARR_F(repr_pair->ins);
@@ -893,7 +903,7 @@ continue_outer:
        /* fix inputs of the meet block */
        set_irn_in(meet_block, j, ins);
        DEL_ARR_F(ins);
-}  /* apply */
+}
 
 /**
  * Create a partition for a the end block.
@@ -901,7 +911,8 @@ continue_outer:
  * @param end_block  the end block
  * @param env        the environment
  */
-static void partition_for_end_block(ir_node *end_block, environment_t *env) {
+static void partition_for_end_block(ir_node *end_block, environment_t *env)
+{
        partition_t *part = create_partition(end_block, env);
        ir_node     *end;
        int         i;
@@ -923,7 +934,7 @@ static void partition_for_end_block(ir_node *end_block, environment_t *env) {
        }
 
        /* collect all no-return blocks */
-       end = get_irg_end(current_ir_graph);
+       end = get_irg_end(get_irn_irg(end_block));
        for (i = get_End_n_keepalives(end) - 1; i >= 0; --i) {
                ir_node *ka    = get_End_keepalive(end, i);
                ir_node *block;
@@ -943,7 +954,7 @@ static void partition_for_end_block(ir_node *end_block, environment_t *env) {
        }
 
        dump_partition("Created", part);
-}  /* partition_for_end_block */
+}
 
 #ifdef GENERAL_SHAPE
 /**
@@ -954,7 +965,8 @@ static void partition_for_end_block(ir_node *end_block, environment_t *env) {
  * @param n_preds  number of elements in preds
  * @param env      the environment
  */
-static void partition_for_block(ir_node *block, pred_t preds[], int n_preds, environment_t *env) {
+static void partition_for_block(ir_node *block, pred_t preds[], int n_preds, environment_t *env)
+{
        partition_t *part = create_partition(block, env);
        int         i;
 
@@ -974,25 +986,27 @@ static void partition_for_block(ir_node *block, pred_t preds[], int n_preds, env
        }
 
        dump_partition("Created", part);
-}  /* partition_for_block */
+}
 
 /**
  * Walker: clear the links of all block phi lists and normal
  * links.
  */
-static void clear_phi_links(ir_node *irn, void *env) {
+static void clear_phi_links(ir_node *irn, void *env)
+{
        (void) env;
        if (is_Block(irn)) {
                set_Block_phis(irn, NULL);
                set_irn_link(irn, NULL);
        }
-}  /* clear_phi_links */
+}
 
 /**
  * Walker, detect live-out nodes.
  */
-static void find_liveouts(ir_node *irn, void *ctx) {
-       environment_t *env        = ctx;
+static void find_liveouts(ir_node *irn, void *ctx)
+{
+       environment_t *env        = (environment_t*)ctx;
        ir_node       **live_outs = env->live_outs;
        ir_node       *this_block;
        int           i;
@@ -1028,17 +1042,18 @@ static void find_liveouts(ir_node *irn, void *ctx) {
                        live_outs[idx] = pred_block;
                }
        }
-}  /* find_liveouts */
+}
 
 /**
- * Check if the current block is the meet block of its predecessors.
+ * Check if the current block is the meet block of its predecessors.
  */
-static void check_for_cf_meet(ir_node *block, void *ctx) {
-       environment_t *env = ctx;
+static void check_for_cf_meet(ir_node *block, void *ctx)
+{
+       environment_t *env = (environment_t*)ctx;
        int           i, k, n;
        pred_t        *preds;
 
-       if (block == get_irg_end_block(current_ir_graph)) {
+       if (block == get_irg_end_block(get_irn_irg(block))) {
                /* always create a partition for the end block */
                partition_for_end_block(block, env);
                return;
@@ -1054,32 +1069,31 @@ static void check_for_cf_meet(ir_node *block, void *ctx) {
        k = 0;
        for (i = n - 1; i >= 0; --i) {
                ir_node *pred = get_Block_cfgpred(block, i);
-               ir_node *pred_block;
 
                /* pred must be a direct jump to us */
                if (! is_Jmp(pred) && ! is_Raise(pred) && !is_Bad(pred))
                        continue;
 
-               pred_block = get_nodes_block(skip_Proj(pred));
-
                preds[k].pred  = pred;
                preds[k].index = i;
+               ++k;
        }
 
        if (k > 1)
                partition_for_block(block, preds, k, env);
-}  /* check_for_cf_meet */
+}
 
 /**
  * Compare two nodes for root ordering.
  */
-static int cmp_nodes(const void *a, const void *b) {
-       ir_node *const *pa     = a;
-       ir_node *const *pb     = b;
+static int cmp_nodes(const void *a, const void *b)
+{
+       const ir_node *const *pa = (const ir_node*const*)a;
+       const ir_node *const *pb = (const ir_node*const*)b;
        const ir_node  *irn_a  = *pa;
        const ir_node  *irn_b  = *pb;
-       ir_opcode      code_a  = get_irn_opcode(irn_a);
-       ir_opcode      code_b  = get_irn_opcode(irn_b);
+       unsigned       code_a  = get_irn_opcode(irn_a);
+       unsigned       code_b  = get_irn_opcode(irn_b);
        ir_mode        *mode_a, *mode_b;
        unsigned       idx_a, idx_b;
 
@@ -1099,12 +1113,13 @@ static int cmp_nodes(const void *a, const void *b) {
        idx_b = get_irn_idx(irn_b);
 
        return (idx_a > idx_b) - (idx_a < idx_b);
-}  /* cmp_nodes */
+}
 
 /**
  * Add the roots to all blocks.
  */
-static void add_roots(ir_graph *irg, environment_t *env) {
+static void add_roots(ir_graph *irg, environment_t *env)
+{
        unsigned idx, n      = get_irg_last_idx(irg);
        ir_node  **live_outs = env->live_outs;
        block_t  *bl;
@@ -1126,16 +1141,14 @@ static void add_roots(ir_graph *irg, environment_t *env) {
        }
        /*
         * Now sort the roots to normalize them as good as possible.
-     * Else, we will split identical blocks if we start which different roots
+     * Else, we will split identical blocks if we start which different roots.
         */
        for (bl = env->all_blocks; bl != NULL; bl = bl->all_next) {
-               int i, n = ARR_LEN(bl->roots);
+               size_t i, n = ARR_LEN(bl->roots);
 
-#if 1
                /* TODO: is this really needed? The roots are already in
                   idx-order by construction, which might be good enough. */
                qsort(bl->roots, n, sizeof(bl->roots[0]), cmp_nodes);
-#endif
 
                DB((dbg, LEVEL_2, " Adding Roots for block %+F\n  ", bl->block));
                /* ok, add them sorted */
@@ -1147,23 +1160,20 @@ static void add_roots(ir_graph *irg, environment_t *env) {
                DEL_ARR_F(bl->roots);
                bl->roots = NULL;
        }
-}  /* add_roots */
+}
 #endif /* GENERAL_SHAPE */
 
 /* Combines congruent end blocks into one. */
-int shape_blocks(ir_graph *irg) {
-       ir_graph      *rem;
+void shape_blocks(ir_graph *irg)
+{
        environment_t env;
-       partition_t   *part;
+       block_t       *bl;
        int           res, n;
 
-       rem = current_ir_graph;
-       current_ir_graph = irg;
-
        /* register a debug mask */
        FIRM_DBG_REGISTER(dbg, "firm.opt.blocks");
 
-       DEBUG_ONLY(part_nr = 0);
+       DEBUG_ONLY(part_nr = 0;)
        DB((dbg, LEVEL_1, "Shaping blocks for %+F\n", irg));
 
        /* works better, when returns are placed at the end of the blocks */
@@ -1175,8 +1185,7 @@ int shape_blocks(ir_graph *irg) {
        env.opcode2id_map  = new_set(cmp_opcode, iro_Last * 4);
 
        n             = get_irg_last_idx(irg);
-       env.live_outs = NEW_ARR_F(ir_node *, n);
-       memset(env.live_outs, 0, sizeof(*env.live_outs) * n);
+       env.live_outs = NEW_ARR_FZ(ir_node*, n);
 
        env.all_blocks = NULL;
 
@@ -1221,21 +1230,19 @@ int shape_blocks(ir_graph *irg) {
 
        if (res) {
                /* control flow changed */
-               set_irg_outs_inconsistent(irg);
-               set_irg_extblk_inconsistent(irg);
-               set_irg_doms_inconsistent(irg);
-               set_irg_loopinfo_inconsistent(irg);
-
-               /* Calls might be removed. */
-               set_trouts_inconsistent();
+               clear_irg_properties(irg, IR_GRAPH_PROPERTY_CONSISTENT_DOMINANCE);
+       }
 
-       //      dump_ir_block_graph(irg, "-after");
+       for (bl = env.all_blocks; bl != NULL; bl = bl->all_next) {
+               DEL_ARR_F(bl->roots);
        }
 
        DEL_ARR_F(env.live_outs);
        del_set(env.opcode2id_map);
        obstack_free(&env.obst, NULL);
-       current_ir_graph = rem;
+}
 
-       return res;
-}  /* shape_blocks */
+ir_graph_pass_t *shape_blocks_pass(const char *name)
+{
+       return def_graph_pass(name ? name : "shape_blocks", shape_blocks);
+}