673e44829d404fdb226637f9467bb4f9a6372f22
[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 #ifdef HAVE_CONFIG_H
27 # include "config.h"
28 #endif
29
30 #include "iroptimize.h"
31
32 #include <assert.h>
33
34 #include "plist.h"
35 #include "xmalloc.h"
36 #include "irnode_t.h"
37 #include "irgraph_t.h"
38 #include "irprog_t.h"
39
40 #include "ircons.h"
41 #include "iropt_t.h"
42 #include "irgwalk.h"
43 #include "irgmod.h"
44 #include "irdump.h"
45 #include "irvrfy.h"
46 #include "iredges.h"
47
48 #include "array.h"
49
50 #include "irouts.h"
51 #include "irbackedge_t.h"
52
53 #include "irflag_t.h"
54 #include "firmstat.h"
55
56 #include "iropt_dbg.h"
57
58 /*------------------------------------------------------------------*/
59 /* Control flow optimization.                                       */
60 /*                                                                  */
61 /* Removes Bad control flow predecessors and empty blocks.  A block */
62 /* is empty if it contains only a Jmp node.                         */
63 /* Blocks can only be removed if they are not needed for the        */
64 /* semantics of Phi nodes.                                          */
65 /* Further, we NEVER remove labeled blocks (even if we could move   */
66 /* the label.                                                       */
67 /*------------------------------------------------------------------*/
68
69 #define set_Block_removable(block)      set_Block_mark(block, 1)
70 #define set_Block_non_removable(block)  set_Block_mark(block, 0)
71 #define is_Block_removable(block)       (get_Block_mark(block) != 0)
72
73 /**
74  * Replace binary Conds that jumps twice into the same block
75  * by a simple Jmp.
76  * E.g.
77  * @verbatim
78  *               Cond                     Jmp  Bad
79  *             /       \                   |   /
80  *       ProjX True   ProjX False  ==>     |  /
81  *             \       /                   | /
82  *               Block                    Block
83  * @endverbatim
84  *
85  * Such pattern are the result of if-conversion.
86  *
87  * Note that the simple case that Block has only these two
88  * predecessors are already handled in equivalent_node_Block().
89  */
90 static int remove_senseless_conds(ir_node *bl) {
91         int i, j;
92         int n = get_Block_n_cfgpreds(bl);
93         int changed = 0;
94
95         for (i = 0; i < n; ++i) {
96                 ir_node *pred_i = get_Block_cfgpred(bl, i);
97                 ir_node *cond_i = skip_Proj(pred_i);
98
99                 /* binary Cond */
100                 if (is_Cond(cond_i) && get_irn_mode(get_Cond_selector(cond_i)) == mode_b) {
101
102                         for (j = i + 1; j < n; ++j) {
103                                 ir_node *pred_j = get_Block_cfgpred(bl, j);
104                                 ir_node *cond_j = skip_Proj(pred_j);
105
106                                 if (cond_j == cond_i) {
107                                         ir_node *jmp = new_r_Jmp(current_ir_graph, get_nodes_block(cond_i));
108                                         set_irn_n(bl, i, jmp);
109                                         set_irn_n(bl, j, new_Bad());
110
111                                         DBG_OPT_IFSIM2(cond_i, jmp);
112                                         changed = 1;
113                                         break;
114                                 }
115                         }
116                 }
117         }
118         return changed;
119 }
120
121 /** An environment for merge_blocks and collect nodes. */
122 typedef struct _merge_env {
123         int changed;    /**< Set if the graph was changed. */
124         int phis_moved; /**< Set if Phi nodes were moved. */
125         plist_t *list;  /**< Helper list for all found Switch Conds. */
126 } merge_env;
127
128 /**
129  * Removes Tuples from Block control flow predecessors.
130  * Optimizes blocks with equivalent_node().  This is tricky,
131  * as we want to avoid nodes that have as block predecessor Bads.
132  * Therefore we also optimize at control flow operations, depending
133  * how we first reach the Block.
134  */
135 static void merge_blocks(ir_node *node, void *ctx) {
136         int i;
137         ir_node *new_block;
138         merge_env *env = ctx;
139
140         /* clear the link field for ALL nodes first */
141         set_irn_link(node, NULL);
142
143         if (is_Block(node)) {
144                 /* Remove Tuples */
145                 for (i = get_Block_n_cfgpreds(node) - 1; i >= 0; --i) {
146                         ir_node *pred = get_Block_cfgpred(node, i);
147                         ir_node *skipped = skip_Tuple(pred);
148                         if (pred != skipped) {
149                                 set_Block_cfgpred(node, i, skipped);
150                                 env->changed = 1;
151                         }
152                 }
153
154                 /* see below */
155                 new_block = equivalent_node(node);
156                 if (new_block != node && ! is_Block_dead(new_block)) {
157                         exchange(node, new_block);
158                         env->changed = 1;
159                 }
160
161         } else if (get_opt_optimize() && (get_irn_mode(node) == mode_X)) {
162                 /* We will soon visit a block.  Optimize it before visiting! */
163                 ir_node *b = get_nodes_block(skip_Proj(node));
164
165                 if (!is_Block_dead(b)) {
166                         new_block = equivalent_node(b);
167
168                         while (irn_not_visited(b) && (!is_Block_dead(new_block)) && (new_block != b)) {
169                                 /* We would have to run gigo() if new is bad, so we
170                                    promote it directly below. Nevertheless, we sometimes reach a block
171                                    the first time through a dataflow node.  In this case we optimized the
172                                    block as such and have to promote the Bad here. */
173                                 assert((get_opt_control_flow_straightening() ||
174                                         get_opt_control_flow_weak_simplification()) &&
175                                         ("strange flag setting"));
176                                 exchange(b, new_block);
177                                 env->changed = 1;
178                                 b = new_block;
179                                 new_block = equivalent_node(b);
180                         }
181
182                         /* normally, we would create a Bad block here, but this must be
183                          * prevented, so just set it's cf to Bad.
184                          */
185                         if (is_Block_dead(new_block)) {
186                                 exchange(node, new_Bad());
187                                 env->changed = 1;
188                         }
189                 }
190         }
191 }
192
193 /**
194  * Block walker removing control flow from dead block by
195  * inspecting dominance info.
196  * Do not replace blocks by Bad.  This optimization shall
197  * ensure, that all Bad control flow predecessors are
198  * removed, and no new other Bads are introduced.
199  * Further removed useless Conds and clear the mark of all blocks.
200  *
201  * Must be run in the post walker.
202  */
203 static void remove_unreachable_blocks_and_conds(ir_node *block, void *env) {
204         int i;
205         int *changed = env;
206
207         /* Check block predecessors and turn control flow into bad.
208            Beware of Tuple, kill them. */
209         for (i = get_Block_n_cfgpreds(block) - 1; i >= 0; --i) {
210                 ir_node *pred_X  = get_Block_cfgpred(block, i);
211                 ir_node *skipped = skip_Tuple(pred_X);
212
213                 if (! is_Bad(skipped)) {
214                         ir_node *pred_bl = get_nodes_block(skip_Proj(skipped));
215
216                         if (is_Block_dead(pred_bl) || (get_Block_dom_depth(pred_bl) < 0)) {
217                                 set_Block_dead(pred_bl);
218                                 exchange(pred_X, new_Bad());
219                                 *changed = 1;
220                         } else if (skipped != pred_X)
221                                 set_Block_cfgpred(block, i, skipped);
222                 }
223         }
224
225         *changed |= remove_senseless_conds(block);
226
227         /* clear the block mark of all blocks */
228         set_Block_removable(block);
229 }
230
231 /**
232  * Collects all Phi nodes in link list of Block.
233  * Marks all blocks "non_removable" if they contain a node other
234  * than Jmp (and Proj).
235  * Links all Proj nodes to their predecessors.
236  * Collects all switch-Conds in a list.
237  */
238 static void collect_nodes(ir_node *n, void *ctx) {
239         ir_opcode code = get_irn_opcode(n);
240         merge_env *env = ctx;
241
242         if (code == iro_Block) {
243                 /* mark the block as non-removable if it is labeled */
244                 if (has_Block_label(n))
245                         set_Block_non_removable(n);
246         } else {
247                 ir_node *b = get_nodes_block(n);
248
249                 if (code == iro_Phi && get_irn_arity(n) > 0) {
250                         /* Collect Phi nodes to compact ins along with block's ins. */
251                         set_irn_link(n, get_irn_link(b));
252                         set_irn_link(b, n);
253                 } else if (code != iro_Jmp && !is_Bad(b)) {  /* Check for non-empty block. */
254                         set_Block_non_removable(b);
255
256                         if (code == iro_Proj) {               /* link Proj nodes */
257                                 ir_node *pred = get_Proj_pred(n);
258
259                                 set_irn_link(n, get_irn_link(pred));
260                                 set_irn_link(pred, n);
261                         } else if (code == iro_Cond) {
262                                 ir_node *sel = get_Cond_selector(n);
263                                 if (mode_is_int(get_irn_mode(sel))) {
264                                         /* found a switch-Cond, collect */
265                                         plist_insert_back(env->list, n);
266                                 }
267                         }
268                 }
269         }
270 }
271
272 /** Returns true if pred is predecessor of block. */
273 static int is_pred_of(ir_node *pred, ir_node *b) {
274         int i;
275
276         for (i = get_Block_n_cfgpreds(b) - 1; i >= 0; --i) {
277                 ir_node *b_pred = get_Block_cfgpred_block(b, i);
278                 if (b_pred == pred)
279                         return 1;
280         }
281         return 0;
282 }
283
284 /** Test whether we can optimize away pred block pos of b.
285  *
286  *  @param  b    A block node.
287  *  @param  pos  The position of the predecessor block to judge about.
288  *
289  *  @returns     The number of predecessors
290  *
291  *  The test is rather tricky.
292  *
293  *  The situation is something like the following:
294  *  @verbatim
295  *                 if-block
296  *                  /   \
297  *              then-b  else-b
298  *                  \   /
299  *                    b
300  *  @endverbatim
301  *
302  *  b merges the control flow of an if-then-else.  We may not remove
303  *  the 'then' _and_ the 'else' block of an 'if' if there is a Phi
304  *  node in b, even if both are empty.  The destruction of this Phi
305  *  requires that a copy is added before the merge.  We have to
306  *  keep one of the case blocks to place the copies in.
307  *
308  *  To perform the test for pos, we must regard predecessors before pos
309  *  as already removed.
310  **/
311 static int test_whether_dispensable(ir_node *b, int pos) {
312         int i, j, n_preds = 1;
313         ir_node *pred = get_Block_cfgpred_block(b, pos);
314
315         /* Bad blocks will be optimized away, so we don't need space for them */
316         if (is_Block_dead(pred))
317                 return 0;
318
319         if (is_Block_removable(pred)) {
320                 if (!get_opt_optimize() || !get_opt_control_flow_strong_simplification()) {
321                         /* Mark block so that is will not be removed: optimization is turned off. */
322                         set_Block_non_removable(pred);
323                         return 1;
324                 }
325
326                 /* Seems to be empty. At least we detected this in collect_nodes. */
327                 if (get_irn_link(b) == NULL) {
328                         /* There are no Phi nodes ==> all predecessors are dispensable. */
329                         n_preds = get_Block_n_cfgpreds(pred);
330                 } else {
331                         /* b's pred blocks and pred's pred blocks must be pairwise disjunct.
332                            Handle all pred blocks with preds < pos as if they were already removed. */
333                         for (i = 0; i < pos; i++) {
334                                 ir_node *b_pred = get_Block_cfgpred_block(b, i);
335                                 if (! is_Block_dead(b_pred) && is_Block_removable(b_pred)) {
336                                         for (j = get_Block_n_cfgpreds(b_pred) - 1; j >= 0; --j) {
337                                                 ir_node *b_pred_pred = get_Block_cfgpred_block(b_pred, j);
338                                                 if (is_pred_of(b_pred_pred, pred))
339                                                         goto non_dispensable;
340                                         }
341                                 } else {
342                                         if (is_pred_of(b_pred, pred))
343                                                 goto non_dispensable;
344                                 }
345                         }
346                         for (i = pos +1; i < get_Block_n_cfgpreds(b); i++) {
347                                 ir_node *b_pred = get_Block_cfgpred_block(b, i);
348                                 if (is_pred_of(b_pred, pred))
349                                         goto non_dispensable;
350                         }
351                         /* if we get here, the block is dispensable */
352                         n_preds = get_Block_n_cfgpreds(pred);
353                 }
354         }
355
356         return n_preds;
357
358 non_dispensable:
359         set_Block_non_removable(pred);
360         return 1;
361 }
362
363 /**
364  * This method removed Bad cf predecessors from Blocks and Phis, and removes
365  * empty blocks.  A block is empty if it only contains Phi and Jmp nodes.
366  *
367  * We first adapt Phi nodes, then Block nodes, as we need the old ins
368  * of the Block to adapt the Phi nodes.  We do this by computing new
369  * in arrays, and then replacing the old ones.  So far we compute new in arrays
370  * for all nodes, not regarding whether there is a possibility for optimization.
371  *
372  * For each predecessor p of a Block b there are three cases:
373  *  -1. The predecessor p is a Bad node:  just skip it.  The in array of b shrinks by one.
374  *  -2. The predecessor p is empty.  Remove p.  All predecessors of p are now
375  *      predecessors of b.
376  *  -3. The predecessor p is a block containing useful code.  Just keep p as is.
377  *
378  * For Phi nodes f we have to check the conditions at the Block of f.
379  * For cases 1 and 3 we proceed as for Blocks.  For case 2 we can have two
380  * cases:
381  *  -2a: The old predecessor of the Phi f is a Phi pred_f IN THE BLOCK REMOVED.  In this
382  *      case we proceed as for blocks. We remove pred_f.  All
383  *      predecessors of pred_f now are predecessors of f.
384  *  -2b: The old predecessor of f is NOT in the block removed. It might be a Phi, too.
385  *      We have to replicate f for each predecessor of the removed block. Or, with
386  *      other words, the removed predecessor block has exactly one predecessor.
387  *
388  * Further there is a special case for self referencing blocks:
389  * @verbatim
390  *
391  *    then_b     else_b                              then_b  else_b
392  *       \      /                                      \      /
393  *        \    /                                        |    /
394  *        pred_b                                        |   /
395  *         |   ____                                     |  /  ____
396  *         |  |    |                                    |  | |    |
397  *         |  |    |       === optimized to ===>        \  | |    |
398  *        loop_b   |                                     loop_b   |
399  *         |  |    |                                      |  |    |
400  *         |  |____|                                      |  |____|
401  *         |                                              |
402  * @endverbatim
403  *
404  * If there is a Phi in pred_b, but we remove pred_b, we have to generate a
405  * Phi in loop_b, that has the ins of the Phi in pred_b and a self referencing
406  * backedge.
407  * @@@ It is negotiable whether we should do this ... there might end up a copy
408  * from the Phi in the loop when removing the Phis.
409  */
410 static void optimize_blocks(ir_node *b, void *ctx) {
411         int i, j, k, n, max_preds, n_preds, p_preds = -1;
412         ir_node *pred, *phi;
413         ir_node **in;
414         merge_env *env = ctx;
415
416         /* Count the number of predecessor if this block is merged with pred blocks
417            that are empty. */
418         max_preds = 0;
419         for (i = 0, k = get_Block_n_cfgpreds(b); i < k; ++i) {
420                 max_preds += test_whether_dispensable(b, i);
421         }
422         in = xmalloc(max_preds * sizeof(*in));
423
424         /*- Fix the Phi nodes of the current block -*/
425         for (phi = get_irn_link(b); phi; ) {
426                 assert(get_irn_op(phi) == op_Phi);
427
428                 /* Find the new predecessors for the Phi */
429                 p_preds = 0;
430                 for (i = 0, n = get_Block_n_cfgpreds(b); i < n; ++i) {
431                         pred = get_Block_cfgpred_block(b, i);
432
433                         if (is_Bad(get_Block_cfgpred(b, i))) {
434                                 /* case Phi 1: Do nothing */
435                         }
436                         else if (is_Block_removable(pred) && Block_not_block_visited(pred)) {
437                                 /* case Phi 2: It's an empty block and not yet visited. */
438                                 ir_node *phi_pred = get_Phi_pred(phi, i);
439
440                                 for (j = 0, k = get_Block_n_cfgpreds(pred); j < k; j++) {
441                                         /* because of breaking loops, not all predecessors are Bad-clean,
442                                          * so we must check this here again */
443                                         if (! is_Bad(get_Block_cfgpred(pred, j))) {
444                                                 if (get_nodes_block(phi_pred) == pred) {
445                                                         /* case Phi 2a: */
446                                                         assert(get_irn_op(phi_pred) == op_Phi);  /* Block is empty!! */
447
448                                                         in[p_preds++] = get_Phi_pred(phi_pred, j);
449                                                 } else {
450                                                         /* case Phi 2b: */
451                                                         in[p_preds++] = phi_pred;
452                                                 }
453                                         }
454                                 }
455                         } else {
456                                 /* case Phi 3: */
457                                 in[p_preds++] = get_Phi_pred(phi, i);
458                         }
459                 }
460                 assert(p_preds <= max_preds);
461
462                 /* Fix the node */
463                 if (p_preds == 1)
464                         /* By removal of Bad ins the Phi might be degenerated. */
465                         exchange(phi, in[0]);
466                 else
467                         set_irn_in(phi, p_preds, in);
468                 env->changed = 1;
469
470                 phi = get_irn_link(phi);
471         }
472
473         /*- This happens only if merge between loop backedge and single loop entry.
474             Moreover, it is only needed if predb is the direct dominator of b, else there can be no uses
475             of the Phi's in predb ... -*/
476         for (k = 0, n = get_Block_n_cfgpreds(b); k < n; ++k) {
477                 ir_node *predb = get_nodes_block(get_Block_cfgpred(b, k));
478
479                 if (is_Block_removable(predb) && Block_not_block_visited(predb)) {
480                         ir_node *next_phi;
481
482                         /* we found a predecessor block at position k that will be removed */
483                         for (phi = get_irn_link(predb); phi; phi = next_phi) {
484                                 int q_preds = 0;
485                                 next_phi = get_irn_link(phi);
486
487                                 assert(is_Phi(phi));
488
489                                 if (get_Block_idom(b) != predb) {
490                                         /* predb is not the dominator. There can't be uses of pred's Phi nodes, kill them .*/
491                                         exchange(phi, new_Bad());
492                                 } else {
493                                         /* predb is the direct dominator of b. There might be uses of the Phi nodes from
494                                            predb in further block, so move this phi from the predecessor into the block b */
495                                         set_nodes_block(phi, b);
496                                         set_irn_link(phi, get_irn_link(b));
497                                         set_irn_link(b, phi);
498                                         env->phis_moved = 1;
499
500                                         /* first, copy all 0..k-1 predecessors */
501                                         for (i = 0; i < k; i++) {
502                                                 pred = get_Block_cfgpred_block(b, i);
503
504                                                 if (is_Bad(pred)) {
505                                                         /* Do nothing */
506                                                 } else if (is_Block_removable(pred) && Block_not_block_visited(pred)) {
507                                                         /* It's an empty block and not yet visited. */
508                                                         for (j = 0; j < get_Block_n_cfgpreds(pred); j++) {
509                                                                 if (! is_Bad(get_Block_cfgpred(pred, j)))
510                                                                         in[q_preds++] = phi;
511                                                         }
512                                                 } else {
513                                                         in[q_preds++] = phi;
514                                                 }
515                                         }
516
517                                         /* now we are at k, copy the phi predecessors */
518                                         pred = get_nodes_block(get_Block_cfgpred(b, k));
519                                         for (i = 0; i < get_Phi_n_preds(phi); i++) {
520                                                 if (! is_Bad(get_Block_cfgpred(pred, i)))
521                                                         in[q_preds++] = get_Phi_pred(phi, i);
522                                         }
523
524                                         /* and now all the rest */
525                                         for (i = k+1; i < get_Block_n_cfgpreds(b); i++) {
526                                                 pred = get_nodes_block(get_Block_cfgpred(b, i));
527
528                                                 if (is_Bad(get_Block_cfgpred(b, i))) {
529                                                         /* Do nothing */
530                                                 } else if (is_Block_removable(pred) && Block_not_block_visited(pred)) {
531                                                         /* It's an empty block and not yet visited. */
532                                                         for (j = 0; j < get_Block_n_cfgpreds(pred); j++) {
533                                                                 if (! is_Bad(get_Block_cfgpred(pred, j)))
534                                                                         in[q_preds++] = phi;
535                                                         }
536                                                 } else {
537                                                         in[q_preds++] = phi;
538                                                 }
539                                         }
540
541                                         /* Fix the node */
542                                         if (q_preds == 1)
543                                                 exchange(phi, in[0]);
544                                         else
545                                                 set_irn_in(phi, q_preds, in);
546                                         env->changed = 1;
547
548                                         assert(q_preds <= max_preds);
549                                         // assert(p_preds == q_preds && "Wrong Phi Fix");
550                                 }
551                         }
552                 }
553         }
554
555         /*- Fix the block -*/
556         n_preds = 0;
557         for (i = 0; i < get_Block_n_cfgpreds(b); i++) {
558                 pred = get_Block_cfgpred_block(b, i);
559
560                 if (is_Bad(pred)) {
561                         /* case 1: Do nothing */
562                 } else if (is_Block_removable(pred) && Block_not_block_visited(pred)) {
563                         /* case 2: It's an empty block and not yet visited. */
564                         assert(get_Block_n_cfgpreds(b) > 1);
565                         /* Else it should be optimized by equivalent_node. */
566                         for (j = 0; j < get_Block_n_cfgpreds(pred); j++) {
567                                 ir_node *pred_block = get_Block_cfgpred(pred, j);
568
569                                 /* because of breaking loops, not all predecessors are Bad-clean,
570                                  * so we must check this here again */
571                                 if (! is_Bad(pred_block))
572                                         in[n_preds++] = pred_block;
573                         }
574                         /* Remove block as it might be kept alive. */
575                         exchange(pred, b/*new_Bad()*/);
576                 } else {
577                         /* case 3: */
578                         in[n_preds++] = get_Block_cfgpred(b, i);
579                 }
580         }
581         assert(n_preds <= max_preds);
582
583         set_irn_in(b, n_preds, in);
584         env->changed = 1;
585
586         assert(get_irn_link(b) == NULL || p_preds == -1 || (n_preds == p_preds && "Wrong Phi Fix"));
587         xfree(in);
588 }
589
590 /**
591  * Block walker: optimize all blocks using the default optimizations.
592  * This removes Blocks that with only a Jmp predecessor.
593  */
594 static void remove_simple_blocks(ir_node *block, void *ctx) {
595         ir_node *new_blk = equivalent_node(block);
596         merge_env *env = ctx;
597
598         if (new_blk != block) {
599                 exchange(block, new_blk);
600                 env->changed = 1;
601         }
602 }
603
604 /**
605  * Handle pre-optimized table switch Cond's.
606  * During iropt, all Projs from a switch-Cond are already removed except
607  * the defProj and maybe the taken one.
608  * The defProj cannot be removed WITHOUT looking backwards, so we do this here.
609  *
610  * @param cond the switch-Cond
611  *
612  * @return non-zero if a switch-Cond was optimized
613  *
614  * Expects all Proj's linked to the cond node
615  */
616 static int handle_switch_cond(ir_node *cond) {
617         ir_node *sel = get_Cond_selector(cond);
618
619         ir_node *proj1 = get_irn_link(cond);
620         ir_node *proj2 = get_irn_link(proj1);
621         ir_node *jmp, *blk;
622
623         blk = get_nodes_block(cond);
624
625         if (proj2 == NULL) {
626                 /* this Cond has only one Proj: must be the defProj */
627                 assert(get_Cond_defaultProj(cond) == get_Proj_proj(proj1));
628                 /* convert it into a Jmp */
629                 jmp = new_r_Jmp(current_ir_graph, blk);
630                 exchange(proj1, jmp);
631                 return 1;
632         } else if (get_irn_link(proj2) == NULL) {
633                 /* We have two Proj's here. Check if the Cond has
634                    a constant argument */
635                 tarval *tv = value_of(sel);
636
637                 if (tv != tarval_bad) {
638                         /* we have a constant switch */
639                         long num     = get_tarval_long(tv);
640                         long def_num = get_Cond_defaultProj(cond);
641
642                         if (def_num == get_Proj_proj(proj1)) {
643                                 /* first one is the defProj */
644                                 if (num == get_Proj_proj(proj2)) {
645                                         jmp = new_r_Jmp(current_ir_graph, blk);
646                                         exchange(proj2, jmp);
647                                         exchange(proj1, new_Bad());
648                                         return 1;
649                                 }
650                         } else if (def_num == get_Proj_proj(proj2)) {
651                                 /* second one is the defProj */
652                                 if (num == get_Proj_proj(proj1)) {
653                                         jmp = new_r_Jmp(current_ir_graph, blk);
654                                         exchange(proj1, jmp);
655                                         exchange(proj2, new_Bad());
656                                         return 1;
657                                 }
658                         } else {
659                                 /* neither: strange, Cond was not optimized so far */
660                                 if (num == get_Proj_proj(proj1)) {
661                                         jmp = new_r_Jmp(current_ir_graph, blk);
662                                         exchange(proj1, jmp);
663                                         exchange(proj2, new_Bad());
664                                         return 1;
665                                 } else if (num == get_Proj_proj(proj2)) {
666                                         jmp = new_r_Jmp(current_ir_graph, blk);
667                                         exchange(proj2, jmp);
668                                         exchange(proj1, new_Bad());
669                                         return 1;
670                                 }
671                         }
672                 }
673         }
674         return 0;
675 }
676
677 /* Optimizations of the control flow that also require changes of Phi nodes.
678  *
679  * This optimization performs two passes over the graph.
680  *
681  * The first pass collects all Phi nodes in a link list in the block
682  * nodes.  Further it performs simple control flow optimizations.
683  * Finally it marks all blocks that do not contain useful
684  * computations, i.e., these blocks might be removed.
685  *
686  * The second pass performs the optimizations intended by this algorithm.
687  * It walks only over block nodes and adapts these and the Phi nodes in these blocks,
688  * which it finds in a linked list computed by the first pass.
689  *
690  * We use the mark flag to mark removable blocks in the first
691  * phase.
692  */
693 void optimize_cf(ir_graph *irg) {
694         int i, j, n;
695         ir_node **in = NULL;
696         ir_node *cond, *end = get_irg_end(irg);
697         ir_graph *rem = current_ir_graph;
698         plist_element_t *el;
699         merge_env env;
700
701         assert(get_irg_phase_state(irg) != phase_building);
702
703         /* if the graph is not pinned, we cannot determine empty blocks */
704         assert(get_irg_pinned(irg) != op_pin_state_floats &&
705                "Control flow optimization need a pinned graph");
706
707         current_ir_graph = irg;
708
709         /* FIXME: control flow opt destroys block edges. So edges are deactivated here. Fix the edges! */
710         edges_deactivate(irg);
711
712         /* we use the mark flag to mark removable blocks */
713         set_using_block_mark(irg);
714 restart:
715         env.changed    = 0;
716         env.phis_moved = 0;
717
718         /* ALWAYS kill unreachable control flow. Backend cannot handle it anyway.
719            Use dominator info to kill blocks. Also optimize useless Conds. */
720         assure_doms(irg);
721         irg_block_walk_graph(irg, NULL, remove_unreachable_blocks_and_conds, &env.changed);
722
723         /* fix the keep-alives */
724         for (i = 0, n = get_End_n_keepalives(end); i < n; ++i) {
725                 ir_node *ka = get_End_keepalive(end, i);
726
727                 if (is_Block(ka)) {
728                         /* do NOT keep dead blocks */
729                         if (get_Block_dom_depth(ka) < 0) {
730                                 set_End_keepalive(end, i, new_Bad());
731                                 env.changed = 1;
732                         }
733                 } else if (is_Block_dead(get_nodes_block(ka)) ||
734                            get_Block_dom_depth(get_nodes_block(ka)) < 0) {
735                         /* do NOT keep nodes in dead blocks */
736                         set_End_keepalive(end, i, new_Bad());
737                         env.changed = 1;
738                 }
739         }
740
741         set_using_irn_link(irg);
742
743         env.list = plist_new();
744         irg_walk(end, merge_blocks, collect_nodes, &env);
745
746         clear_using_irn_link(irg);
747
748         if (env.changed) {
749                 /* Handle graph state if was changed. */
750                 set_irg_outs_inconsistent(irg);
751                 set_irg_doms_inconsistent(irg);
752                 set_irg_extblk_inconsistent(irg);
753                 set_irg_loopinfo_inconsistent(irg);
754                 env.changed = 0;
755         }
756
757         /* handle all collected switch-Conds */
758         foreach_plist(env.list, el) {
759                 cond = plist_element_get_value(el);
760                 env.changed |= handle_switch_cond(cond);
761         }
762         plist_free(env.list);
763
764         if (env.changed) {
765                 /* The Cond optimization might generate unreachable code, so restart if
766                    it happens. */
767                 goto restart;
768         }
769
770         /* Optimize the standard code. */
771         env.changed = 0;
772         assure_doms(irg);
773         irg_block_walk(get_irg_end_block(irg), optimize_blocks, remove_simple_blocks, &env);
774
775         /* Walk all keep alives, optimize them if block, add to new in-array
776            for end if useful. */
777         n  = get_End_n_keepalives(end);
778         if (n > 0)
779                 NEW_ARR_A(ir_node *, in, n);
780
781         /* in rare cases a node may be kept alive more than once, use the visited flag to detect this */
782         inc_irg_visited(irg);
783         set_using_irn_visited(irg);
784
785         /* fix the keep alive */
786         for (i = j = 0; i < n; i++) {
787                 ir_node *ka = get_End_keepalive(end, i);
788
789                 if (irn_not_visited(ka)) {
790                         ir_op *op = get_irn_op(ka);
791
792                         if ((op == op_Block) && Block_not_block_visited(ka)) {
793                                 /* irg_block_walk() will increase the block visited flag, but we must visit only
794                                    these blocks that are not visited yet, so decrease it first. */
795                                 set_irg_block_visited(irg, get_irg_block_visited(irg) - 1);
796                                 irg_block_walk(ka, optimize_blocks, remove_simple_blocks, &env.changed);
797                                 mark_irn_visited(ka);
798                                 in[j++] = ka;
799                         } else if (op == op_Phi) {
800                                 mark_irn_visited(ka);
801                                 /* don't keep alive dead blocks */
802                                 if (! is_Block_dead(get_nodes_block(ka)))
803                                         in[j++] = ka;
804                         } else if (is_op_keep(op)) {
805                                 mark_irn_visited(ka);
806                                 if (! is_Block_dead(get_nodes_block(ka)))
807                                         in[j++] = ka;
808                         }
809                 }
810         }
811         if (j != n) {
812                 set_End_keepalives(end, j, in);
813                 env.changed = 1;
814         }
815
816         clear_using_block_mark(irg);
817         clear_using_irn_visited(irg);
818
819         if (env.phis_moved) {
820                 /* Bad: when we moved Phi's, we might produce dead Phi nodes
821                    that are kept-alive.
822                    Some other phases cannot copy with this, so will them.
823                  */
824                 n = get_End_n_keepalives(end);
825                 if (n > 0) {
826                         if (env.changed) {
827                                 /* Handle graph state if was changed. */
828                                 set_irg_outs_inconsistent(irg);
829                         }
830                         assure_irg_outs(irg);
831
832                         for (i = j = 0; i < n; ++i) {
833                                 ir_node *ka = get_End_keepalive(end, i);
834
835                                 if (is_Phi(ka)) {
836                                         int k;
837
838                                         for (k = get_irn_n_outs(ka) - 1; k >= 0; --k) {
839                                                 ir_node *user = get_irn_out(ka, k);
840
841                                                 if (user != ka && user != end) {
842                                                         /* Is it a real user or just a self loop ? */
843                                                         break;
844                                                 }
845                                         }
846                                         if (k >= 0)
847                                                 in[j++] = ka;
848                                 } else
849                                         in[j++] = ka;
850                         }
851                         if (j != n) {
852                                 set_End_keepalives(end, j, in);
853                                 env.changed = 1;
854                         }
855                 }
856         }
857
858         if (env.changed) {
859                 /* Handle graph state if was changed. */
860                 set_irg_outs_inconsistent(irg);
861                 set_irg_doms_inconsistent(irg);
862                 set_irg_extblk_inconsistent(irg);
863                 set_irg_loopinfo_inconsistent(irg);
864         }
865
866
867         /* the verifier doesn't work yet with floating nodes */
868         if (get_irg_pinned(irg) == op_pin_state_pinned) {
869                 /* after optimize_cf(), only Bad data flow may remain. */
870                 if (irg_vrfy_bads(irg, BAD_DF | BAD_BLOCK | TUPLE)) {
871                         dump_ir_block_graph(irg, "-vrfy-cf");
872                         dump_ir_graph(irg, "-vrfy-cf");
873                         fprintf(stderr, "VRFY_BAD in optimize_cf()\n");
874                 }
875         }
876
877         current_ir_graph = rem;
878 }