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