1 /*
2  * Copyright (C) 1995-2011 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  *
25  * This phase find congruent blocks.
26  * Two block are congruent, if they contains only equal calculations.
27  */
28 #include "config.h"
29 
30 #include "iroptimize.h"
31 #include "ircons.h"
32 #include "irgmod.h"
33 #include "irgraph_t.h"
34 #include "irnode_t.h"
35 #include "iropt_t.h"
36 #include "array_t.h"
37 #include "trouts.h"
38 #include "irgwalk.h"
39 #include "set.h"
40 #include "irpass.h"
41 #include "debug.h"
42 #include "util.h"
43 
44 /* define this for general block shaping: congruent blocks
45    are found not only before the end block but anywhere in the graph */
46 #define GENERAL_SHAPE
47 
48 typedef struct partition_t     partition_t;
49 typedef struct block_t         block_t;
50 typedef struct node_t          node_t;
51 typedef struct pair_t          pair_t;
52 typedef struct phi_t           phi_t;
53 typedef struct opcode_key_t    opcode_key_t;
54 typedef struct listmap_entry_t listmap_entry_t;
55 typedef struct environment_t   environment_t;
56 typedef struct pred_t          pred_t;
57 
58 /** An opcode map key. */
59 struct opcode_key_t {
60 	unsigned    code;   /**< The Firm opcode. */
61 	ir_mode     *mode;  /**< The mode of all nodes in the partition. */
62 	int         arity;  /**< The arity of this opcode (needed for Phi etc. */
63 	union {
64 		long            proj;   /**< For Proj nodes, its proj number */
65 		ir_entity       *ent;   /**< For Sel nodes, its entity */
66 		ir_tarval       *tv;    /**< For Const nodes, its tarval */
67 		symconst_symbol sym;    /**< For SymConst nodes, its symbol .*/
68 		void            *addr;  /**< Alias all addresses. */
69 		int             intVal; /**< For Conv/Div nodes: strict/remainderless. */
70 	} u;
71 };
72 
73 /** A partition contains all congruent blocks. */
74 struct partition_t {
75 	list_head part_list;     /**< Double linked list of partitions. */
76 	list_head blocks;        /**< List of blocks in this partition. */
77 	unsigned  n_blocks;      /**< Number of block in this partition. */
78 	ir_node   *meet_block;   /**< The control flow meet block of this partition. */
79 #ifdef DEBUG_libfirm
80 	unsigned  nr;            /**< For debugging: number of this partition. */
81 #endif
82 };
83 
84 /** A block. */
85 struct block_t {
86 	list_head  block_list;   /**< Double linked list of block inside a partition. */
87 	list_head  nodes;        /**< Wait-queue of nodes that must be checked for congruence. */
88 	block_t    *next;        /**< Next block of a split list. */
89 	ir_node    *block;       /**< Pointer to the associated IR-node block. */
90 	ir_node    **roots;      /**< An array of all root nodes. */
91 	node_t     *cf_root;     /**< The control flow root node of this block. */
92 	pair_t     *input_pairs; /**< The list of inputs to this block. */
93 	phi_t      *phis;        /**< The list of Phis in this block. */
94 	block_t    *all_next;    /**< Links all created blocks. */
95 	int        meet_input;   /**< Input number of this block in the meet-block. */
96 };
97 
98 /** A node. */
99 struct node_t {
100 	list_head  node_list;    /**< Double linked list of block inside a partition. */
101 	ir_node    *node;        /**< Pointer to the associated IR-node or NULL for block inputs. */
102 	char       is_input;     /**< Set if this node is an input from other block. */
103 };
104 
105 /** The environment. */
106 struct environment_t {
107 	list_head       partitions;     /**< list of partitions. */
108 	list_head       ready;          /**< list of ready partitions. */
109 	set             *opcode2id_map; /**< The opcodeMode->id map. */
110 	ir_node         **live_outs;    /**< Live out only nodes. */
111 	block_t         *all_blocks;    /**< List of all created blocks. */
112 	struct obstack  obst;           /** obstack for temporary data */
113 };
114 
115 /** A (node, input index) pair. */
116 struct pair_t {
117 	pair_t  *next;    /**< Points to the next pair entry. */
118 	ir_node *irn;     /**< The IR-node. */
119 	int     index;    /**< An input index. */
120 	ir_node **ins;    /**< A new in array once allocated. */
121 };
122 
123 /** A Phi, inputs pair. */
124 struct phi_t {
125 	phi_t   *next;    /**< Points to the next Phi pair entry. */
126 	ir_node *phi;     /**< The Phi node. */
127 	ir_node **ins;    /**< A new in array once allocated. */
128 };
129 
130 /** Describes a predecessor input. */
131 struct pred_t {
132 	ir_node *pred;  /**< The predecessor. */
133 	int     index;  /**< Its input index. */
134 };
135 
136 /**
137  * An entry in the list_map.
138  */
139 struct listmap_entry_t {
140 	void            *id;    /**< The id. */
141 	block_t         *list;  /**< The associated list for this id. */
142 	listmap_entry_t *next;  /**< Link to the next entry in the map. */
143 };
144 
145 /** We must map id's to lists. */
146 typedef struct listmap_t {
147 	set             *map;    /**< Map id's to listmap_entry_t's */
148 	listmap_entry_t *values; /**< List of all values in the map. */
149 } listmap_t;
150 
151 #define get_Block_entry(block)  ((block_t *)get_irn_link(block))
152 
153 /** The debug module handle. */
154 DEBUG_ONLY(static firm_dbg_module_t *dbg;)
155 
156 /** Next partition number. */
157 DEBUG_ONLY(static unsigned part_nr = 0;)
158 
159 #ifdef DEBUG_libfirm
160 /**
161  * Dump partition to output.
162  */
dump_partition(const char * msg,const partition_t * part)163 static void dump_partition(const char *msg, const partition_t *part)
164 {
165 	int first = 1;
166 
167 	DB((dbg, LEVEL_2, " %s part%u (%u blocks) {\n  ", msg, part->nr, part->n_blocks));
168 	list_for_each_entry(block_t, block, &part->blocks, block_list) {
169 		DB((dbg, LEVEL_2, "%s%+F", first ? "" : ", ", block->block));
170 		first = 0;
171 	}
172 	DB((dbg, LEVEL_2, "\n }\n"));
173 }  /* dump_partition */
174 
175 /**
176  * Dumps a list.
177  */
dump_list(const char * msg,const block_t * block)178 static void dump_list(const char *msg, const block_t *block)
179 {
180 	const block_t *p;
181 	int           first = 1;
182 
183 	DB((dbg, LEVEL_3, "  %s = {\n   ", msg));
184 	for (p = block; p != NULL; p = p->next) {
185 		DB((dbg, LEVEL_3, "%s%+F", first ? "" : ", ", p->block));
186 		first = 0;
187 	}
188 	DB((dbg, LEVEL_3, "\n  }\n"));
189 }  /* do_dump_list */
190 #else
191 #define dump_partition(msg, part)
192 #define dump_list(msg, block)
193 #endif
194 
195 /**
196  * Compare two pointer values of a listmap.
197  */
listmap_cmp_ptr(const void * elt,const void * key,size_t size)198 static int listmap_cmp_ptr(const void *elt, const void *key, size_t size)
199 {
200 	const listmap_entry_t *e1 = (const listmap_entry_t*)elt;
201 	const listmap_entry_t *e2 = (const listmap_entry_t*)key;
202 
203 	(void) size;
204 	return e1->id != e2->id;
205 }  /* listmap_cmp_ptr */
206 
207 /**
208  * Initializes a listmap.
209  *
210  * @param map  the listmap
211  */
listmap_init(listmap_t * map)212 static void listmap_init(listmap_t *map)
213 {
214 	map->map    = new_set(listmap_cmp_ptr, 16);
215 	map->values = NULL;
216 }  /* listmap_init */
217 
218 /**
219  * Terminates a listmap.
220  *
221  * @param map  the listmap
222  */
listmap_term(listmap_t * map)223 static void listmap_term(listmap_t *map)
224 {
225 	del_set(map->map);
226 }  /* listmap_term */
227 
228 /**
229  * Return the associated listmap entry for a given id.
230  *
231  * @param map  the listmap
232  * @param id   the id to search for
233  *
234  * @return the associated listmap entry for the given id
235  */
listmap_find(listmap_t * map,void * id)236 static listmap_entry_t *listmap_find(listmap_t *map, void *id)
237 {
238 	listmap_entry_t key, *entry;
239 
240 	key.id   = id;
241 	key.list = NULL;
242 	key.next = NULL;
243 	entry    = set_insert(listmap_entry_t, map->map, &key, sizeof(key), hash_ptr(id));
244 
245 	if (entry->list == NULL) {
246 		/* a new entry, put into the list */
247 		entry->next = map->values;
248 		map->values = entry;
249 	}
250 	return entry;
251 }  /* listmap_find */
252 
253 /**
254  * Calculate the hash value for an opcode map entry.
255  *
256  * @param entry  an opcode map entry
257  *
258  * @return a hash value for the given opcode map entry
259  */
opcode_hash(const opcode_key_t * entry)260 static unsigned opcode_hash(const opcode_key_t *entry)
261 {
262 	/* assume long >= int */
263 	return (unsigned)(PTR_TO_INT(entry->mode) * 9 + entry->code + entry->u.proj * 3 + hash_ptr(entry->u.addr) + entry->arity);
264 }  /* opcode_hash */
265 
266 /**
267  * Compare two entries in the opcode map.
268  */
cmp_opcode(const void * elt,const void * key,size_t size)269 static int cmp_opcode(const void *elt, const void *key, size_t size)
270 {
271 	const opcode_key_t *o1 = (opcode_key_t*)elt;
272 	const opcode_key_t *o2 = (opcode_key_t*)key;
273 
274 	(void) size;
275 	return o1->code != o2->code || o1->mode != o2->mode ||
276 	       o1->arity != o2->arity ||
277 	       o1->u.proj != o2->u.proj || o1->u.addr != o2->u.addr;
278 }  /* cmp_opcode */
279 
280 /**
281  * Creates a new empty partition and put in on the
282  * partitions list.
283  *
284  * @param meet_block  the control flow meet block of this partition
285  * @param env         the environment
286  */
create_partition(ir_node * meet_block,environment_t * env)287 static partition_t *create_partition(ir_node *meet_block, environment_t *env)
288 {
289 	partition_t *part = OALLOC(&env->obst, partition_t);
290 
291 	INIT_LIST_HEAD(&part->blocks);
292 	part->meet_block = meet_block;
293 	part->n_blocks   = 0;
294 	DEBUG_ONLY(part->nr = part_nr++;)
295 	list_add_tail(&part->part_list, &env->partitions);
296 	return part;
297 }  /* create_partition */
298 
299 /**
300  * Allocate a new block in the given partition.
301  *
302  * @param block      the IR-node
303  * @param meet_input Input number of this block in the meet-block
304  * @param partition  the partition to add to
305  * @param env        the environment
306  */
create_block(ir_node * block,int meet_input,partition_t * partition,environment_t * env)307 static block_t *create_block(ir_node *block, int meet_input, partition_t *partition, environment_t *env)
308 {
309 	block_t *bl = OALLOC(&env->obst, block_t);
310 
311 	set_irn_link(block, bl);
312 
313 	INIT_LIST_HEAD(&bl->nodes);
314 	bl->next        = NULL;
315 	bl->block       = block;
316 	bl->roots       = NEW_ARR_F(ir_node *, 0);
317 	bl->cf_root     = NULL;
318 	bl->input_pairs = NULL;
319 	bl->phis        = NULL;
320 	bl->meet_input  = meet_input;
321 
322 	/* put it into the list of partition blocks */
323 	list_add_tail(&bl->block_list, &partition->blocks);
324 	++partition->n_blocks;
325 
326 	/* put in into the list of all blocks */
327 	bl->all_next    = env->all_blocks;
328 	env->all_blocks = bl;
329 
330 	return bl;
331 }  /* create_block */
332 
333 /**
334  * Allocate a new node and add it to a blocks wait queue.
335  *
336  * @param irn    the IR-node
337  * @param block  the block to add to
338  * @param env    the environment
339  */
create_node(ir_node * irn,block_t * block,environment_t * env)340 static node_t *create_node(ir_node *irn, block_t *block, environment_t *env)
341 {
342 	node_t *node = OALLOC(&env->obst, node_t);
343 
344 	node->node     = irn;
345 	node->is_input = 0;
346 
347 	list_add_tail(&node->node_list, &block->nodes);
348 
349 	return node;
350 }  /* create_node */
351 
352 /**
353  * Add an input pair to a block.
354  *
355  * @param block  the block
356  * @param irn    the IR-node that has an block input
357  * @param idx    the index of the block input in node's predecessors
358  * @param env    the environment
359  */
add_pair(block_t * block,ir_node * irn,int idx,environment_t * env)360 static void add_pair(block_t *block, ir_node *irn, int idx, environment_t *env)
361 {
362 	pair_t *pair = OALLOC(&env->obst, pair_t);
363 
364 	pair->next  = block->input_pairs;
365 	pair->irn   = irn;
366 	pair->index = idx;
367 	pair->ins   = NULL;
368 
369 	block->input_pairs = pair;
370 }  /* add_pair */
371 
372 /**
373  * Add a Phi to a block.
374  *
375  * @param block  the block
376  * @param phi    the Phi node
377  * @param env    the environment
378  */
add_phi(block_t * block,ir_node * phi,environment_t * env)379 static void add_phi(block_t *block, ir_node *phi, environment_t *env)
380 {
381 	phi_t *node = OALLOC(&env->obst, phi_t);
382 
383 	node->next = block->phis;
384 	node->phi  = phi;
385 	node->ins  = NULL;
386 
387 	block->phis = node;
388 }  /** add_phi */
389 
390 /**
391  * Creates an opcode from a node.
392  */
opcode(const node_t * node,environment_t * env)393 static opcode_key_t *opcode(const node_t *node, environment_t *env)
394 {
395 	opcode_key_t key, *entry;
396 	ir_node      *irn = node->node;
397 
398 	if (node->is_input) {
399 		/* Node: as Block nodes are never propagated, it is safe to
400 		   use its code for "input" node */
401 		key.code   = iro_Block;
402 		key.arity  = 0;
403 	} else {
404 		key.code   = get_irn_opcode(irn);
405 		key.arity  = get_irn_arity(irn);
406 	}
407 	key.mode   = get_irn_mode(node->node);
408 	key.u.proj = 0;
409 	key.u.addr = NULL;
410 
411 	switch (key.code) {
412 	case iro_Proj:
413 		key.u.proj = get_Proj_proj(irn);
414 		break;
415 	case iro_Sel:
416 		key.u.ent = get_Sel_entity(irn);
417 		break;
418 	case iro_SymConst:
419 		key.u.sym = get_SymConst_symbol(irn);
420 		break;
421 	case iro_Const:
422 		key.u.tv  = get_Const_tarval(irn);
423 		break;
424 	case iro_Load:
425 		key.mode = get_Load_mode(irn);
426 		break;
427 	case iro_Div:
428 		key.u.intVal = get_Div_no_remainder(irn);
429 		break;
430 	case iro_Builtin:
431 		key.u.intVal = get_Builtin_kind(irn);
432 		break;
433 	default:
434 		break;
435 	}
436 
437 	entry = set_insert(opcode_key_t, env->opcode2id_map, &key, sizeof(key), opcode_hash(&key));
438 	return entry;
439 }  /* opcode */
440 
441 /**
442  * Split a partition by a local list.
443  *
444  * @param Z    partition to split
445  * @param g    a (non-empty) block list
446  * @param env  the environment
447  *
448  * @return  a new partition containing the nodes of g
449  */
split(partition_t * Z,block_t * g,environment_t * env)450 static partition_t *split(partition_t *Z, block_t *g, environment_t *env)
451 {
452 	partition_t *Z_prime;
453 	block_t     *block;
454 	unsigned    n = 0;
455 
456 	dump_partition("Splitting ", Z);
457 	dump_list("by list ", g);
458 
459 	assert(g != NULL);
460 
461 	/* Remove g from Z. */
462 	for (block = g; block != NULL; block = block->next) {
463 		list_del(&block->block_list);
464 		++n;
465 	}
466 	assert(n < Z->n_blocks);
467 	Z->n_blocks -= n;
468 
469 	/* Move g to a new partition, Z'. */
470 	Z_prime = create_partition(Z->meet_block, env);
471 	for (block = g; block != NULL; block = block->next) {
472 		list_add_tail(&block->block_list, &Z_prime->blocks);
473 	}
474 	Z_prime->n_blocks = n;
475 
476 	dump_partition("Now ", Z);
477 	dump_partition("Created new ", Z_prime);
478 	return Z_prime;
479 }  /* split */
480 
481 /**
482  * Return non-zero if pred should be tread as a input node.
483  */
is_input_node(ir_node * pred,ir_node * irn,int index)484 static int is_input_node(ir_node *pred, ir_node *irn, int index)
485 {
486 	/* for now, do NOT turn direct calls into indirect one */
487 	if (index != 1)
488 		return 1;
489 	if (! is_SymConst_addr_ent(pred))
490 		return 1;
491 	if (! is_Call(irn))
492 		return 1;
493 	return 0;
494 }  /* is_input_node */
495 
496 /**
497  * Propagate nodes on all wait queues of the given partition.
498  *
499  * @param part  the partition
500  * @param env   the environment
501  */
propagate_blocks(partition_t * part,environment_t * env)502 static void propagate_blocks(partition_t *part, environment_t *env)
503 {
504 	block_t         *ready_blocks = NULL;
505 	unsigned        n_ready       = 0;
506 	listmap_t       map;
507 	listmap_entry_t *iter;
508 
509 	DB((dbg, LEVEL_2, " Propagate blocks on part%u\n", part->nr));
510 
511 	/* Let map be an empty mapping from the range of Opcodes to (local) list of blocks. */
512 	listmap_init(&map);
513 	list_for_each_entry_safe(block_t, bl, next, &part->blocks, block_list) {
514 		opcode_key_t    *id;
515 		listmap_entry_t *entry;
516 		node_t          *node;
517 
518 		if (list_empty(&bl->nodes)) {
519 			bl->next     = ready_blocks;
520 			ready_blocks = bl;
521 			++n_ready;
522 			DB((dbg, LEVEL_2, " Block %+F completely processed\n", bl->block));
523 			continue;
524 		}
525 
526 		/* get the first node from the wait queue */
527 		node = list_entry(bl->nodes.next, node_t, node_list);
528 		list_del(&node->node_list);
529 
530 		/* put all not-visited predecessors to the wait queue */
531 		if (! node->is_input) {
532 			ir_node *irn = node->node;
533 			int     i;
534 
535 			DB((dbg, LEVEL_3, "  propagate %+F\n", irn));
536 			ir_normalize_node(node->node);
537 			for (i = get_irn_arity(irn) - 1; i >= 0; --i) {
538 				ir_node *pred  = get_irn_n(irn, i);
539 				ir_node *block = get_nodes_block(skip_Proj(pred));
540 
541 				if (block != bl->block) {
542 					node_t *p_node = create_node(pred, bl, env);
543 					if (is_input_node(pred, irn, i)) {
544 						/* is a block live input */
545 						p_node->is_input = 1;
546 						if (! is_Phi(irn))
547 							add_pair(bl, irn, i, env);
548 					} else if (is_Phi(pred)) {
549 						/* update the Phi list */
550 						add_phi(bl, pred, env);
551 					}
552 				} else if (! irn_visited_else_mark(pred)) {
553 					/* not yet visited, ok */
554 					create_node(pred, bl, env);
555 
556 					if (is_Phi(pred)) {
557 						/* update the Phi list */
558 						add_phi(bl, pred, env);
559 					}
560 				}
561 			}
562 		} else {
563 			DB((dbg, LEVEL_3, "  propagate Input %+F\n", node->node));
564 		}
565 
566 		/* Add bl to map[opcode(n)]. */
567 		id          = opcode(node, env);
568 		entry       = listmap_find(&map, id);
569 		bl->next    = entry->list;
570 		entry->list = bl;
571 	}
572 
573 	/* split out ready blocks */
574 	if (n_ready > 0) {
575 		partition_t *Z;
576 
577 		if (n_ready < part->n_blocks)
578 			Z = split(part, ready_blocks, env);
579 		else
580 			Z = part;
581 		list_del(&Z->part_list);
582 
583 		if (Z->n_blocks > 1) {
584 			DB((dbg, LEVEL_2, " Partition %u is ready\n", Z->nr));
585 			list_add(&Z->part_list, &env->ready);
586 		} else {
587 			DB((dbg, LEVEL_2, " Partition %u contains only one block, killed\n", Z->nr));
588 		}
589 	}
590 
591 	/* for all sets S except one in the range of map do */
592 	for (iter = map.values; iter != NULL; iter = iter->next) {
593 		block_t *S;
594 
595 		if (iter->next == NULL) {
596 			/* this is the last entry, ignore */
597 			break;
598 		}
599 		S = iter->list;
600 
601 		/* Add SPLIT( X, S ) to P. */
602 		split(part, S, env);
603 	}
604 	listmap_term(&map);
605 }  /* propagate_blocks */
606 
607 /**
608  * Propagate nodes on all wait queues.
609  *
610  * @param env    the environment
611  */
propagate(environment_t * env)612 static void propagate(environment_t *env)
613 {
614 	list_for_each_entry_safe(partition_t, part, next, &env->partitions, part_list) {
615 		if (part->n_blocks < 2) {
616 			/* zero or one block left, kill this partition */
617 			list_del(&part->part_list);
618 			DB((dbg, LEVEL_2, " Partition %u contains less than 2 blocks, killed\n", part->nr));
619 		} else
620 			propagate_blocks(part, env);
621 	}
622 }  /* propagate */
623 
624 /**
625  * Map a block to the phi[block->input] live-trough.
626  */
live_throughs(const block_t * bl,const ir_node * phi)627 static void *live_throughs(const block_t *bl, const ir_node *phi)
628 {
629 	ir_node *input = get_Phi_pred(phi, bl->meet_input);
630 
631 	/* If this input is inside our block, this
632 	   is a live-out and not a live trough.
633 	   Live-outs are tested inside propagate, so map all of
634 	   them to the "general" value NULL */
635 	if (get_nodes_block(input) == bl->block)
636 		return NULL;
637 	return input;
638 }  /* live_throughs */
639 
640 /**
641  * Split partition by live-outs and live-troughs.
642  *
643  * @param part  the partition
644  * @param env   the environment
645  */
propagate_blocks_live_troughs(partition_t * part,environment_t * env)646 static void propagate_blocks_live_troughs(partition_t *part, environment_t *env)
647 {
648 	const ir_node   *meet_block = part->meet_block;
649 	listmap_t       map;
650 	listmap_entry_t *iter;
651 	const ir_node   *phi;
652 
653 	DB((dbg, LEVEL_2, " Propagate live-troughs on part%u\n", part->nr));
654 
655 	for (phi = get_Block_phis(meet_block); phi != NULL; phi = get_Phi_next(phi)) {
656 		/* propagate on all Phis of the meet-block */
657 
658 		if (part->n_blocks < 2) {
659 			/* zero or one block left, kill this partition */
660 			list_del(&part->part_list);
661 			DB((dbg, LEVEL_2, " Partition %u contains less than 2 blocks, killed\n", part->nr));
662 			return;
663 		}
664 
665 		/* Let map be an empty mapping from the range of live-troughs to (local) list of blocks. */
666 		listmap_init(&map);
667 		list_for_each_entry_safe(block_t, bl, next, &part->blocks, block_list) {
668 			opcode_key_t    *id;
669 			listmap_entry_t *entry;
670 
671 			/* Add bl to map[live_trough(bl)]. */
672 			id          = (opcode_key_t*)live_throughs(bl, phi);
673 			entry       = listmap_find(&map, id);
674 			bl->next    = entry->list;
675 			entry->list = bl;
676 		}
677 
678 		/* for all sets S except one in the range of map do */
679 		for (iter = map.values; iter != NULL; iter = iter->next) {
680 			block_t *S;
681 
682 			if (iter->next == NULL) {
683 				/* this is the last entry, ignore */
684 				break;
685 			}
686 			S = iter->list;
687 
688 			/* Add SPLIT( X, S ) to P. */
689 			split(part, S, env);
690 		}
691 		listmap_term(&map);
692 	}
693 }  /* propagate_blocks_live_troughs */
694 
695 /**
696  * Propagate live-troughs on all partitions on the partition list.
697  *
698  * @param env    the environment
699  */
propagate_live_troughs(environment_t * env)700 static void propagate_live_troughs(environment_t *env)
701 {
702 	list_for_each_entry_safe(partition_t, part, next, &env->partitions, part_list) {
703 		propagate_blocks_live_troughs(part, env);
704 	}
705 }  /* propagate_live_troughs */
706 
707 /**
708  * Apply analysis results by replacing all blocks of a partition
709  * by one representative.
710  *
711  * Route all inputs from all block of the partition to the one
712  * representative.
713  * Enhance all existing Phis by combining them.
714  * Create new Phis for all previous input nodes.
715  *
716  * @param part  the partition to process
717  */
apply(ir_graph * irg,partition_t * part)718 static void apply(ir_graph *irg, partition_t *part)
719 {
720 	block_t *repr = list_entry(part->blocks.next, block_t, block_list);
721 	ir_node *block, *end, *meet_block, *p, *next;
722 	ir_node **ins, **phi_ins;
723 	phi_t   *repr_phi, *phi;
724 	pair_t  *repr_pair, *pair;
725 	int     i, j, k, n, n_phis;
726 
727 	list_del(&repr->block_list);
728 
729 	/* prepare new in arrays for the block ... */
730 	block = repr->block;
731 	n     = get_Block_n_cfgpreds(block);
732 	ins   = NEW_ARR_F(ir_node *, n);
733 
734 	for (i = 0; i < n; ++i) {
735 		ins[i] = get_Block_cfgpred(block, i);
736 	}
737 
738 	/* ... for all existing Phis ... */
739 	for (repr_phi = repr->phis; repr_phi != NULL; repr_phi = repr_phi->next) {
740 		repr_phi->ins = NEW_ARR_F(ir_node *, n);
741 
742 		for (i = 0; i < n; ++i)
743 			repr_phi->ins[i] = get_Phi_pred(repr_phi->phi, i);
744 	}
745 
746 	/* ... and all newly created Phis */
747 	for (repr_pair = repr->input_pairs; repr_pair != NULL; repr_pair = repr_pair->next) {
748 		ir_node *input = get_irn_n(repr_pair->irn, repr_pair->index);
749 
750 		repr_pair->ins = NEW_ARR_F(ir_node *, n);
751 		for (i = 0; i < n; ++i)
752 			repr_pair->ins[i] = input;
753 	}
754 
755 	DB((dbg, LEVEL_1, "Replacing "));
756 
757 	/* collect new in arrays */
758 	end = get_irg_end(irg);
759 	list_for_each_entry(block_t, bl, &part->blocks, block_list) {
760 		block = bl->block;
761 
762 		DB((dbg, LEVEL_1, "%+F, ", block));
763 
764 		/* first step: kill any keep-alive from this block */
765 		for (i = get_End_n_keepalives(end) - 1; i >= 0; --i) {
766 			ir_node *ka = get_End_keepalive(end, i);
767 
768 			if (is_Block(ka)) {
769 				if (ka == block)
770 					remove_End_keepalive(end, ka);
771 			} else {
772 				if (get_nodes_block(ka) == block)
773 					remove_End_keepalive(end, ka);
774 			}
775 		}
776 
777 		/* second step: update control flow */
778 		n = get_Block_n_cfgpreds(block);
779 		for (i = 0; i < n; ++i) {
780 			ir_node *pred = get_Block_cfgpred(block, i);
781 			ARR_APP1(ir_node *, ins, pred);
782 		}
783 
784 		/* third step: update Phis */
785 		for (repr_phi = repr->phis, phi = bl->phis;
786 		     repr_phi != NULL;
787 		     repr_phi = repr_phi->next, phi = phi->next) {
788 			for (i = 0; i < n; ++i) {
789 				ir_node *pred = get_Phi_pred(phi->phi, i);
790 				ARR_APP1(ir_node *, repr_phi->ins, pred);
791 			}
792 		}
793 
794 		/* fourth step: update inputs for new Phis */
795 		for (repr_pair = repr->input_pairs, pair = bl->input_pairs;
796 		     repr_pair != NULL;
797 		     repr_pair = repr_pair->next, pair = pair->next) {
798 			ir_node *input = get_irn_n(pair->irn, pair->index);
799 
800 			for (i = 0; i < n; ++i)
801 				ARR_APP1(ir_node *, repr_pair->ins, input);
802 		}
803 	}
804 
805 	DB((dbg, LEVEL_1, "by %+F\n", repr->block));
806 
807 	/* rewire block input ... */
808 	n = ARR_LEN(ins);
809 
810 	/*
811 	 * Some problem here. For:
812 	 * if (x) y = 1; else y = 2;
813 	 *
814 	 * the following code is constructed:
815 	 *
816 	 * b0: if (x) goto b1; else goto b1;
817 	 * b1: y = Phi(1,2)
818 	 *
819 	 * However, both predecessors of b1 are b0, making the Phi
820 	 * "wrong".
821 	 *
822 	 * We solve this by fixing critical edges.
823 	 */
824 	for (i = 0; i < n; ++i) {
825 		ir_node     *pred = ins[i];
826 		const ir_op *cfop;
827 
828 		if (is_Bad(pred))
829 			continue;
830 
831 		cfop = get_irn_op(skip_Proj(pred));
832 		if (is_op_fragile(cfop)) {
833 			/* ignore exception flow */
834 			continue;
835 		}
836 		if (is_op_forking(cfop)) {
837 			/* a critical edge */
838 			ir_node *block = new_r_Block(irg, 1, &ins[i]);
839 			ir_node *jmp   = new_r_Jmp(block);
840 			ins[i] = jmp;
841 		}
842 	}
843 
844 	block = repr->block;
845 	set_irn_in(block, n, ins);
846 	DEL_ARR_F(ins);
847 
848 	/* ... existing Phis ... */
849 	for (repr_phi = repr->phis; repr_phi != NULL; repr_phi = repr_phi->next) {
850 		set_irn_in(repr_phi->phi, n, repr_phi->ins);
851 		DEL_ARR_F(repr_phi->ins);
852 	}
853 
854 	/* ... and all inputs by creating new Phis ... */
855 	for (repr_pair = repr->input_pairs; repr_pair != NULL; repr_pair = repr_pair->next) {
856 		ir_node *input = get_irn_n(repr_pair->irn, repr_pair->index);
857 		ir_mode *mode  = get_irn_mode(input);
858 		ir_node *phi   = new_r_Phi(block, n, repr_pair->ins, mode);
859 
860 		set_irn_n(repr_pair->irn, repr_pair->index, phi);
861 		DEL_ARR_F(repr_pair->ins);
862 
863 		/* might be optimized away */
864 		if (is_Phi(phi))
865 			add_Block_phi(block, phi);
866 	}
867 
868 	/* ... finally rewire the meet block and fix its Phi-nodes */
869 	meet_block = part->meet_block;
870 	n         = get_Block_n_cfgpreds(meet_block);
871 
872 	ins = NEW_ARR_F(ir_node *, n);
873 
874 	n_phis = 0;
875 	for (p = get_Block_phis(meet_block); p != NULL; p = get_Phi_next(p)) {
876 		++n_phis;
877 	}
878 
879 	phi_ins = NEW_ARR_F(ir_node *, n_phis * n);
880 
881 	for (i = j = 0; i < n; ++i) {
882 		ir_node *pred = get_Block_cfgpred(meet_block, i);
883 
884 		list_for_each_entry(block_t, bl, &part->blocks, block_list) {
885 			if (bl->cf_root->node == pred)
886 				goto continue_outer;
887 		}
888 		ins[j] = pred;
889 
890 		for (k = 0, p = get_Block_phis(meet_block); p != NULL; p = get_Phi_next(p), ++k) {
891 			phi_ins[k * n + j] = get_Phi_pred(p, i);
892 		}
893 		++j;
894 
895 continue_outer:
896 		;
897 	}
898 
899 	/* fix phis */
900 	if (j == 1) {
901 		for (k = 0, p = get_Block_phis(meet_block); p != NULL; p = next, ++k) {
902 			next = get_Phi_next(p);
903 
904 			exchange(p, phi_ins[k * n]);
905 		}
906 		/* all Phis killed */
907 		set_Block_phis(meet_block, NULL);
908 	} else {
909 		for (k = 0, p = get_Block_phis(meet_block); p != NULL; p = next, ++k) {
910 			next = get_Phi_next(p);
911 
912 			set_irn_in(p, j, &phi_ins[k * n]);
913 		}
914 	}
915 	DEL_ARR_F(phi_ins);
916 
917 	/* fix inputs of the meet block */
918 	set_irn_in(meet_block, j, ins);
919 	DEL_ARR_F(ins);
920 }  /* apply */
921 
922 /**
923  * Create a partition for a the end block.
924  *
925  * @param end_block  the end block
926  * @param env        the environment
927  */
partition_for_end_block(ir_node * end_block,environment_t * env)928 static void partition_for_end_block(ir_node *end_block, environment_t *env)
929 {
930 	partition_t *part = create_partition(end_block, env);
931 	ir_node     *end;
932 	int         i;
933 
934 	/* collect normal blocks */
935 	for (i = get_Block_n_cfgpreds(end_block) - 1; i >= 0; --i) {
936 		ir_node *pred = get_Block_cfgpred(end_block, i);
937 		ir_node *block;
938 		block_t *bl;
939 		node_t  *node;
940 
941 		mark_irn_visited(pred);
942 
943 		block = get_nodes_block(pred);
944 		bl    = create_block(block, i, part, env);
945 		node  = create_node(pred, bl, env);
946 
947 		bl->cf_root = node;
948 	}
949 
950 	/* collect all no-return blocks */
951 	end = get_irg_end(get_irn_irg(end_block));
952 	for (i = get_End_n_keepalives(end) - 1; i >= 0; --i) {
953 		ir_node *ka    = get_End_keepalive(end, i);
954 		ir_node *block;
955 		block_t *bl;
956 		node_t  *node;
957 
958 		if (! is_Call(ka))
959 			continue;
960 		mark_irn_visited(ka);
961 
962 		/* found one */
963 		block = get_nodes_block(ka);
964 		bl    = create_block(block, -1, part, env);
965 		node  = create_node(ka, bl, env);
966 
967 		bl->cf_root = node;
968 	}
969 
970 	dump_partition("Created", part);
971 }  /* partition_for_end_block */
972 
973 #ifdef GENERAL_SHAPE
974 /**
975  * Create a partition for a given meet block.
976  *
977  * @param block    the meet block
978  * @param preds    array of candidate predecessors
979  * @param n_preds  number of elements in preds
980  * @param env      the environment
981  */
partition_for_block(ir_node * block,pred_t preds[],int n_preds,environment_t * env)982 static void partition_for_block(ir_node *block, pred_t preds[], int n_preds, environment_t *env)
983 {
984 	partition_t *part = create_partition(block, env);
985 	int         i;
986 
987 	for (i = n_preds - 1; i >= 0; --i) {
988 		ir_node *pred = preds[i].pred;
989 		ir_node *block;
990 		block_t *bl;
991 		node_t  *node;
992 
993 		mark_irn_visited(pred);
994 
995 		block = get_nodes_block(pred);
996 		bl    = create_block(block, preds[i].index, part, env);
997 		node  = create_node(pred, bl, env);
998 
999 		bl->cf_root = node;
1000 	}
1001 
1002 	dump_partition("Created", part);
1003 }  /* partition_for_block */
1004 
1005 /**
1006  * Walker: clear the links of all block phi lists and normal
1007  * links.
1008  */
clear_phi_links(ir_node * irn,void * env)1009 static void clear_phi_links(ir_node *irn, void *env)
1010 {
1011 	(void) env;
1012 	if (is_Block(irn)) {
1013 		set_Block_phis(irn, NULL);
1014 		set_irn_link(irn, NULL);
1015 	}
1016 }  /* clear_phi_links */
1017 
1018 /**
1019  * Walker, detect live-out nodes.
1020  */
find_liveouts(ir_node * irn,void * ctx)1021 static void find_liveouts(ir_node *irn, void *ctx)
1022 {
1023 	environment_t *env        = (environment_t*)ctx;
1024 	ir_node       **live_outs = env->live_outs;
1025 	ir_node       *this_block;
1026 	int           i;
1027 
1028 	if (is_Block(irn))
1029 		return;
1030 
1031 	/* ignore Keep-alives */
1032 	if (is_End(irn))
1033 		return;
1034 
1035 	this_block = get_nodes_block(irn);
1036 
1037 	if (is_Phi(irn)) {
1038 		/* update the Phi list */
1039 		add_Block_phi(this_block, irn);
1040 	}
1041 
1042 	for (i = get_irn_arity(irn) - 1; i >= 0; --i) {
1043 		ir_node *pred_block;
1044 		ir_node *pred = get_irn_n(irn, i);
1045 		int     idx   = get_irn_idx(pred);
1046 
1047 		if (live_outs[idx] != NULL) {
1048 			/* already marked as live-out */
1049 			return;
1050 		}
1051 
1052 		pred_block = get_nodes_block(pred);
1053 		/* Phi nodes always refer to live-outs */
1054 		if (is_Phi(irn) || this_block != pred_block) {
1055 			/* pred is a live-out */
1056 			live_outs[idx] = pred_block;
1057 		}
1058 	}
1059 }  /* find_liveouts */
1060 
1061 /**
1062  * Check if the current block is the meet block of its predecessors.
1063  */
check_for_cf_meet(ir_node * block,void * ctx)1064 static void check_for_cf_meet(ir_node *block, void *ctx)
1065 {
1066 	environment_t *env = (environment_t*)ctx;
1067 	int           i, k, n;
1068 	pred_t        *preds;
1069 
1070 	if (block == get_irg_end_block(get_irn_irg(block))) {
1071 		/* always create a partition for the end block */
1072 		partition_for_end_block(block, env);
1073 		return;
1074 	}
1075 
1076 	n = get_Block_n_cfgpreds(block);
1077 	if (n <= 1) {
1078 		/* Must have at least two predecessors */
1079 		return;
1080 	}
1081 
1082 	NEW_ARR_A(pred_t, preds, n);
1083 	k = 0;
1084 	for (i = n - 1; i >= 0; --i) {
1085 		ir_node *pred = get_Block_cfgpred(block, i);
1086 
1087 		/* pred must be a direct jump to us */
1088 		if (! is_Jmp(pred) && ! is_Raise(pred) && !is_Bad(pred))
1089 			continue;
1090 
1091 		preds[k].pred  = pred;
1092 		preds[k].index = i;
1093 		++k;
1094 	}
1095 
1096 	if (k > 1)
1097 		partition_for_block(block, preds, k, env);
1098 }  /* check_for_cf_meet */
1099 
1100 /**
1101  * Compare two nodes for root ordering.
1102  */
cmp_nodes(const void * a,const void * b)1103 static int cmp_nodes(const void *a, const void *b)
1104 {
1105 	const ir_node *const *pa = (const ir_node*const*)a;
1106 	const ir_node *const *pb = (const ir_node*const*)b;
1107 	const ir_node  *irn_a  = *pa;
1108 	const ir_node  *irn_b  = *pb;
1109 	unsigned       code_a  = get_irn_opcode(irn_a);
1110 	unsigned       code_b  = get_irn_opcode(irn_b);
1111 	ir_mode        *mode_a, *mode_b;
1112 	unsigned       idx_a, idx_b;
1113 
1114 	/* try opcode first */
1115 	if (code_a != code_b)
1116 		return code_a - code_b;
1117 
1118 	/* try mode */
1119 	mode_a = get_irn_mode(irn_a);
1120 	mode_b = get_irn_mode(irn_b);
1121 
1122 	if (mode_a != mode_b)
1123 		return mode_a < mode_b ? -1 : +1;
1124 
1125 	/* last resort: index */
1126 	idx_a = get_irn_idx(irn_a);
1127 	idx_b = get_irn_idx(irn_b);
1128 
1129 	return (idx_a > idx_b) - (idx_a < idx_b);
1130 }  /* cmp_nodes */
1131 
1132 /**
1133  * Add the roots to all blocks.
1134  */
add_roots(ir_graph * irg,environment_t * env)1135 static void add_roots(ir_graph *irg, environment_t *env)
1136 {
1137 	unsigned idx, n      = get_irg_last_idx(irg);
1138 	ir_node  **live_outs = env->live_outs;
1139 	block_t  *bl;
1140 
1141 	for (idx = 0; idx < n; ++idx) {
1142 		ir_node *block = live_outs[idx];
1143 
1144 		if (block != NULL && is_Block(block)) {
1145 			block_t *bl = get_Block_entry(block);
1146 
1147 			if (bl != NULL) {
1148 				ir_node *irn = get_idx_irn(irg, idx);
1149 
1150 				if (!irn_visited_else_mark(irn)) {
1151 					ARR_APP1(ir_node *, bl->roots, irn);
1152 				}
1153 			}
1154 		}
1155 	}
1156 	/*
1157 	 * Now sort the roots to normalize them as good as possible.
1158      * Else, we will split identical blocks if we start which different roots.
1159 	 */
1160 	for (bl = env->all_blocks; bl != NULL; bl = bl->all_next) {
1161 		size_t i, n = ARR_LEN(bl->roots);
1162 
1163 #if 1
1164 		/* TODO: is this really needed? The roots are already in
1165 		   idx-order by construction, which might be good enough. */
1166 		qsort(bl->roots, n, sizeof(bl->roots[0]), cmp_nodes);
1167 #endif
1168 
1169 		DB((dbg, LEVEL_2, " Adding Roots for block %+F\n  ", bl->block));
1170 		/* ok, add them sorted */
1171 		for (i = 0; i < n; ++i) {
1172 			DB((dbg, LEVEL_2, "%+F, ", bl->roots[i]));
1173 			create_node(bl->roots[i], bl, env);
1174 		}
1175 		DB((dbg, LEVEL_2, "\n"));
1176 		DEL_ARR_F(bl->roots);
1177 		bl->roots = NULL;
1178 	}
1179 }  /* add_roots */
1180 #endif /* GENERAL_SHAPE */
1181 
1182 /* Combines congruent end blocks into one. */
shape_blocks(ir_graph * irg)1183 void shape_blocks(ir_graph *irg)
1184 {
1185 	environment_t env;
1186 	block_t       *bl;
1187 	int           res, n;
1188 
1189 	/* register a debug mask */
1190 	FIRM_DBG_REGISTER(dbg, "firm.opt.blocks");
1191 
1192 	DEBUG_ONLY(part_nr = 0;)
1193 	DB((dbg, LEVEL_1, "Shaping blocks for %+F\n", irg));
1194 
1195 	/* works better, when returns are placed at the end of the blocks */
1196 	normalize_n_returns(irg);
1197 
1198 	obstack_init(&env.obst);
1199 	INIT_LIST_HEAD(&env.partitions);
1200 	INIT_LIST_HEAD(&env.ready);
1201 	env.opcode2id_map  = new_set(cmp_opcode, iro_Last * 4);
1202 
1203 	n             = get_irg_last_idx(irg);
1204 	env.live_outs = NEW_ARR_F(ir_node *, n);
1205 	memset(env.live_outs, 0, sizeof(*env.live_outs) * n);
1206 
1207 	env.all_blocks = NULL;
1208 
1209 	ir_reserve_resources(irg, IR_RESOURCE_IRN_LINK | IR_RESOURCE_PHI_LIST);
1210 
1211 #ifdef GENERAL_SHAPE
1212 	/*
1213 	 * Detect, which nodes are live-out only: these are the roots of our blocks.
1214 	 * Build phi lists.
1215 	 */
1216 	irg_walk_graph(irg, clear_phi_links, find_liveouts, &env);
1217 #endif
1218 
1219 	ir_reserve_resources(irg, IR_RESOURCE_IRN_VISITED);
1220 
1221 	inc_irg_visited(irg);
1222 #ifdef GENERAL_SHAPE
1223 	/*
1224 	 * Detect all control flow meets and create partitions.
1225 	 */
1226 	irg_block_walk_graph(irg, NULL, check_for_cf_meet, &env);
1227 
1228 	/* add root nodes to the partition blocks */
1229 	add_roots(irg, &env);
1230 #else
1231 	partition_for_end_block(get_irg_end_block(irg), &env);
1232 #endif
1233 
1234 	propagate_live_troughs(&env);
1235 	while (! list_empty(&env.partitions))
1236 		propagate(&env);
1237 
1238 	res = !list_empty(&env.ready);
1239 	//if (res) dump_ir_block_graph(irg, "-before");
1240 
1241 
1242 	list_for_each_entry(partition_t, part, &env.ready, part_list) {
1243 		dump_partition("Ready Partition", part);
1244 		apply(irg, part);
1245 	}
1246 	ir_free_resources(irg, IR_RESOURCE_IRN_VISITED | IR_RESOURCE_IRN_LINK | IR_RESOURCE_PHI_LIST);
1247 
1248 	if (res) {
1249 		/* control flow changed */
1250 		clear_irg_properties(irg, IR_GRAPH_PROPERTY_CONSISTENT_DOMINANCE);
1251 	}
1252 
1253 	for (bl = env.all_blocks; bl != NULL; bl = bl->all_next) {
1254 		DEL_ARR_F(bl->roots);
1255 	}
1256 
1257 	DEL_ARR_F(env.live_outs);
1258 	del_set(env.opcode2id_map);
1259 	obstack_free(&env.obst, NULL);
1260 }  /* shape_blocks */
1261 
shape_blocks_pass(const char * name)1262 ir_graph_pass_t *shape_blocks_pass(const char *name)
1263 {
1264 	return def_graph_pass(name ? name : "shape_blocks", shape_blocks);
1265 }  /* shape_blocks_pass */
1266