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