d65e46e651a957700e418905edbeea9d23f21462
[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  * @version $Id$
25  *
26  * Removes Bad control flow predecessors and empty blocks.  A block is empty
27  * if it contains only a Jmp node. Blocks can only be removed if they are not
28  * needed for the semantics of Phi nodes. Further, we NEVER remove labeled
29  * blocks (even if we could move the label).
30  */
31 #include "config.h"
32
33 #include "iroptimize.h"
34
35 #include <assert.h>
36 #include <stdbool.h>
37
38 #include "xmalloc.h"
39 #include "irnode_t.h"
40 #include "irgraph_t.h"
41 #include "irprog_t.h"
42
43 #include "ircons.h"
44 #include "iropt_t.h"
45 #include "irgwalk.h"
46 #include "irgmod.h"
47 #include "irdump.h"
48 #include "irverify.h"
49 #include "iredges.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
60 #include "iropt_dbg.h"
61
62 /** An environment for merge_blocks and collect nodes. */
63 typedef struct merge_env {
64         bool      changed;      /**< Set if the graph was changed. */
65         bool      phis_moved;   /**< Set if Phi nodes were moved. */
66         ir_node **switch_conds; /**< Helper list for all found Switch Conds. */
67 } merge_env;
68
69 static void set_Block_removable(ir_node *block, bool removable)
70 {
71         set_Block_mark(block, removable);
72 }
73
74 static bool is_Block_removable(ir_node *block)
75 {
76         return get_Block_mark(block);
77 }
78
79 static void clear_link(ir_node *node, void *ctx)
80 {
81         (void) ctx;
82         set_irn_link(node, NULL);
83         if (is_Block(node))
84                 set_Block_removable(node, true);
85 }
86
87 /**
88  * Collects all Phi nodes in link list of Block.
89  * Marks all blocks "non_removable" if they contain a node other
90  * than Jmp (and Proj).
91  * Links all Proj nodes to their predecessors.
92  * Collects all switch-Conds in a list.
93  */
94 static void collect_nodes(ir_node *n, void *ctx)
95 {
96         merge_env *env = (merge_env*)ctx;
97
98         if (is_Phi(n)) {
99                 /* Collect Phi nodes to compact ins along with block's ins. */
100                 ir_node *block = get_nodes_block(n);
101                 set_irn_link(n, get_irn_link(block));
102                 set_irn_link(block, n);
103         } else if (is_Block(n)) {
104                 if (has_Block_entity(n))
105                         set_Block_removable(n, false);
106                 return;
107         } else if (!is_Jmp(n)) {  /* Check for non-empty block. */
108                 ir_node *block = get_nodes_block(n);
109                 set_Block_removable(block, false);
110
111                 if (is_Proj(n)) {
112                         /* link Proj nodes */
113                         ir_node *pred = get_Proj_pred(n);
114                         set_irn_link(n, get_irn_link(pred));
115                         set_irn_link(pred, n);
116                 } else if (is_Cond(n)) {
117                         ir_node *sel = get_Cond_selector(n);
118                         if (get_irn_mode(sel) != mode_b) {
119                                 /* found a switch-Cond, collect */
120                                 ARR_APP1(ir_node*, env->switch_conds, n);
121                         }
122                 }
123         }
124 }
125
126 /** Returns true if pred is predecessor of block. */
127 static bool is_pred_of(ir_node *pred, ir_node *b)
128 {
129         int i;
130
131         for (i = get_Block_n_cfgpreds(b) - 1; i >= 0; --i) {
132                 ir_node *b_pred = get_Block_cfgpred_block(b, i);
133                 if (b_pred == pred)
134                         return true;
135         }
136         return false;
137 }
138
139 /** Test whether we can optimize away pred block pos of b.
140  *
141  *  @param  b    A block node.
142  *  @param  pos  The position of the predecessor block to judge about.
143  *
144  *  @returns     The number of predecessors
145  *
146  *  The test is rather tricky.
147  *
148  *  The situation is something like the following:
149  *  @verbatim
150  *                 if-block
151  *                  /   \
152  *              then-b  else-b
153  *                  \   /
154  *                    b
155  *  @endverbatim
156  *
157  *  b merges the control flow of an if-then-else.  We may not remove
158  *  the 'then' _and_ the 'else' block of an 'if' if there is a Phi
159  *  node in b, even if both are empty.  The destruction of this Phi
160  *  requires that a copy is added before the merge.  We have to
161  *  keep one of the case blocks to place the copies in.
162  *
163  *  To perform the test for pos, we must regard predecessors before pos
164  *  as already removed.
165  **/
166 static unsigned test_whether_dispensable(ir_node *b, int pos)
167 {
168         ir_node *pred  = get_Block_cfgpred(b, pos);
169         ir_node *predb = get_nodes_block(pred);
170
171         if (is_Bad(pred) || !is_Block_removable(predb))
172                 return 1;
173
174         /* can't remove self-loops */
175         if (predb == b)
176                 goto non_dispensable;
177         if (is_unknown_jump(pred))
178                 goto non_dispensable;
179
180         /* Seems to be empty. At least we detected this in collect_nodes. */
181         if (get_irn_link(b) != NULL) {
182                 int n_cfgpreds = get_Block_n_cfgpreds(b);
183                 int i;
184                 /* there are Phi nodes */
185
186                 /* b's pred blocks and pred's pred blocks must be pairwise disjunct.
187                  * Handle all pred blocks with preds < pos as if they were already
188                  * removed. */
189                 for (i = 0; i < pos; i++) {
190                         ir_node *other_pred  = get_Block_cfgpred(b, i);
191                         ir_node *other_predb = get_nodes_block(other_pred);
192                         if (is_Bad(other_pred))
193                                 continue;
194                         if (is_Block_removable(other_predb)
195                             && !Block_block_visited(other_predb)) {
196                                 int j;
197                                 for (j = get_Block_n_cfgpreds(other_predb) - 1; j >= 0; --j) {
198                                         ir_node *other_predpred
199                                                 = get_Block_cfgpred_block(other_predb, j);
200                                         if (is_pred_of(other_predpred, predb))
201                                                 goto non_dispensable;
202                                 }
203                         } else if (is_pred_of(other_predb, predb)) {
204                                 goto non_dispensable;
205                         }
206                 }
207                 for (i = pos+1; i < n_cfgpreds; i++) {
208                         ir_node *other_predb = get_Block_cfgpred_block(b, i);
209                         if (is_pred_of(other_predb, predb))
210                                 goto non_dispensable;
211                 }
212         }
213         /* we will not dispense already visited blocks */
214         if (Block_block_visited(predb))
215                 return 1;
216         /* if we get here, the block is dispensable, count useful preds */
217         return get_irn_arity(predb);
218
219 non_dispensable:
220         set_Block_removable(predb, false);
221         return 1;
222 }
223
224 /**
225  * This method removed Bad cf predecessors from Blocks and Phis, and removes
226  * empty blocks.  A block is empty if it only contains Phi and Jmp nodes.
227  *
228  * We first adapt Phi nodes, then Block nodes, as we need the old ins
229  * of the Block to adapt the Phi nodes.  We do this by computing new
230  * in arrays, and then replacing the old ones.  So far we compute new in arrays
231  * for all nodes, not regarding whether there is a possibility for optimization.
232  *
233  * For each predecessor p of a Block b there are three cases:
234  *  - The predecessor p is a Bad node: just skip it. The in array of b shrinks
235  *    by one.
236  *  - The predecessor p is empty. Remove p. All predecessors of p are now
237  *    predecessors of b.
238  *  - The predecessor p is a block containing useful code. Just keep p as is.
239  *
240  * For Phi nodes f we have to check the conditions at the Block of f.
241  * For cases 1 and 3 we proceed as for Blocks.  For case 2 we can have two
242  * cases:
243  *  -2a: The old predecessor of the Phi f is a Phi pred_f IN THE BLOCK REMOVED.
244  *       In this case we proceed as for blocks. We remove pred_f.  All
245  *       predecessors of pred_f now are predecessors of f.
246  *  -2b: The old predecessor of f is NOT in the block removed. It might be a Phi
247  *       too. We have to replicate f for each predecessor of the removed block.
248  *       Or, with other words, the removed predecessor block has exactly one
249  *       predecessor.
250  *
251  * Further there is a special case for self referencing blocks:
252  * @verbatim
253  *
254  *    then_b     else_b                              then_b  else_b
255  *       \      /                                      \      /
256  *        \    /                                        |    /
257  *        pred_b                                        |   /
258  *         |   ____                                     |  /  ____
259  *         |  |    |                                    |  | |    |
260  *         |  |    |       === optimized to ===>        \  | |    |
261  *        loop_b   |                                     loop_b   |
262  *         |  |    |                                      |  |    |
263  *         |  |____|                                      |  |____|
264  *         |                                              |
265  * @endverbatim
266  *
267  * If there is a Phi in pred_b, but we remove pred_b, we have to generate a
268  * Phi in loop_b, that has the ins of the Phi in pred_b and a self referencing
269  * backedge.
270  */
271 static void optimize_blocks(ir_node *b, void *ctx)
272 {
273         int i, j, k, n, max_preds, n_preds, p_preds = -1;
274         ir_node *pred, *phi, *next;
275         ir_node **in;
276         merge_env *env = (merge_env*)ctx;
277
278         /* Count the number of predecessor if this block is merged with pred blocks
279            that are empty. */
280         max_preds = 0;
281         for (i = 0, k = get_Block_n_cfgpreds(b); i < k; ++i) {
282                 max_preds += test_whether_dispensable(b, i);
283         }
284         in = XMALLOCN(ir_node*, max_preds);
285
286         /*- Fix the Phi nodes of the current block -*/
287         for (phi = (ir_node*)get_irn_link(b); phi != NULL; phi = (ir_node*)next) {
288                 assert(is_Phi(phi));
289                 next = (ir_node*)get_irn_link(phi);
290
291                 /* Find the new predecessors for the Phi */
292                 p_preds = 0;
293                 for (i = 0, n = get_Block_n_cfgpreds(b); i < n; ++i) {
294                         ir_graph *irg = get_irn_irg(b);
295                         pred = get_Block_cfgpred_block(b, i);
296
297                         if (is_Bad(pred)) {
298                                 /* case Phi 1: maintain Bads, as somebody else is responsible to remove them */
299                                 in[p_preds++] = new_r_Bad(irg, get_irn_mode(phi));
300                         } else if (is_Block_removable(pred) && !Block_block_visited(pred)) {
301                                 /* case Phi 2: It's an empty block and not yet visited. */
302                                 ir_node *phi_pred = get_Phi_pred(phi, i);
303
304                                 for (j = 0, k = get_Block_n_cfgpreds(pred); j < k; j++) {
305                                         ir_node *pred_pred = get_Block_cfgpred(pred, j);
306
307                                         if (is_Bad(pred_pred)) {
308                                                 in[p_preds++] = new_r_Bad(irg, get_irn_mode(phi));
309                                                 continue;
310                                         }
311
312                                         if (get_nodes_block(phi_pred) == pred) {
313                                                 /* case Phi 2a: */
314                                                 assert(is_Phi(phi_pred));  /* Block is empty!! */
315
316                                                 in[p_preds++] = get_Phi_pred(phi_pred, j);
317                                         } else {
318                                                 /* case Phi 2b: */
319                                                 in[p_preds++] = phi_pred;
320                                         }
321                                 }
322                         } else {
323                                 /* case Phi 3: */
324                                 in[p_preds++] = get_Phi_pred(phi, i);
325                         }
326                 }
327                 assert(p_preds == max_preds);
328
329                 /* Fix the node */
330                 if (p_preds == 1)
331                         exchange(phi, in[0]);
332                 else
333                         set_irn_in(phi, p_preds, in);
334                 env->changed = true;
335         }
336
337         /*- This happens only if merge between loop backedge and single loop entry.
338             Moreover, it is only needed if predb is the direct dominator of b,
339             else there can be no uses of the Phi's in predb ... -*/
340         for (k = 0, n = get_Block_n_cfgpreds(b); k < n; ++k) {
341                 ir_node *pred  = get_Block_cfgpred(b, k);
342                 ir_node *predb = get_nodes_block(pred);
343                 if (is_Bad(pred))
344                         continue;
345
346                 if (is_Block_removable(predb) && !Block_block_visited(predb)) {
347                         ir_node *next_phi;
348
349                         /* we found a predecessor block at position k that will be removed */
350                         for (phi = (ir_node*)get_irn_link(predb); phi; phi = next_phi) {
351                                 int q_preds = 0;
352                                 next_phi = (ir_node*)get_irn_link(phi);
353
354                                 assert(is_Phi(phi));
355
356                                 if (get_Block_idom(b) != predb) {
357                                         /* predb is not the dominator. There can't be uses of pred's Phi nodes, kill them .*/
358                                         ir_graph *irg  = get_irn_irg(b);
359                                         ir_mode  *mode = get_irn_mode(phi);
360                                         exchange(phi, new_r_Bad(irg, mode));
361                                 } else {
362                                         /* predb is the direct dominator of b. There might be uses of the Phi nodes from
363                                            predb in further block, so move this phi from the predecessor into the block b */
364                                         set_nodes_block(phi, b);
365                                         set_irn_link(phi, get_irn_link(b));
366                                         set_irn_link(b, phi);
367                                         env->phis_moved = true;
368
369                                         /* first, copy all 0..k-1 predecessors */
370                                         for (i = 0; i < k; i++) {
371                                                 pred = get_Block_cfgpred_block(b, i);
372
373                                                 if (is_Bad(pred)) {
374                                                         /* Do nothing */
375                                                 } else if (is_Block_removable(pred) && !Block_block_visited(pred)) {
376                                                         /* It's an empty block and not yet visited. */
377                                                         for (j = 0; j < get_Block_n_cfgpreds(pred); j++) {
378                                                                 if (! is_Bad(get_Block_cfgpred(pred, j)))
379                                                                         in[q_preds++] = phi;
380                                                         }
381                                                 } else {
382                                                         in[q_preds++] = phi;
383                                                 }
384                                         }
385
386                                         /* now we are at k, copy the phi predecessors */
387                                         pred = get_nodes_block(get_Block_cfgpred(b, k));
388                                         for (i = 0; i < get_Phi_n_preds(phi); i++) {
389                                                 if (! is_Bad(get_Block_cfgpred(pred, i)))
390                                                         in[q_preds++] = get_Phi_pred(phi, i);
391                                         }
392
393                                         /* and now all the rest */
394                                         for (i = k+1; i < get_Block_n_cfgpreds(b); i++) {
395                                                 pred = get_Block_cfgpred_block(b, i);
396
397                                                 if (is_Bad(pred)) {
398                                                         /* Do nothing */
399                                                 } else if (is_Block_removable(pred) && !Block_block_visited(pred)) {
400                                                         /* It's an empty block and not yet visited. */
401                                                         for (j = 0; j < get_Block_n_cfgpreds(pred); j++) {
402                                                                 if (! is_Bad(get_Block_cfgpred(pred, j)))
403                                                                         in[q_preds++] = phi;
404                                                         }
405                                                 } else {
406                                                         in[q_preds++] = phi;
407                                                 }
408                                         }
409
410                                         /* Fix the node */
411                                         if (q_preds == 1)
412                                                 exchange(phi, in[0]);
413                                         else
414                                                 set_irn_in(phi, q_preds, in);
415                                         env->changed = true;
416
417                                         assert(q_preds <= max_preds);
418                                         // assert(p_preds == q_preds && "Wrong Phi Fix");
419                                 }
420                         }
421                 }
422         }
423
424         /*- Fix the block -*/
425         n_preds = 0;
426         for (i = 0; i < get_Block_n_cfgpreds(b); i++) {
427                 ir_node *pred  = get_Block_cfgpred(b, i);
428                 ir_node *predb = get_nodes_block(pred);
429                 ir_graph *irg  = get_irn_irg(pred);
430
431                 /* case 1: Do nothing */
432                 if (is_Bad(pred)) {
433                         in[n_preds++] = new_r_Bad(irg, mode_X);
434                         continue;
435                 }
436                 if (is_Block_removable(predb) && !Block_block_visited(predb)) {
437                         /* case 2: It's an empty block and not yet visited. */
438                         for (j = 0; j < get_Block_n_cfgpreds(predb); j++) {
439                                 ir_node *predpred = get_Block_cfgpred(predb, j);
440
441                                 if (is_Bad(predpred)) {
442                                         in[n_preds++] = new_r_Bad(irg, mode_X);
443                                         continue;
444                                 }
445
446                                 in[n_preds++] = predpred;
447                         }
448                         /* Remove block+jump as it might be kept alive. */
449                         exchange(pred, new_r_Bad(get_irn_irg(b), mode_X));
450                         exchange(predb, new_r_Bad(get_irn_irg(b), mode_BB));
451                 } else {
452                         /* case 3: */
453                         in[n_preds++] = pred;
454                 }
455         }
456         assert(n_preds == max_preds);
457
458         set_irn_in(b, n_preds, in);
459         env->changed = true;
460
461         /* see if phi-fix was correct */
462         assert(get_irn_link(b) == NULL || p_preds == -1 || (n_preds == p_preds));
463         xfree(in);
464 }
465
466 /**
467  * Block walker: optimize all blocks using the default optimizations.
468  * This removes Blocks with only a Jmp predecessor.
469  */
470 static void remove_simple_blocks(ir_node *block, void *ctx)
471 {
472         merge_env *env = (merge_env*)ctx;
473         ir_node   *new_blk = equivalent_node(block);
474
475         if (new_blk != block) {
476                 exchange(block, new_blk);
477                 env->changed = true;
478         }
479 }
480
481 /**
482  * Optimize table-switch Conds.
483  *
484  * @param cond the switch-Cond
485  * @return true if the switch-Cond was optimized
486  */
487 static bool handle_switch_cond(ir_node *cond)
488 {
489         ir_node *sel   = get_Cond_selector(cond);
490         ir_node *proj1 = (ir_node*)get_irn_link(cond);
491         ir_node *proj2 = (ir_node*)get_irn_link(proj1);
492         ir_node *blk   = get_nodes_block(cond);
493
494         /* exactly 1 Proj on the Cond node: must be the defaultProj */
495         if (proj2 == NULL) {
496                 ir_node *jmp = new_r_Jmp(blk);
497                 assert(get_Cond_default_proj(cond) == get_Proj_proj(proj1));
498                 /* convert it into a Jmp */
499                 exchange(proj1, jmp);
500                 return true;
501         }
502
503         /* handle Cond nodes with constant argument. In this case the localopt rules
504          * should have killed all obviously impossible cases.
505          * So the only case left to handle here is 1 defaultProj + 1case
506          * (this one case should be the one taken) */
507         if (get_irn_link(proj2) == NULL) {
508                 ir_tarval *tv = value_of(sel);
509
510                 if (tv != tarval_bad) {
511                         /* we have a constant switch */
512                         long      num     = get_tarval_long(tv);
513                         long      def_num = get_Cond_default_proj(cond);
514                         ir_graph *irg     = get_irn_irg(cond);
515                         ir_node  *bad     = new_r_Bad(irg, mode_X);
516
517                         if (def_num == get_Proj_proj(proj1)) {
518                                 /* first one is the defProj */
519                                 if (num == get_Proj_proj(proj2)) {
520                                         ir_node *jmp = new_r_Jmp(blk);
521                                         exchange(proj2, jmp);
522                                         exchange(proj1, bad);
523                                         return true;
524                                 }
525                         } else if (def_num == get_Proj_proj(proj2)) {
526                                 /* second one is the defProj */
527                                 if (num == get_Proj_proj(proj1)) {
528                                         ir_node *jmp = new_r_Jmp(blk);
529                                         exchange(proj1, jmp);
530                                         exchange(proj2, bad);
531                                         return true;
532                                 }
533                         } else {
534                                 /* neither: strange, Cond was not optimized so far */
535                                 if (num == get_Proj_proj(proj1)) {
536                                         ir_node *jmp = new_r_Jmp(blk);
537                                         exchange(proj1, jmp);
538                                         exchange(proj2, bad);
539                                         return true;
540                                 } else if (num == get_Proj_proj(proj2)) {
541                                         ir_node *jmp = new_r_Jmp(blk);
542                                         exchange(proj2, jmp);
543                                         exchange(proj1, bad);
544                                         return true;
545                                 }
546                         }
547                 }
548         }
549         return false;
550 }
551
552 /* Optimizations of the control flow that also require changes of Phi nodes.
553  *
554  * This optimization performs two passes over the graph.
555  *
556  * The first pass collects all Phi nodes in a link list in the block
557  * nodes.  Further it performs simple control flow optimizations.
558  * Finally it marks all blocks that do not contain useful
559  * computations, i.e., these blocks might be removed.
560  *
561  * The second pass performs the optimizations intended by this algorithm.
562  * It walks only over block nodes and adapts these and the Phi nodes in these
563  * blocks, which it finds in a linked list computed by the first pass.
564  *
565  * We use the mark flag to mark removable blocks in the first phase.
566  */
567 void optimize_cf(ir_graph *irg)
568 {
569         int i, j, n;
570         ir_node **in = NULL;
571         ir_node *end = get_irg_end(irg);
572         ir_node *new_end;
573         merge_env env;
574
575         assert(get_irg_phase_state(irg) != phase_building);
576
577         /* if the graph is not pinned, we cannot determine empty blocks */
578         assert(get_irg_pinned(irg) != op_pin_state_floats &&
579                "Control flow optimization need a pinned graph");
580
581         /* FIXME: control flow opt destroys block edges. So edges are deactivated
582          * here. Fix the edges! */
583         edges_deactivate(irg);
584
585         /* we use the mark flag to mark removable blocks */
586         ir_reserve_resources(irg, IR_RESOURCE_BLOCK_MARK | IR_RESOURCE_IRN_LINK);
587 restart:
588         env.changed    = false;
589         env.phis_moved = false;
590
591         assure_doms(irg);
592
593         env.switch_conds = NEW_ARR_F(ir_node*, 0);
594         irg_walk(end, clear_link, collect_nodes, &env);
595
596         /* handle all collected switch-Conds */
597         n = ARR_LEN(env.switch_conds);
598         for (i = 0; i < n; ++i) {
599                 ir_node *cond = env.switch_conds[i];
600                 env.changed |= handle_switch_cond(cond);
601         }
602         DEL_ARR_F(env.switch_conds);
603
604         if (env.changed) {
605                 /* Handle graph state if was changed. */
606                 set_irg_outs_inconsistent(irg);
607                 set_irg_doms_inconsistent(irg);
608                 set_irg_extblk_inconsistent(irg);
609                 set_irg_loopinfo_inconsistent(irg);
610                 set_irg_entity_usage_state(irg, ir_entity_usage_not_computed);
611
612                 /* The Cond optimization might generate unreachable code, so restart if
613                    it happens. */
614                 goto restart;
615         }
616
617         /* Optimize the standard code. */
618         assure_doms(irg);
619         irg_block_walk_graph(irg, optimize_blocks, remove_simple_blocks, &env);
620
621         new_end = optimize_in_place(end);
622         if (new_end != end) {
623                 set_irg_end(irg, new_end);
624                 end = new_end;
625         }
626         remove_End_Bads_and_doublets(end);
627
628         ir_free_resources(irg, IR_RESOURCE_BLOCK_MARK | IR_RESOURCE_IRN_LINK);
629
630         if (env.phis_moved) {
631                 /* Bad: when we moved Phi's, we might produce dead Phi nodes
632                    that are kept-alive.
633                    Some other phases cannot copy with this, so will them.
634                  */
635                 n = get_End_n_keepalives(end);
636                 if (n > 0) {
637                         NEW_ARR_A(ir_node *, in, n);
638                         if (env.changed) {
639                                 /* Handle graph state if was changed. */
640                                 set_irg_outs_inconsistent(irg);
641                         }
642                         assure_irg_outs(irg);
643
644                         for (i = j = 0; i < n; ++i) {
645                                 ir_node *ka = get_End_keepalive(end, i);
646
647                                 if (is_Phi(ka)) {
648                                         int k;
649
650                                         for (k = get_irn_n_outs(ka) - 1; k >= 0; --k) {
651                                                 ir_node *user = get_irn_out(ka, k);
652
653                                                 if (user != ka && user != end) {
654                                                         /* Is it a real user or just a self loop ? */
655                                                         break;
656                                                 }
657                                         }
658                                         if (k >= 0)
659                                                 in[j++] = ka;
660                                 } else
661                                         in[j++] = ka;
662                         }
663                         if (j != n) {
664                                 set_End_keepalives(end, j, in);
665                                 env.changed = true;
666                         }
667                 }
668         }
669
670         if (env.changed) {
671                 /* Handle graph state if was changed. */
672                 set_irg_outs_inconsistent(irg);
673                 set_irg_doms_inconsistent(irg);
674                 set_irg_extblk_inconsistent(irg);
675                 set_irg_loopinfo_inconsistent(irg);
676                 set_irg_entity_usage_state(irg, ir_entity_usage_not_computed);
677         }
678 }
679
680 /* Creates an ir_graph pass for optimize_cf. */
681 ir_graph_pass_t *optimize_cf_pass(const char *name)
682 {
683         return def_graph_pass(name ? name : "optimize_cf", optimize_cf);
684 }