2 * Copyright (C) 1995-2008 University of Karlsruhe. All right reserved.
4 * This file is part of libFirm.
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.
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.
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
22 * @brief Combining congruent blocks
23 * @author Michael Beck
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.
32 #include "iroptimize.h"
34 #include "irgraph_t.h"
43 /* define this for gneral block shaping (buggy yet) */
46 typedef struct partition_t partition_t;
47 typedef struct block_t block_t;
48 typedef struct node_t node_t;
49 typedef struct pair_t pair_t;
50 typedef struct phi_t phi_t;
51 typedef struct opcode_key_t opcode_key_t;
52 typedef struct listmap_entry_t listmap_entry_t;
53 typedef struct environment_t environment_t;
55 /** An opcode map key. */
57 ir_opcode code; /**< The Firm opcode. */
58 ir_mode *mode; /**< The mode of all nodes in the partition. */
59 int arity; /**< The arity of this opcode (needed for Phi etc. */
61 long proj; /**< For Proj nodes, its proj number */
62 ir_entity *ent; /**< For Sel Nodes, its entity */
66 /** A partition contains all congruent blocks. */
68 list_head part_list; /**< Double linked list of partitions. */
69 list_head blocks; /**< List of blocks in this partition. */
70 unsigned n_blocks; /**< Number of block in this partition. */
71 ir_node *meet_block; /**< The control flow meet block of this partition. */
73 unsigned nr; /**< For debugging: number of this partition. */
79 list_head block_list; /**< Double linked list of block inside a partition. */
80 list_head nodes; /**< Wait-queue of nodes that must be checked for congruence. */
81 block_t *next; /**< Next block of a split list. */
82 ir_node *block; /**< Pointer to the associated IR-node block. */
83 ir_node **roots; /**< An array of all root nodes. */
84 node_t *cf_root; /**< The control flow root node of this block. */
85 pair_t *input_pairs; /**< The list of inputs to this block. */
86 phi_t *phis; /**< The list of Phis in this block. */
87 block_t *all_next; /**< links all craeted blocks. */
92 list_head node_list; /**< Double linked list of block inside a partition. */
93 ir_node *node; /**< Pointer to the associated IR-node or NULL for block inputs. */
94 char is_input; /**< Set if this node is an input from other block. */
97 /** The environment. */
98 struct environment_t {
99 list_head partitions; /**< list of partitions. */
100 list_head ready; /**< list of ready partitions. */
101 set *opcode2id_map; /**< The opcodeMode->id map. */
102 ir_node **live_outs; /**< Live out only nodes. */
103 block_t *all_blocks; /**< List of all created blocks. */
104 struct obstack obst; /** obstack for temporary data */
107 /** A node, input index pair. */
109 pair_t *next; /**< Points to the next pair entry. */
110 ir_node *irn; /**< The IR-node. */
111 int index; /**< An input index. */
112 ir_node **ins; /**< A new in array once allocated. */
115 /** A Phi, inputs pair. */
117 phi_t *next; /**< Points to the next Phi pair entry. */
118 ir_node *phi; /**< The Phi node. */
119 ir_node **ins; /**< A new in array once allocated. */
123 * An entry in the list_map.
125 struct listmap_entry_t {
126 void *id; /**< The id. */
127 block_t *list; /**< The associated list for this id. */
128 listmap_entry_t *next; /**< Link to the next entry in the map. */
131 /** We must map id's to lists. */
132 typedef struct listmap_t {
133 set *map; /**< Map id's to listmap_entry_t's */
134 listmap_entry_t *values; /**< List of all values in the map. */
137 #define get_Block_entry(block) ((block_t *)get_irn_link(block))
139 /** The debug module handle. */
140 DEBUG_ONLY(static firm_dbg_module_t *dbg;)
142 /** Next partition number. */
143 DEBUG_ONLY(static unsigned part_nr = 0);
147 * Dump partition to output.
149 static void dump_partition(const char *msg, const partition_t *part) {
150 const block_t *block;
153 DB((dbg, LEVEL_2, " %s part%u (%u blocks) {\n ", msg, part->nr, part->n_blocks));
154 list_for_each_entry(block_t, block, &part->blocks, block_list) {
155 DB((dbg, LEVEL_2, "%s%+F", first ? "" : ", ", block->block));
158 DB((dbg, LEVEL_2, "\n }\n"));
159 } /* dump_partition */
164 static void dump_list(const char *msg, const block_t *block) {
168 DB((dbg, LEVEL_3, " %s = {\n ", msg));
169 for (p = block; p != NULL; p = p->next) {
170 DB((dbg, LEVEL_3, "%s%+F", first ? "" : ", ", p->block));
173 DB((dbg, LEVEL_3, "\n }\n"));
176 #define dump_partition(msg, part)
177 #define dump_list(msg, block)
181 * Compare two pointer values of a listmap.
183 static int listmap_cmp_ptr(const void *elt, const void *key, size_t size) {
184 const listmap_entry_t *e1 = elt;
185 const listmap_entry_t *e2 = key;
188 return e1->id != e2->id;
189 } /* listmap_cmp_ptr */
192 * Initializes a listmap.
194 * @param map the listmap
196 static void listmap_init(listmap_t *map) {
197 map->map = new_set(listmap_cmp_ptr, 16);
202 * Terminates a listmap.
204 * @param map the listmap
206 static void listmap_term(listmap_t *map) {
211 * Return the associated listmap entry for a given id.
213 * @param map the listmap
214 * @param id the id to search for
216 * @return the associated listmap entry for the given id
218 static listmap_entry_t *listmap_find(listmap_t *map, void *id) {
219 listmap_entry_t key, *entry;
224 entry = set_insert(map->map, &key, sizeof(key), HASH_PTR(id));
226 if (entry->list == NULL) {
227 /* a new entry, put into the list */
228 entry->next = map->values;
235 * Calculate the hash value for an opcode map entry.
237 * @param entry an opcode map entry
239 * @return a hash value for the given opcode map entry
241 static unsigned opcode_hash(const opcode_key_t *entry) {
242 return (entry->mode - (ir_mode *)0) * 9 + entry->code + entry->u.proj * 3 + HASH_PTR(entry->u.ent) + entry->arity;
246 * Compare two entries in the opcode map.
248 static int cmp_opcode(const void *elt, const void *key, size_t size) {
249 const opcode_key_t *o1 = elt;
250 const opcode_key_t *o2 = key;
253 return o1->code != o2->code || o1->mode != o2->mode ||
254 o1->arity != o2->arity ||
255 o1->u.proj != o2->u.proj || o1->u.ent != o2->u.ent;
259 * Creates a new empty partition and put in on the
262 * @param meet_block the control flow meet block of thi partition
263 * @param env the environment
265 static partition_t *create_partition(ir_node *meet_block, environment_t *env) {
266 partition_t *part = obstack_alloc(&env->obst, sizeof(*part));
268 INIT_LIST_HEAD(&part->blocks);
269 part->meet_block = meet_block;
271 DEBUG_ONLY(part->nr = part_nr++);
272 list_add_tail(&part->part_list, &env->partitions);
274 } /* create_partition */
277 * Allocate a new block in the given partition.
279 * @param block the IR-node
280 * @param partition the partition to add to
281 * @param env the environment
283 static block_t *create_block(ir_node *block, partition_t *partition, environment_t *env) {
284 block_t *bl = obstack_alloc(&env->obst, sizeof(*bl));
286 set_irn_link(block, bl);
288 INIT_LIST_HEAD(&bl->nodes);
291 bl->roots = NEW_ARR_F(ir_node *, 0);
293 bl->input_pairs = NULL;
296 /* put it into the list of partition blocks */
297 list_add_tail(&bl->block_list, &partition->blocks);
298 ++partition->n_blocks;
300 /* put in into the list of all blocks */
301 bl->all_next = env->all_blocks;
302 env->all_blocks = bl;
308 * Allocate a new node and add it to a blocks wait queue.
310 * @param irn the IR-node
311 * @param block the block to add to
312 * @param env the environment
314 static node_t *create_node(ir_node *irn, block_t *block, environment_t *env) {
315 node_t *node = obstack_alloc(&env->obst, sizeof(*node));
320 list_add_tail(&node->node_list, &block->nodes);
326 * Add an input pair to a block.
328 * @param block the block
329 * @param irn the IR-node that has an block input
330 * @param idx the index of the block input in node's predecessors
331 * @param env the environment
333 static void add_pair(block_t *block, ir_node *irn, int idx, environment_t *env) {
334 pair_t *pair = obstack_alloc(&env->obst, sizeof(*pair));
336 pair->next = block->input_pairs;
341 block->input_pairs = pair;
345 * Add a Phi to a block.
347 * @param block the block
348 * @param phi the Phi node
349 * @param env the environment
351 static void add_phi(block_t *block, ir_node *phi, environment_t *env) {
352 phi_t *node = obstack_alloc(&env->obst, sizeof(*node));
354 node->next = block->phis;
362 * Creates an opcode from a node.
364 static opcode_key_t *opcode(const node_t *node, environment_t *env) {
365 opcode_key_t key, *entry;
366 ir_node *irn = node->node;
368 if (node->is_input) {
369 /* Node: as Block nodes are never propagated, it is safe to
370 use its code for "input" node */
371 key.code = iro_Block;
374 key.code = get_irn_opcode(irn);
375 key.arity = get_irn_arity(irn);
377 key.mode = get_irn_mode(node->node);
383 key.u.proj = get_Proj_proj(irn);
386 key.u.ent = get_Sel_entity(irn);
392 entry = set_insert(env->opcode2id_map, &key, sizeof(key), opcode_hash(&key));
397 * Split a partition by a local list.
399 * @param Z partition to split
400 * @param g a (non-empty) block list
401 * @param env the environment
403 * @return a new partition containing the nodes of g
405 static partition_t *split(partition_t *Z, block_t *g, environment_t *env) {
406 partition_t *Z_prime;
410 dump_partition("Splitting ", Z);
411 dump_list("by list ", g);
415 /* Remove g from Z. */
416 for (block = g; block != NULL; block = block->next) {
417 list_del(&block->block_list);
420 assert(n < Z->n_blocks);
423 /* Move g to a new partition, Z'. */
424 Z_prime = create_partition(Z->meet_block, env);
425 for (block = g; block != NULL; block = block->next) {
426 list_add_tail(&block->block_list, &Z_prime->blocks);
428 Z_prime->n_blocks = n;
430 dump_partition("Now ", Z);
431 dump_partition("Created new ", Z_prime);
436 * Propagate nodes on all wait queues of the given partition.
438 * @param part the partition
439 * @param env the environment
441 void propagate_blocks(partition_t *part, environment_t *env) {
442 block_t *ready_blocks = NULL;
443 unsigned n_ready = 0;
446 listmap_entry_t *iter;
448 DB((dbg, LEVEL_2, " Propagate blocks on part%u\n", part->nr));
450 /* Let map be an empty mapping from the range of Opcodes to (local) list of Nodes. */
452 list_for_each_entry_safe(block_t, bl, next, &part->blocks, block_list) {
454 listmap_entry_t *entry;
457 if (list_empty(&bl->nodes)) {
458 bl->next = ready_blocks;
461 DB((dbg, LEVEL_2, " Block %+F completely processed\n", bl->block));
465 /* get the first node from the wait queue */
466 node = list_entry(bl->nodes.next, node_t, node_list);
467 list_del(&node->node_list);
469 /* put all not-visited predecessors to the wait queue */
470 if (! node->is_input) {
471 ir_node *irn = node->node;
474 DB((dbg, LEVEL_3, " propagate %+F\n", irn));
475 ir_normalize_node(node->node);
476 for (i = get_irn_arity(irn) - 1; i >= 0; --i) {
477 ir_node *pred = get_irn_n(irn, i);
478 ir_node *block = get_nodes_block(skip_Proj(pred));
481 if (block != bl->block) {
482 p_node = create_node(pred, bl, env);
483 /* do not threat Constants like live-ins */
484 if (! is_irn_constlike(pred)) {
485 p_node->is_input = 1;
487 add_pair(bl, irn, i, env);
489 } else if (! irn_visited_else_mark(pred)) {
490 /* not yet visited, ok */
491 p_node = create_node(pred, bl, env);
494 /* update the Phi list */
495 add_phi(bl, pred, env);
500 DB((dbg, LEVEL_3, " propagate Input %+F\n", node->node));
503 /* Add bl to map[opcode(bl)]. */
504 id = opcode(node, env);
505 entry = listmap_find(&map, id);
506 bl->next = entry->list;
510 /* split out ready blocks */
514 if (n_ready < part->n_blocks)
515 Z = split(part, ready_blocks, env);
518 list_del(&Z->part_list);
520 if (Z->n_blocks > 1) {
521 DB((dbg, LEVEL_2, " Partition %u is ready\n", Z->nr));
522 list_add(&Z->part_list, &env->ready);
524 DB((dbg, LEVEL_2, " Partition %u contains only one block, killed\n", Z->nr));
528 /* for all sets S except one in the range of map do */
529 for (iter = map.values; iter != NULL; iter = iter->next) {
532 if (iter->next == NULL) {
533 /* this is the last entry, ignore */
538 /* Add SPLIT( X, S ) to P. */
542 } /* propagate_blocks */
545 * Propagate nodes on all wait queues.
547 * @param env the environment
549 void propagate(environment_t *env) {
550 partition_t *part, *next;
552 list_for_each_entry_safe(partition_t, part, next, &env->partitions, part_list) {
553 if (part->n_blocks < 2) {
554 /* zero or one block left, kill this partition */
555 list_del(&part->part_list);
556 DB((dbg, LEVEL_2, " Partition %u contains less than 2 blocks, killed\n", part->nr));
558 propagate_blocks(part, env);
563 * Apply analysis results by replacing all blocks of a partition
564 * by one representative.
566 * Route all inputs from all block of the partition to the one
568 * Enhance all existing Phis by combining them.
569 * Create new Phis for all previous input nodes.
571 * @param part the partition to process
573 static void apply(ir_graph *irg, partition_t *part) {
574 block_t *repr = list_entry(part->blocks.next, block_t, block_list);
576 ir_node *block, *end, *meet_block, *p, *next;
577 ir_node **ins, **phi_ins;
578 phi_t *repr_phi, *phi;
579 pair_t *repr_pair, *pair;
580 int i, j, k, n, block_nr, n_phis;
582 list_del(&repr->block_list);
584 /* prepare new in arrays for the block ... */
586 n = get_Block_n_cfgpreds(block);
587 ins = NEW_ARR_F(ir_node *, n);
589 for (i = 0; i < n; ++i) {
590 ins[i] = get_Block_cfgpred(block, i);
593 /* ... for all existing Phis ... */
594 for (repr_phi = repr->phis; repr_phi != NULL; repr_phi = repr_phi->next) {
595 repr_phi->ins = NEW_ARR_F(ir_node *, n);
597 for (i = 0; i < n; ++i)
598 repr_phi->ins[i] = get_Phi_pred(repr_phi->phi, i);
601 /* ... and all newly created Phis */
602 for (repr_pair = repr->input_pairs; repr_pair != NULL; repr_pair = repr_pair->next) {
603 ir_node *input = get_irn_n(repr_pair->irn, repr_pair->index);
605 repr_pair->ins = NEW_ARR_F(ir_node *, n);
606 for (i = 0; i < n; ++i)
607 repr_pair->ins[i] = input;
610 DB((dbg, LEVEL_1, "Replacing "));
612 /* collect new in arrays */
613 end = get_irg_end(irg);
615 list_for_each_entry(block_t, bl, &part->blocks, block_list) {
619 DB((dbg, LEVEL_1, "%+F, ", block));
621 /* first step: kill any keep-alive from this block */
622 for (i = get_End_n_keepalives(end) - 1; i >= 0; --i) {
623 ir_node *ka = get_End_keepalive(end, i);
627 remove_End_keepalive(end, ka);
629 if (get_nodes_block(ka) == block)
630 remove_End_keepalive(end, ka);
634 /* second step: update control flow */
635 n = get_Block_n_cfgpreds(block);
636 for (i = 0; i < n; ++i) {
637 ir_node *pred = get_Block_cfgpred(block, i);
638 ARR_APP1(ir_node *, ins, pred);
641 /* third step: update Phis */
642 for (repr_phi = repr->phis, phi = bl->phis;
644 repr_phi = repr_phi->next, phi = phi->next) {
645 for (i = 0; i < n; ++i) {
646 ir_node *pred = get_Phi_pred(phi->phi, i);
647 ARR_APP1(ir_node *, repr_phi->ins, pred);
651 /* fourth step: update inputs for new Phis */
652 for (repr_pair = repr->input_pairs, pair = bl->input_pairs;
654 repr_pair = repr_pair->next, pair = pair->next) {
655 ir_node *input = get_irn_n(pair->irn, pair->index);
657 for (i = 0; i < n; ++i)
658 ARR_APP1(ir_node *, repr_pair->ins, input);
662 DB((dbg, LEVEL_1, "by %+F\n", repr->block));
664 /* rewire block input ... */
668 * Some problem here. For:
669 * if (x) y = 1; else y = 2;
671 * the following code is constructed:
673 * b0: if (x) goto b1; else goto b1;
676 * However, both predecessors of b1 are b0, making the Phi
679 * We solve this by fixing critical edges.
681 for (i = 0; i < n; ++i) {
682 ir_node *pred = ins[i];
688 cfop = get_irn_op(skip_Proj(pred));
689 if (is_op_fragile(cfop)) {
690 /* ignore exception flow */
693 if (is_op_forking(cfop)) {
694 /* a critical edge */
695 ir_node *block = new_r_Block(irg, 1, &ins[i]);
696 ir_node *jmp = new_r_Jmp(irg, block);
702 set_irn_in(block, n, ins);
705 /* ... existing Phis ... */
706 for (repr_phi = repr->phis; repr_phi != NULL; repr_phi = repr_phi->next) {
707 set_irn_in(repr_phi->phi, n, repr_phi->ins);
708 DEL_ARR_F(repr_phi->ins);
711 /* ... and all inputs by creating new Phis ... */
712 for (repr_pair = repr->input_pairs; repr_pair != NULL; repr_pair = repr_pair->next) {
713 ir_node *input = get_irn_n(repr_pair->irn, repr_pair->index);
714 ir_mode *mode = get_irn_mode(input);
715 ir_node *phi = new_r_Phi(current_ir_graph, block, n, repr_pair->ins, mode);
717 set_irn_n(repr_pair->irn, repr_pair->index, phi);
718 DEL_ARR_F(repr_pair->ins);
720 /* might be optimized away */
722 add_Block_phi(block, phi);
725 /* ... finally rewire the meet block and fix its Phi-nodes */
726 meet_block = part->meet_block;
727 n = get_Block_n_cfgpreds(meet_block);
729 ins = NEW_ARR_F(ir_node *, n);
732 for (p = get_Block_phis(meet_block); p != NULL; p = get_Phi_next(p)) {
736 phi_ins = NEW_ARR_F(ir_node *, n_phis * n);
738 for (i = j = 0; i < n; ++i) {
739 ir_node *pred = get_Block_cfgpred(meet_block, i);
741 list_for_each_entry(block_t, bl, &part->blocks, block_list) {
742 if (bl->cf_root->node == pred)
747 for (k = 0, p = get_Block_phis(meet_block); p != NULL; p = get_Phi_next(p), ++k) {
748 phi_ins[k * n + j] = get_Phi_pred(p, i);
758 for (k = 0, p = get_Block_phis(meet_block); p != NULL; p = next, ++k) {
759 next = get_Phi_next(p);
761 exchange(p, phi_ins[k * n]);
763 /* all Phis killed */
764 set_Block_phis(meet_block, NULL);
766 for (k = 0, p = get_Block_phis(meet_block); p != NULL; p = next, ++k) {
767 next = get_Phi_next(p);
769 set_irn_in(p, j, &phi_ins[k * n]);
774 /* fix inputs of the meet block */
775 set_irn_in(meet_block, j, ins);
780 * Create a partition for a the end block.
782 * @param end_block the end block
783 * @param env the environment
785 static void partition_for_end_block(ir_node *end_block, environment_t *env) {
786 partition_t *part = create_partition(end_block, env);
790 /* collect normal blocks */
791 for (i = get_Block_n_cfgpreds(end_block) - 1; i >= 0; --i) {
792 ir_node *pred = get_Block_cfgpred(end_block, i);
797 mark_irn_visited(pred);
799 block = get_nodes_block(pred);
800 bl = create_block(block, part, env);
801 node = create_node(pred, bl, env);
806 /* collect all no-return blocks */
807 end = get_irg_end(current_ir_graph);
808 for (i = get_End_n_keepalives(end) - 1; i >= 0; --i) {
809 ir_node *ka = get_End_keepalive(end, i);
816 mark_irn_visited(ka);
819 block = get_nodes_block(ka);
820 bl = create_block(block, part, env);
821 node = create_node(ka, bl, env);
826 dump_partition("Created", part);
827 } /* partition_for_end_block */
831 * Create a partition for a given meet block.
833 * @param block the meet block
834 * @param preds array of candidate predecessors
835 * @param n_preds number of elements in preds
836 * @param env the environment
838 static void partition_for_block(ir_node *block, ir_node *preds[], int n_preds, environment_t *env) {
839 partition_t *part = create_partition(block, env);
842 for (i = n_preds - 1; i >= 0; --i) {
843 ir_node *pred = preds[i];
848 mark_irn_visited(pred);
850 block = get_nodes_block(pred);
851 bl = create_block(block, part, env);
852 node = create_node(pred, bl, env);
857 dump_partition("Created", part);
858 } /* partition_for_block */
861 * Walker: clear the links of all block phi lists and normal
864 static void clear_phi_links(ir_node *irn, void *env) {
867 set_Block_phis(irn, NULL);
868 set_irn_link(irn, NULL);
870 } /* clear_phi_links */
873 * Walker, detect live-out only nodes.
875 static void find_liveouts(ir_node *irn, void *ctx) {
876 environment_t *env = ctx;
877 ir_node **live_outs = env->live_outs;
884 /* ignore Keep-alives */
888 this_block = get_nodes_block(irn);
891 /* update the Phi list */
892 add_Block_phi(this_block, irn);
895 for (i = get_irn_arity(irn) - 1; i >= 0; --i) {
897 ir_node *pred = get_irn_n(irn, i);
898 int idx = get_irn_idx(pred);
900 if (live_outs[idx] == pred) {
901 /* referenced by other nodes inside this block */
905 pred_block = get_nodes_block(pred);
906 if (this_block != pred_block) {
907 /* pred is a live-out */
908 live_outs[idx] = pred_block;
910 /* this node is referenced from inside this block */
911 live_outs[idx] = pred;
917 * Check if the current block is the meet block of a its predecessors.
919 static void check_for_cf_meet(ir_node *block, void *ctx) {
920 environment_t *env = ctx;
924 if (block == get_irg_end_block(current_ir_graph)) {
925 /* always create a partition for the end block */
926 partition_for_end_block(block, env);
930 n = get_Block_n_cfgpreds(block);
932 /* Must have at least two predecessors */
935 NEW_ARR_A(ir_node *, preds, n);
938 for (i = n - 1; i >= 0; --i) {
939 ir_node *pred = get_Block_cfgpred(block, i);
941 /* pred must be a direct jump to us */
942 if (! is_Jmp(pred) && ! is_Raise(pred))
948 partition_for_block(block, preds, k, env);
949 } /* check_for_cf_meet */
952 * Compare two nodes for root ordering.
954 static int cmp_nodes(const void *a, const void *b) {
955 ir_node *const *pa = a;
956 ir_node *const *pb = b;
957 const ir_node *irn_a = *pa;
958 const ir_node *irn_b = *pb;
959 ir_opcode code_a = get_irn_opcode(irn_a);
960 ir_opcode code_b = get_irn_opcode(irn_b);
961 ir_mode *mode_a, *mode_b;
962 unsigned idx_a, idx_b;
964 /* try opcode first */
965 if (code_a != code_b)
966 return code_a - code_b;
969 mode_a = get_irn_mode(irn_a);
970 mode_b = get_irn_mode(irn_b);
972 if (mode_a != mode_b)
973 return mode_a < mode_b ? -1 : +1;
975 /* last resort: index */
976 idx_a = get_irn_idx(irn_a);
977 idx_b = get_irn_idx(irn_b);
979 return (idx_a > idx_b) - (idx_a < idx_b);
983 * Add the roots to all blocks.
985 static void add_roots(ir_graph *irg, environment_t *env) {
986 unsigned idx, n = get_irg_last_idx(irg);
987 ir_node **live_outs = env->live_outs;
990 for (idx = 0; idx < n; ++idx) {
991 ir_node *block = live_outs[idx];
993 if (block != NULL && is_Block(block)) {
994 block_t *bl = get_Block_entry(block);
997 ir_node *irn = get_idx_irn(irg, idx);
999 if (!irn_visited_else_mark(irn)) {
1000 ARR_APP1(ir_node *, bl->roots, irn);
1006 * Now sort the roots to normalize them as good as possible.
1007 * Else, we will split identical blocks if we start which different roots
1009 for (bl = env->all_blocks; bl != NULL; bl = bl->all_next) {
1010 int i, n = ARR_LEN(bl->roots);
1013 /* TODO: is this really needed? The roots are already in
1014 idx-order by construction, which might be good enough. */
1015 qsort(bl->roots, n, sizeof(bl->roots[0]), cmp_nodes);
1018 DB((dbg, LEVEL_2, " Adding Roots for block %+F\n ", bl->block));
1019 /* ok, add them sorted */
1020 for (i = 0; i < n; ++i) {
1021 DB((dbg, LEVEL_2, "%+F, ", bl->roots[i]));
1022 create_node(bl->roots[i], bl, env);
1024 DB((dbg, LEVEL_2, "\n"));
1025 DEL_ARR_F(bl->roots);
1029 #endif /* GENERAL_SHAPE */
1031 /* Combines congruent end blocks into one. */
1032 int shape_blocks(ir_graph *irg) {
1038 rem = current_ir_graph;
1039 current_ir_graph = irg;
1041 /* register a debug mask */
1042 FIRM_DBG_REGISTER(dbg, "firm.opt.blocks");
1044 DEBUG_ONLY(part_nr = 0);
1045 DB((dbg, LEVEL_1, "Shaping blocks for %+F\n", irg));
1047 /* works better, when returns are placed at the end of the blocks */
1048 normalize_n_returns(irg);
1050 obstack_init(&env.obst);
1051 INIT_LIST_HEAD(&env.partitions);
1052 INIT_LIST_HEAD(&env.ready);
1053 env.opcode2id_map = new_set(cmp_opcode, iro_Last * 4);
1055 n = get_irg_last_idx(irg);
1056 env.live_outs = NEW_ARR_F(ir_node *, n);
1057 memset(env.live_outs, 0, sizeof(*env.live_outs) * n);
1059 env.all_blocks = NULL;
1061 ir_reserve_resources(irg, IR_RESOURCE_IRN_LINK | IR_RESOURCE_PHI_LIST);
1063 #ifdef GENERAL_SHAPE
1065 * Detect, which nodes are live-out only: these are the roots of our blocks.
1068 irg_walk_graph(irg, clear_phi_links, find_liveouts, &env);
1071 ir_reserve_resources(irg, IR_RESOURCE_IRN_VISITED);
1073 inc_irg_visited(irg);
1074 #ifdef GENERAL_SHAPE
1076 * Detect all control flow meets and create partitions.
1078 irg_block_walk_graph(irg, NULL, check_for_cf_meet, &env);
1080 /* add root nodes to the partition blocks */
1081 add_roots(irg, &env);
1083 partition_for_end_block(get_irg_end_block(irg), &env);
1086 while (! list_empty(&env.partitions))
1089 res = !list_empty(&env.ready);
1091 list_for_each_entry(partition_t, part, &env.ready, part_list) {
1092 dump_partition("Ready Partition", part);
1095 ir_free_resources(irg, IR_RESOURCE_IRN_VISITED | IR_RESOURCE_IRN_LINK | IR_RESOURCE_PHI_LIST);
1098 /* control flow changed */
1099 set_irg_outs_inconsistent(irg);
1100 set_irg_extblk_inconsistent(irg);
1101 set_irg_doms_inconsistent(irg);
1102 /* Hmm, only the root loop is inconsistent */
1103 set_irg_loopinfo_inconsistent(irg);
1105 /* Calls might be removed. */
1106 set_trouts_inconsistent();
1109 DEL_ARR_F(env.live_outs);
1110 del_set(env.opcode2id_map);
1111 obstack_free(&env.obst, NULL);
1112 current_ir_graph = rem;
1115 } /* shape_blocks */