49aa7728887ad9c784e10c2a7b1498eada3f2bd7
[libfirm] / ir / opt / cfopt.c
1 /*
2  * Copyright (C) 1995-2008 University of Karlsruhe.  All right reserved.
3  *
4  * This file is part of libFirm.
5  *
6  * This file may be distributed and/or modified under the terms of the
7  * GNU General Public License version 2 as published by the Free Software
8  * Foundation and appearing in the file LICENSE.GPL included in the
9  * packaging of this file.
10  *
11  * Licensees holding valid libFirm Professional Edition licenses may use
12  * this file in accordance with the libFirm Commercial License.
13  * Agreement provided with the Software.
14  *
15  * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
16  * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
17  * PURPOSE.
18  */
19
20 /**
21  * @file
22  * @brief   Control flow optimizations.
23  * @author  Goetz Lindenmaier, Michael Beck, Sebastian Hack
24  *
25  * Removes Bad control flow predecessors and empty blocks.  A block is empty
26  * if it contains only a Jmp node. Blocks can only be removed if they are not
27  * needed for the semantics of Phi nodes. Further, we NEVER remove labeled
28  * blocks (even if we could move the label).
29  */
30 #include "config.h"
31
32 #include "iroptimize.h"
33
34 #include <assert.h>
35 #include <stdbool.h>
36
37 #include "xmalloc.h"
38 #include "irnode_t.h"
39 #include "irgraph_t.h"
40 #include "irprog_t.h"
41
42 #include "ircons.h"
43 #include "iropt_t.h"
44 #include "irgwalk.h"
45 #include "irgmod.h"
46 #include "irdump.h"
47 #include "irverify.h"
48 #include "iredges.h"
49 #include "opt_manage.h"
50
51 #include "array_t.h"
52
53 #include "irouts.h"
54 #include "irbackedge_t.h"
55
56 #include "irflag_t.h"
57 #include "firmstat.h"
58 #include "irpass.h"
59 #include "irnodehashmap.h"
60 #include "irtools.h"
61
62 #include "iropt_dbg.h"
63
64 /** An environment for merge_blocks and collect nodes. */
65 typedef struct merge_env {
66         bool      changed;      /**< Set if the graph was changed. */
67         bool      phis_moved;   /**< Set if Phi nodes were moved. */
68 } merge_env;
69
70 /** set or reset the removable property of a block. */
71 static void set_Block_removable(ir_node *block, bool removable)
72 {
73         set_Block_mark(block, removable);
74 }
75
76 /** check if a block has the removable property set. */
77 static bool is_Block_removable(const ir_node *block)
78 {
79         return get_Block_mark(block);
80 }
81
82 /** checks if a given Cond node is a switch Cond. */
83 static bool is_switch_Cond(const ir_node *cond)
84 {
85         ir_node *sel = get_Cond_selector(cond);
86         return get_irn_mode(sel) != mode_b;
87 }
88
89 /** Walker: clear link fields and mark all blocks as removable. */
90 static void clear_link_and_mark_blocks_removable(ir_node *node, void *ctx)
91 {
92         (void) ctx;
93         set_irn_link(node, NULL);
94         if (is_Block(node)) {
95                 set_Block_removable(node, true);
96                 set_Block_phis(node, NULL);
97         } else if (is_Phi(node)) {
98                 set_Phi_next(node, NULL);
99         }
100 }
101
102 /**
103  * Collects all Phi nodes in link list of Block.
104  * Marks all blocks "non_removable" if they contain a node other
105  * than Jmp (and Proj).
106  * Links all Proj nodes to their predecessors.
107  * Collects all switch-Conds in a list.
108  */
109 static void collect_nodes(ir_node *n, void *ctx)
110 {
111         (void) ctx;
112         if (is_Phi(n)) {
113                 /* Collect Phi nodes to compact ins along with block's ins. */
114                 ir_node *block = get_nodes_block(n);
115                 add_Block_phi(block, n);
116         } else if (is_Block(n)) {
117                 if (get_Block_entity(n) != NULL) {
118                         /* block with a jump label attached cannot be removed. */
119                         set_Block_removable(n, false);
120                 }
121         } else if (is_Bad(n) || is_Jmp(n)) {
122                 /* ignore these */
123                 return;
124         } else {
125                 /* Check for non-empty block. */
126                 ir_node *block = get_nodes_block(n);
127
128                 set_Block_removable(block, false);
129
130                 if (is_Proj(n)) {
131                         /* link Proj nodes */
132                         ir_node *pred = get_Proj_pred(n);
133                         set_irn_link(n, get_irn_link(pred));
134                         set_irn_link(pred, n);
135                 }
136         }
137 }
138
139 /** Returns true if pred is predecessor of block b. */
140 static bool is_pred_of(const ir_node *pred, const ir_node *b)
141 {
142         int i;
143
144         for (i = get_Block_n_cfgpreds(b) - 1; i >= 0; --i) {
145                 ir_node *b_pred = get_Block_cfgpred_block(b, i);
146                 if (b_pred == pred)
147                         return true;
148         }
149         return false;
150 }
151
152 /** Test whether we can optimize away pred block pos of b.
153  *
154  *  @param  b    A block node.
155  *  @param  pos  The position of the predecessor block to judge about.
156  *
157  *  @returns     The number of predecessors
158  *
159  *  The test is rather tricky.
160  *
161  *  The situation is something like the following:
162  *  @verbatim
163  *                 if-block
164  *                  /   \
165  *              then-b  else-b
166  *                  \   /
167  *                    b
168  *  @endverbatim
169  *
170  *  b merges the control flow of an if-then-else.  We may not remove
171  *  the 'then' _and_ the 'else' block of an 'if' if there is a Phi
172  *  node in b, even if both are empty.  The destruction of this Phi
173  *  requires that a copy is added before the merge.  We have to
174  *  keep one of the case blocks to place the copies in.
175  *
176  *  To perform the test for pos, we must regard predecessors before pos
177  *  as already removed.
178  **/
179 static unsigned test_whether_dispensable(const ir_node *b, int pos)
180 {
181         ir_node *pred  = get_Block_cfgpred(b, pos);
182         ir_node *predb = get_nodes_block(pred);
183
184         if (is_Bad(pred) || !is_Block_removable(predb))
185                 return 1;
186
187         /* can't remove self-loops */
188         if (predb == b)
189                 goto non_dispensable;
190         if (is_unknown_jump(pred))
191                 goto non_dispensable;
192
193         /* Seems to be empty. At least we detected this in collect_nodes. */
194         if (get_Block_phis(b) != NULL) {
195                 int n_cfgpreds = get_Block_n_cfgpreds(b);
196                 int i;
197                 /* there are Phi nodes */
198
199                 /* b's pred blocks and pred's pred blocks must be pairwise disjunct.
200                  * Handle all pred blocks with preds < pos as if they were already
201                  * removed. */
202                 for (i = 0; i < pos; i++) {
203                         ir_node *other_pred  = get_Block_cfgpred(b, i);
204                         ir_node *other_predb = get_nodes_block(other_pred);
205                         if (is_Bad(other_pred))
206                                 continue;
207                         if (is_Block_removable(other_predb)
208                             && !Block_block_visited(other_predb)) {
209                                 int j;
210                                 for (j = get_Block_n_cfgpreds(other_predb) - 1; j >= 0; --j) {
211                                         ir_node *other_predpred
212                                                 = get_Block_cfgpred_block(other_predb, j);
213                                         if (is_pred_of(other_predpred, predb))
214                                                 goto non_dispensable;
215                                 }
216                         } else if (is_pred_of(other_predb, predb)) {
217                                 goto non_dispensable;
218                         }
219                 }
220                 for (i = pos+1; i < n_cfgpreds; i++) {
221                         ir_node *other_predb = get_Block_cfgpred_block(b, i);
222                         if (is_pred_of(other_predb, predb))
223                                 goto non_dispensable;
224                 }
225         }
226         /* we will not dispense already visited blocks */
227         if (Block_block_visited(predb))
228                 return 1;
229         /* if we get here, the block is dispensable, count useful preds */
230         return get_irn_arity(predb);
231
232 non_dispensable:
233         set_Block_removable(predb, false);
234         return 1;
235 }
236
237 /**
238  * This method removes empty blocks.  A block is empty if it only contains Phi
239  * and Jmp nodes.
240  *
241  * We first adapt Phi nodes, then Block nodes, as we need the old ins
242  * of the Block to adapt the Phi nodes.  We do this by computing new
243  * in arrays, and then replacing the old ones.  So far we compute new in arrays
244  * for all nodes, not regarding whether there is a possibility for optimization.
245  *
246  * For each predecessor p of a Block b there are three cases:
247  *  - The predecessor p is a Bad node: just skip it. The in array of b shrinks
248  *    by one.
249  *  - The predecessor p is empty. Remove p. All predecessors of p are now
250  *    predecessors of b.
251  *  - The predecessor p is a block containing useful code. Just keep p as is.
252  *
253  * For Phi nodes f we have to check the conditions at the Block of f.
254  * For cases 1 and 3 we proceed as for Blocks.  For case 2 we can have two
255  * cases:
256  *  -2a: The old predecessor of the Phi f is a Phi pred_f IN THE BLOCK REMOVED.
257  *       In this case we proceed as for blocks. We remove pred_f.  All
258  *       predecessors of pred_f now are predecessors of f.
259  *  -2b: The old predecessor of f is NOT in the block removed. It might be a Phi
260  *       too. We have to replicate f for each predecessor of the removed block.
261  *       Or, with other words, the removed predecessor block has exactly one
262  *       predecessor.
263  *
264  * Further there is a special case for self referencing blocks:
265  * @verbatim
266  *
267  *    then_b     else_b                              then_b  else_b
268  *       \      /                                      \      /
269  *        \    /                                        |    /
270  *        pred_b                                        |   /
271  *         |   ____                                     |  /  ____
272  *         |  |    |                                    |  | |    |
273  *         |  |    |       === optimized to ===>        \  | |    |
274  *        loop_b   |                                     loop_b   |
275  *         |  |    |                                      |  |    |
276  *         |  |____|                                      |  |____|
277  *         |                                              |
278  * @endverbatim
279  *
280  * If there is a Phi in pred_b, but we remove pred_b, we have to generate a
281  * Phi in loop_b, that has the ins of the Phi in pred_b and a self referencing
282  * backedge.
283  */
284 static void optimize_blocks(ir_node *b, void *ctx)
285 {
286         int i, j, k, n, max_preds, n_preds, p_preds = -1;
287         ir_node *phi;
288         ir_node *next;
289         ir_node **in;
290         merge_env *env = (merge_env*)ctx;
291
292         if (get_Block_dom_depth(b) < 0) {
293                 /* ignore unreachable blocks */
294                 return;
295         }
296
297         /* Count the number of predecessor if this block is merged with pred blocks
298            that are empty. */
299         max_preds = 0;
300         for (i = 0, k = get_Block_n_cfgpreds(b); i < k; ++i) {
301                 max_preds += test_whether_dispensable(b, i);
302         }
303         in = XMALLOCN(ir_node*, max_preds);
304
305         /*- Fix the Phi nodes of the current block -*/
306         for (phi = get_Block_phis(b); phi != NULL; phi = next) {
307                 next = get_Phi_next(phi);
308
309                 /* Find the new predecessors for the Phi */
310                 p_preds = 0;
311                 for (i = 0, n = get_Block_n_cfgpreds(b); i < n; ++i) {
312                         ir_graph *irg = get_irn_irg(b);
313                         ir_node *predx = get_Block_cfgpred(b, i);
314                         ir_node *pred;
315
316                         /* case Phi 1: maintain Bads, as somebody else is responsible to
317                          * remove them */
318                         if (is_Bad(predx)) {
319                                 in[p_preds++] = new_r_Bad(irg, get_irn_mode(phi));
320                                 continue;
321                         }
322
323                         pred = get_nodes_block(predx);
324
325                         /* case Phi 2: It's an empty block and not yet visited. */
326                         if (is_Block_removable(pred) && !Block_block_visited(pred)) {
327                                 ir_node *phi_pred = get_Phi_pred(phi, i);
328
329                                 for (j = 0, k = get_Block_n_cfgpreds(pred); j < k; j++) {
330                                         ir_node *pred_pred = get_Block_cfgpred(pred, j);
331
332                                         if (is_Bad(pred_pred)) {
333                                                 in[p_preds++] = new_r_Bad(irg, get_irn_mode(phi));
334                                                 continue;
335                                         }
336
337                                         if (get_nodes_block(phi_pred) == pred) {
338                                                 /* case Phi 2a: */
339                                                 assert(is_Phi(phi_pred));  /* Block is empty!! */
340
341                                                 in[p_preds++] = get_Phi_pred(phi_pred, j);
342                                         } else {
343                                                 /* case Phi 2b: */
344                                                 in[p_preds++] = phi_pred;
345                                         }
346                                 }
347                         } else {
348                                 /* case Phi 3: */
349                                 in[p_preds++] = get_Phi_pred(phi, i);
350                         }
351                 }
352                 assert(p_preds == max_preds);
353
354                 /* Fix the node */
355                 if (p_preds == 1) {
356                         exchange(phi, in[0]);
357                 } else {
358                         set_irn_in(phi, p_preds, in);
359                 }
360                 env->changed = true;
361         }
362
363         /*- This happens only if merge between loop backedge and single loop entry.
364             Moreover, it is only needed if predb is the direct dominator of b,
365             else there can be no uses of the Phi's in predb ... -*/
366         for (k = 0, n = get_Block_n_cfgpreds(b); k < n; ++k) {
367                 ir_node *pred  = get_Block_cfgpred(b, k);
368                 ir_node *predb = get_nodes_block(pred);
369                 if (is_Bad(pred))
370                         continue;
371
372                 if (is_Block_removable(predb) && !Block_block_visited(predb)) {
373                         ir_node *next_phi;
374
375                         /* we found a predecessor block at position k that will be removed */
376                         for (phi = get_Block_phis(predb); phi != NULL; phi = next_phi) {
377                                 int q_preds = 0;
378                                 next_phi = get_Phi_next(phi);
379
380                                 if (get_Block_idom(b) != predb) {
381                                         /* predb is not the dominator. There can't be uses of
382                                          * pred's Phi nodes, kill them .*/
383                                         ir_graph *irg  = get_irn_irg(b);
384                                         ir_mode  *mode = get_irn_mode(phi);
385                                         exchange(phi, new_r_Bad(irg, mode));
386                                 } else {
387                                         /* predb is the direct dominator of b. There might be uses
388                                          * of the Phi nodes from predb in further block, so move
389                                          * this phi from the predecessor into the block b */
390                                         set_nodes_block(phi, b);
391                                         set_Phi_next(phi, get_Block_phis(b));
392                                         set_Block_phis(b, phi);
393                                         env->phis_moved = true;
394
395                                         /* first, copy all 0..k-1 predecessors */
396                                         for (i = 0; i < k; i++) {
397                                                 ir_node *predx = get_Block_cfgpred(b, i);
398                                                 ir_node *pred_block;
399
400                                                 if (is_Bad(predx)) {
401                                                         ir_graph *irg  = get_irn_irg(b);
402                                                         ir_mode  *mode = get_irn_mode(phi);
403                                                         in[q_preds++] = new_r_Bad(irg, mode);
404                                                         continue;
405                                                 }
406                                                 pred_block = get_nodes_block(predx);
407                                                 if (is_Block_removable(pred_block)
408                                                            && !Block_block_visited(pred_block)) {
409                                                         int n_cfgpreds = get_Block_n_cfgpreds(pred_block);
410                                                         /* It's an empty block and not yet visited. */
411                                                         for (j = 0; j < n_cfgpreds; j++) {
412                                                                 if (!is_Bad(get_Block_cfgpred(pred_block, j))) {
413                                                                         in[q_preds++] = phi;
414                                                                 } else {
415                                                                         ir_graph *irg  = get_irn_irg(b);
416                                                                         ir_mode  *mode = get_irn_mode(phi);
417                                                                         in[q_preds++] = new_r_Bad(irg, mode);
418                                                                 }
419                                                         }
420                                                 } else {
421                                                         in[q_preds++] = phi;
422                                                 }
423                                         }
424
425                                         /* now we are at k, copy the phi predecessors */
426                                         pred = get_nodes_block(get_Block_cfgpred(b, k));
427                                         for (i = 0; i < get_Phi_n_preds(phi); i++) {
428                                                 in[q_preds++] = get_Phi_pred(phi, i);
429                                         }
430
431                                         /* and now all the rest */
432                                         for (i = k+1; i < get_Block_n_cfgpreds(b); i++) {
433                                                 pred = get_Block_cfgpred_block(b, i);
434
435                                                 if (is_Bad(pred)) {
436                                                         ir_graph *irg  = get_irn_irg(b);
437                                                         ir_mode  *mode = get_irn_mode(phi);
438                                                         in[q_preds++] = new_r_Bad(irg, mode);
439                                                 } else if (is_Block_removable(pred) && !Block_block_visited(pred)) {
440                                                         /* It's an empty block and not yet visited. */
441                                                         for (j = 0; j < get_Block_n_cfgpreds(pred); j++) {
442                                                                 if (! is_Bad(get_Block_cfgpred(pred, j))) {
443                                                                         in[q_preds++] = phi;
444                                                                 } else {
445                                                                         ir_graph *irg  = get_irn_irg(b);
446                                                                         ir_mode  *mode = get_irn_mode(phi);
447                                                                         in[q_preds++] = new_r_Bad(irg, mode);
448                                                                 }
449                                                         }
450                                                 } else {
451                                                         in[q_preds++] = phi;
452                                                 }
453                                         }
454
455                                         /* Fix the node */
456                                         if (q_preds == 1)
457                                                 exchange(phi, in[0]);
458                                         else
459                                                 set_irn_in(phi, q_preds, in);
460                                         env->changed = true;
461
462                                         assert(q_preds <= max_preds);
463                                         // assert(p_preds == q_preds && "Wrong Phi Fix");
464                                 }
465                         }
466                 }
467         }
468
469         /*- Fix the block -*/
470         n_preds = 0;
471         for (i = 0; i < get_Block_n_cfgpreds(b); i++) {
472                 ir_node *pred  = get_Block_cfgpred(b, i);
473                 ir_node *predb = get_nodes_block(pred);
474                 ir_graph *irg  = get_irn_irg(pred);
475
476                 /* case 1: Bad predecessor */
477                 if (is_Bad(pred)) {
478                         in[n_preds++] = new_r_Bad(irg, mode_X);
479                         continue;
480                 }
481                 if (is_Block_removable(predb) && !Block_block_visited(predb)) {
482                         /* case 2: It's an empty block and not yet visited. */
483                         for (j = 0; j < get_Block_n_cfgpreds(predb); j++) {
484                                 ir_node *predpred = get_Block_cfgpred(predb, j);
485
486                                 if (is_Bad(predpred)) {
487                                         in[n_preds++] = new_r_Bad(irg, mode_X);
488                                         continue;
489                                 }
490
491                                 in[n_preds++] = predpred;
492                         }
493                         /* Remove block+jump as it might be kept alive. */
494                         exchange(pred, new_r_Bad(get_irn_irg(b), mode_X));
495                         exchange(predb, new_r_Bad(get_irn_irg(b), mode_BB));
496                 } else {
497                         /* case 3: */
498                         in[n_preds++] = pred;
499                 }
500         }
501         assert(n_preds == max_preds);
502
503         set_irn_in(b, n_preds, in);
504         env->changed = true;
505
506         /* see if phi-fix was correct */
507         assert(get_Block_phis(b) == NULL || p_preds == -1 || (n_preds == p_preds));
508         xfree(in);
509 }
510
511 /**
512  * Optimize boolean Conds, where true and false jump to the same block into a Jmp
513  * Block must contain no Phi nodes.
514  *
515  *        Cond
516  *       /    \
517  *  projA      projB   =>   Jmp     Bad
518  *       \    /                \   /
519  *       block                 block
520  */
521 static bool optimize_pred_cond(ir_node *block, int i, int j)
522 {
523         ir_node *projA, *projB, *cond, *pred_block, *jmp, *bad;
524         assert(i != j);
525
526         projA = get_Block_cfgpred(block, i);
527         if (!is_Proj(projA)) return false;
528         projB = get_Block_cfgpred(block, j);
529         if (!is_Proj(projB)) return false;
530         cond  = get_Proj_pred(projA);
531         if (!is_Cond(cond))  return false;
532
533         if (cond != get_Proj_pred(projB)) return false;
534         if (is_switch_Cond(cond)) return false;
535
536         /* cond should actually be a Jmp */
537         pred_block = get_nodes_block(cond);
538         jmp = new_r_Jmp(pred_block);
539         bad = new_r_Bad(get_irn_irg(block), mode_X);
540
541         assert(projA != projB);
542         exchange(projA, jmp);
543         exchange(projB, bad);
544         return true;
545 }
546
547 typedef enum block_flags_t {
548         BF_HAS_OPERATIONS         = 1 << 0,
549         BF_HAS_PHIS               = 1 << 1,
550         BF_IS_UNKNOWN_JUMP_TARGET = 1 << 2,
551 } block_flags_t;
552
553 static bool get_block_flag(const ir_nodehashmap_t *infos, const ir_node *block,
554                            int flag)
555 {
556         return PTR_TO_INT(ir_nodehashmap_get(infos, block)) & flag;
557 }
558
559 static void set_block_flag(ir_nodehashmap_t *infos, ir_node *block,
560                            block_flags_t flag)
561 {
562         int data = PTR_TO_INT(ir_nodehashmap_get(infos, block));
563         data |= flag;
564         ir_nodehashmap_insert(infos, block, INT_TO_PTR(data));
565 }
566
567 static void clear_block_flag(ir_nodehashmap_t *infos, const ir_node *block)
568 {
569         ir_nodehashmap_remove(infos, block);
570 }
571
572 static bool has_operations(ir_nodehashmap_t *infos, const ir_node *block)
573 {
574         return get_block_flag(infos, block, BF_HAS_OPERATIONS);
575 }
576
577 static void set_has_operations(ir_nodehashmap_t *infos, ir_node *block)
578 {
579         set_block_flag(infos, block, BF_HAS_OPERATIONS);
580 }
581
582 static bool has_phis(ir_nodehashmap_t *infos, const ir_node *block)
583 {
584         return get_block_flag(infos, block, BF_HAS_PHIS);
585 }
586
587 static void set_has_phis(ir_nodehashmap_t *infos, ir_node *block)
588 {
589         set_block_flag(infos, block, BF_HAS_PHIS);
590 }
591
592 static bool is_unknown_jump_target(ir_nodehashmap_t *infos, const ir_node *block)
593 {
594         return get_block_flag(infos, block, BF_IS_UNKNOWN_JUMP_TARGET);
595 }
596
597 static void set_is_unknown_jump_target(ir_nodehashmap_t *infos, ir_node *block)
598 {
599         set_block_flag(infos, block, BF_IS_UNKNOWN_JUMP_TARGET);
600 }
601
602 /**
603  * Pre-Walker: fill block info information.
604  */
605 static void compute_block_info(ir_node *n, void *x)
606 {
607         ir_nodehashmap_t *infos = (ir_nodehashmap_t*)x;
608
609         if (is_Block(n)) {
610                 int i, max = get_Block_n_cfgpreds(n);
611                 for (i=0; i<max; i++) {
612                         ir_node *pred = get_Block_cfgpred(n,i);
613                         if (is_unknown_jump(pred)) {
614                                 set_is_unknown_jump_target(infos, n);
615                         }
616                 }
617         } else if (is_Phi(n)) {
618                 ir_node *block = get_nodes_block(n);
619                 set_has_phis(infos, block);
620         } else if (is_Jmp(n) || is_Cond(n) || is_Proj(n)) {
621                 /* ignore */
622         } else {
623                 ir_node *block = get_nodes_block(n);
624                 set_has_operations(infos, block);
625         }
626 }
627
628 static void clear_block_info(ir_node *block, void *x)
629 {
630         ir_nodehashmap_t *infos = (ir_nodehashmap_t*)x;
631         clear_block_flag(infos, block);
632 }
633
634 typedef struct skip_env {
635         bool             changed;
636         ir_nodehashmap_t block_infos;
637 } skip_env;
638
639 /**
640  * Post-Block-walker: Optimize useless if's (boolean Cond nodes
641  * with same true/false target) away.
642  */
643 static void optimize_ifs(ir_node *block, void *x)
644 {
645         skip_env *env = (skip_env*)x;
646         int i, j;
647         int n_preds = get_Block_n_cfgpreds(block);
648
649         if (has_phis(&env->block_infos, block))
650                 return;
651
652         /* optimize Cond predecessors (might produce Bad predecessors) */
653         for (i = 0; i < n_preds; ++i) {
654                 for (j = i+1; j < n_preds; ++j) {
655                         optimize_pred_cond(block, i, j);
656                 }
657         }
658 }
659
660 /**
661  * Pre-Block walker: remove empty blocks (only contain a Jmp)
662  * that are control flow predecessors of the current block.
663  */
664 static void remove_empty_blocks(ir_node *block, void *x)
665 {
666         skip_env *env = (skip_env*)x;
667         int i;
668         int n_preds = get_Block_n_cfgpreds(block);
669
670         for (i = 0; i < n_preds; ++i) {
671                 ir_node *jmp, *jmp_block;
672                 int n_jpreds = 0;
673
674                 jmp = get_Block_cfgpred(block, i);
675                 if (!is_Jmp(jmp))
676                         continue;
677                 jmp_block = get_nodes_block(jmp);
678                 if (jmp_block == block)
679                         continue; /* this infinite loop cannot be optimized any further */
680                 if (is_unknown_jump_target(&env->block_infos, jmp_block))
681                         continue; /* unknown jump target must not be optimized */
682                 if (has_phis(&env->block_infos,jmp_block))
683                         continue; /* this block contains Phis and is not skipped */
684                 if (Block_block_visited(jmp_block)) {
685                         continue;
686                         /* otherwise we could break the walker,
687                          * if block was reached via
688                          *     KeepAlive edge -> jmp_block -> A ---> block,
689                          * because the walker cannot handle Id nodes.
690                          *
691                          *   A      B
692                          *    \    /
693                          *   jmp_block
694                          *    /    \
695                          * block    End
696                          */
697                 }
698
699                 /* jmp_block is an empty block and can be optimized! */
700
701                 n_jpreds = get_Block_n_cfgpreds(jmp_block);
702                 /**
703                  * If the jmp block has only one predecessor this is straightforward.
704                  * However, if there are more predecessors, we only handle this,
705                  * if block has no Phis.
706                  */
707                 if (n_jpreds == 1) {
708                         ir_node *pred        = get_Block_cfgpred(jmp_block, 0);
709                         ir_node *pred_block  = get_nodes_block(pred);
710                         if (has_operations(&env->block_infos,jmp_block)) {
711                                 if (get_irg_start_block(get_irn_irg(pred_block)) == pred_block)
712                                         continue; /* must not merge operations into start block */
713                                 if (!is_Jmp(pred))
714                                         continue; /* must not create partially dead code, especially when it is mode_M */
715                         }
716
717                         /* skip jmp block by rerouting its predecessor to block
718                          *
719                          *     A              A
720                          *     |              |
721                          *  jmp_block   =>    |
722                          *     |              |
723                          *   block          block
724                          */
725                         exchange(jmp, pred);
726
727                         /* cleanup: jmp_block might have a Keep edge! */
728                         exchange(jmp_block, pred_block);
729                         env->changed = true;
730                 } else if ( !has_phis(&env->block_infos, block) &&
731                             !has_operations(&env->block_infos,jmp_block))
732                 {
733                         /* all predecessors can skip the jmp block, so block gets some new
734                          * predecessors
735                          *
736                          *  A     B                 A  B
737                          *   \   /                  |  |
738                          * jmp_block  C  =>  Bad  C |  |
739                          *      \    /          \ | | /
740                          *      block            block
741                          */
742                         ir_node **ins = ALLOCAN(ir_node*, n_preds+n_jpreds);
743                         int j;
744                         /* first copy the old predecessors, because the outer loop (i)
745                          * still walks over them */
746                         for (j = 0; j < n_preds; ++j) {
747                                 ins[j] = get_Block_cfgpred(block, j);
748                         }
749                         /* now append the new predecessors */
750                         for (j = 0; j < n_jpreds; ++j) {
751                                 ir_node *pred = get_Block_cfgpred(jmp_block, j);
752                                 ins[n_preds+j] = pred;
753                         }
754                         set_irn_in(block, n_preds+n_jpreds, ins);
755                         /* convert the jmp_block to Bad */
756                         ir_graph *irg = get_irn_irg(block);
757                         exchange(jmp_block, new_r_Bad(irg, mode_BB));
758                         exchange(jmp, new_r_Bad(irg, mode_X));
759                         /* let the outer loop walk over the new predecessors as well */
760                         n_preds += n_jpreds;
761                         env->changed = true;
762                         // TODO What if jmp_block had a KeepAlive edge?
763                 } else {
764                         /* This would involve Phis ... */
765                 }
766         }
767 }
768
769 /*
770  * All cfg optimizations, which do not touch Phi nodes.
771  *
772  * Note that this might create critical edges.
773  */
774 static void cfgopt_ignoring_phis(ir_graph *irg)
775 {
776         skip_env env;
777
778         env.changed = true;
779         ir_nodehashmap_init(&env.block_infos);
780
781         while (env.changed) {
782                 irg_walk_graph(irg, compute_block_info, NULL, &env.block_infos);
783                 env.changed = false;
784
785                 /* Remove blocks, which only consist of a Jmp */
786                 irg_block_walk_graph(irg, remove_empty_blocks, NULL, &env);
787
788                 /* Optimize Cond->Jmp, where then- and else-block are the same. */
789                 irg_block_walk_graph(irg, NULL, optimize_ifs, &env);
790
791                 if (env.changed) {
792                         clear_irg_state(irg, IR_GRAPH_STATE_CONSISTENT_DOMINANCE);
793                         /* clear block info, because it must be recomputed */
794                         irg_block_walk_graph(irg, clear_block_info, NULL, &env.block_infos);
795                         /* Removing blocks and Conds might enable more optimizations */
796                         continue;
797                 } else {
798                         break;
799                 }
800         }
801
802         ir_nodehashmap_destroy(&env.block_infos);
803 }
804
805 /* Optimizations of the control flow that also require changes of Phi nodes.  */
806 static ir_graph_state_t do_cfopt(ir_graph *irg)
807 {
808         int i, j, n;
809         ir_node **in = NULL;
810         ir_node *end = get_irg_end(irg);
811         ir_node *new_end;
812         merge_env env;
813
814         env.changed    = false;
815         env.phis_moved = false;
816
817         assert(get_irg_phase_state(irg) != phase_building);
818
819         /* if the graph is not pinned, we cannot determine empty blocks */
820         assert(get_irg_pinned(irg) != op_pin_state_floats &&
821                "Control flow optimization need a pinned graph");
822
823         edges_deactivate(irg);
824
825         /* First the "simple" optimizations, which do not touch Phis */
826         cfgopt_ignoring_phis(irg);
827
828         /* we use the mark flag to mark removable blocks */
829         ir_reserve_resources(irg, IR_RESOURCE_BLOCK_MARK | IR_RESOURCE_IRN_LINK
830                              | IR_RESOURCE_PHI_LIST);
831
832         /* The switch Cond optimization might expose unreachable code, so we loop */
833         for (;;) {
834                 bool changed = false;
835
836                 assure_doms(irg);
837
838                 /*
839                  * This pass collects all Phi nodes in a link list in the block
840                  * nodes.  Further it performs simple control flow optimizations.
841                  * Finally it marks all blocks that do not contain useful
842                  * computations, i.e., these blocks might be removed.
843                  */
844                 irg_walk(end, clear_link_and_mark_blocks_removable, collect_nodes, NULL);
845
846                 if (!changed)
847                         break;
848
849                 clear_irg_state(irg, IR_GRAPH_STATE_CONSISTENT_DOMINANCE
850                                    | IR_GRAPH_STATE_VALID_EXTENDED_BLOCKS
851                                    | IR_GRAPH_STATE_CONSISTENT_ENTITY_USAGE);
852         }
853
854         /* assert due to collect_nodes:
855          * 1. removable blocks are now marked as such
856          * 2. phi lists are up to date
857          */
858
859         /* Optimize the standard code.
860          * It walks only over block nodes and adapts these and the Phi nodes in these
861          * blocks, which it finds in a linked list computed before.
862          * */
863         assure_doms(irg);
864         irg_block_walk_graph(irg, optimize_blocks, NULL, &env);
865
866         new_end = optimize_in_place(end);
867         if (new_end != end) {
868                 set_irg_end(irg, new_end);
869                 end = new_end;
870         }
871         remove_End_Bads_and_doublets(end);
872
873         ir_free_resources(irg, IR_RESOURCE_BLOCK_MARK | IR_RESOURCE_IRN_LINK
874                           | IR_RESOURCE_PHI_LIST);
875
876         if (env.phis_moved) {
877                 /* Bad: when we moved Phi's, we might produce dead Phi nodes
878                    that are kept-alive.
879                    Some other phases cannot copy with this, so kill them.
880                  */
881                 n = get_End_n_keepalives(end);
882                 if (n > 0) {
883                         NEW_ARR_A(ir_node *, in, n);
884                         assure_irg_outs(irg);
885
886                         for (i = j = 0; i < n; ++i) {
887                                 ir_node *ka = get_End_keepalive(end, i);
888
889                                 if (is_Phi(ka)) {
890                                         int k;
891
892                                         for (k = get_irn_n_outs(ka) - 1; k >= 0; --k) {
893                                                 ir_node *user = get_irn_out(ka, k);
894
895                                                 if (user != ka && user != end) {
896                                                         /* Is it a real user or just a self loop ? */
897                                                         break;
898                                                 }
899                                         }
900                                         if (k >= 0)
901                                                 in[j++] = ka;
902                                 } else
903                                         in[j++] = ka;
904                         }
905                         if (j != n) {
906                                 set_End_keepalives(end, j, in);
907                                 env.changed = true;
908                         }
909                 }
910         }
911
912         return 0;
913 }
914
915 static optdesc_t opt_cf = {
916         "control-flow",
917         IR_GRAPH_STATE_NO_UNREACHABLE_CODE,
918         do_cfopt,
919 };
920
921 void optimize_cf(ir_graph *irg)
922 {
923         perform_irg_optimization(irg, &opt_cf);
924 }
925
926 /* Creates an ir_graph pass for optimize_cf. */
927 ir_graph_pass_t *optimize_cf_pass(const char *name)
928 {
929         return def_graph_pass(name ? name : "optimize_cf", optimize_cf);
930 }