298fca1d7db4ee73b3f088333a16ae6938ed7902
[libfirm] / ir / opt / cfopt.c
1 /*
2  * Project:     libFIRM
3  * File name:   ir/opt/cfopt.c
4  * Purpose:     control flow optimizations
5  * Author:
6  * Created:
7  * CVS-ID:      $Id$
8  * Copyright:   (c) 1998-2004 Universität Karlsruhe
9  * Licence:     This file protected by GPL -  GNU GENERAL PUBLIC LICENSE.
10  */
11
12 #ifdef HAVE_CONFIG_H
13 # include <config.h>
14 #endif
15
16 #include <assert.h>
17
18 #include "irnode_t.h"
19 #include "irgraph_t.h"
20 #include "irprog_t.h"
21
22 #include "ircons.h"
23 #include "iropt_t.h"
24 #include "irgwalk.h"
25 #include "irgmod.h"
26 #include "irdump.h"
27 #include "irvrfy.h"
28
29 #include "array.h"
30
31 #include "irouts.h"
32 #include "irbackedge_t.h"
33
34 #include "irflag_t.h"
35 #include "firmstat.h"
36
37 #include "cfopt.h"
38
39 /*------------------------------------------------------------------*/
40 /* Control flow optimization.                                       */
41 /*                                                                  */
42 /* Removes Bad control flow predecessors and empty blocks.  A block */
43 /* is empty if it contains only a Jmp node.                         */
44 /* Blocks can only be removed if they are not needed for the        */
45 /* semantics of Phi nodes.                                          */
46 /*------------------------------------------------------------------*/
47
48 /**
49  * Removes Tuples from Block control flow predecessors.
50  * Optimizes blocks with equivalent_node().  This is tricky,
51  * as we want to avoid nodes that have as block predecessor Bads.
52  * Therefore we also optimize at control flow operations, depending
53  * how we first reach the Block.
54  */
55 static void merge_blocks(ir_node *n, void *env) {
56   int i;
57   ir_node *new_block;
58
59   /* clear the link field for ALL nodes first */
60   set_irn_link(n, NULL);
61
62   if (get_irn_op(n) == op_Block) {
63     /* Remove Tuples */
64     for (i = 0; i < get_Block_n_cfgpreds(n); i++) {
65       /* GL @@@ : is this possible? if (get_opt_normalize()) -- added, all tests go through.
66          A different order of optimizations might cause problems. */
67       if (get_opt_normalize())
68         set_Block_cfgpred(n, i, skip_Tuple(get_Block_cfgpred(n, i)));
69     }
70     new_block = equivalent_node(n);
71     if (new_block != n)
72       exchange (n, new_block);
73
74   } else if (get_opt_optimize() && (get_irn_mode(n) == mode_X)) {
75     /* We will soon visit a block.  Optimize it before visiting! */
76     ir_node *b        = get_nodes_block(n);
77
78     if (!is_Bad(b)) {
79       new_block = equivalent_node(b);
80
81       while (irn_not_visited(b) && (!is_Bad(new_block)) && (new_block != b)) {
82         /* We would have to run gigo if new is bad, so we
83            promote it directly below. Nevertheless, we sometimes reach a block
84            the first time through a dataflow node.  In this case we optimized the
85            block as such and have to promote the Bad here. */
86         assert(((b == new_block) ||
87             get_opt_control_flow_straightening() ||
88             get_opt_control_flow_weak_simplification()) &&
89            ("strange flag setting"));
90         exchange (b, new_block);
91         b = new_block;
92         new_block = equivalent_node(b);
93       }
94       b = new_block;
95     }
96
97     /*
98      * BEWARE: do not kill floating notes here as they might be needed in
99      * valid blocks because of global CSE.
100      */
101     if (is_Bad(b) && get_opt_normalize() &&
102       get_op_pinned(get_irn_op(n)) == op_pin_state_pinned)
103       exchange(n, new_Bad());
104   }
105 }
106
107 /**
108  * Remove dead block by inspecting dominance info
109  */
110 static void remove_dead_blocks(ir_node *block, void *env) {
111   /* delete dead blocks: if we have dominator information, this can easily be detected.
112    * Here, new Bad blocks my be introduced.
113    *
114    * BEWARE: don't kill the end block */
115   if (block != get_irg_end_block(current_ir_graph) &&
116       get_Block_dom_depth(block) == -1 &&
117       get_opt_unreachable_code()) {
118     exchange (block, new_Bad());
119   }
120 }
121
122 /**
123  * Collects all Phi nodes in link list of Block.
124  * Marks all blocks "block_visited" if they contain a node other
125  * than Jmp.
126  * Replaces n by Bad if n is unreachable control flow. We do that
127  * in the post walker, so we catch all blocks.
128  */
129 static void collect_nodes(ir_node *n, void *env) {
130   if (is_no_Block(n)) {
131     ir_node *b = get_nodes_block(n);
132
133     /*
134      * BEWARE: do not kill floating notes here as they might be needed in
135      * valid blocks because of global CSE.
136      */
137     if (is_Bad(b) &&
138       get_op_pinned(get_irn_op(n)) == op_pin_state_pinned) {
139       /* previous merge_blocks() may have killed dead blocks */
140       exchange(n, new_Bad());
141     }
142     else if ((get_irn_op(n) == op_Phi)) {
143       /* Collect Phi nodes to compact ins along with block's ins. */
144       set_irn_link(n, get_irn_link(b));
145       set_irn_link(b, n);
146     }
147     else if ((get_irn_op(n) != op_Jmp) && !is_Bad(b)) {  /* Check for non empty block. */
148       mark_Block_block_visited(b);
149     }
150   }
151 }
152
153 /** Returns true if pred is predecessor of block. */
154 static int is_pred_of(ir_node *pred, ir_node *b) {
155   int i, n;
156
157   for (i = 0, n = get_Block_n_cfgpreds(b); i < n; ++i) {
158     ir_node *b_pred = get_nodes_block(get_Block_cfgpred(b, i));
159     if (b_pred == pred) return 1;
160   }
161   return 0;
162 }
163
164
165 /** Test wether we can optimize away pred block pos of b.
166  *
167  *  @param  b    A block node.
168  *  @param  pos  The position of the predecessor block to judge about.
169  *
170  *  @returns     The number of predecessors
171  *
172  *  The test is rather tricky.
173  *
174  *  The situation is something like the following:
175  *
176  *                 if-block
177  *                  /   \
178  *              then-b  else-b
179  *                  \   /
180  *                    b
181  *
182  *     b merges the control flow of an if-then-else.  We may not remove
183  *     the 'then' _and_ the 'else' block of an 'if' if there is a Phi
184  *     node in b, even if both are empty.  The destruction of this Phi
185  *     requires that a copy is added before the merge.  We have to
186  *     keep one of the case blocks to place the copies in.
187  *
188  *     To perform the test for pos, we must regard preds before pos
189  *     as already removed.
190  **/
191 static int test_whether_dispensable(ir_node *b, int pos) {
192   int i, j, n_preds = 1;
193   int dispensable = 1;
194   ir_node *cfop = get_Block_cfgpred(b, pos);
195   ir_node *pred = get_nodes_block(cfop);
196
197   if (get_Block_block_visited(pred) + 1
198       < get_irg_block_visited(current_ir_graph)) {
199
200     if (!get_opt_optimize() || !get_opt_control_flow_strong_simplification()) {
201       /* Mark block so that is will not be removed: optimization is turned off. */
202       set_Block_block_visited(pred, get_irg_block_visited(current_ir_graph)-1);
203       return 1;
204     }
205
206     /* Seems to be empty. At least we detected this in collect_nodes. */
207     if (!get_irn_link(b)) {
208       /* There are no Phi nodes ==> all predecessors are dispensable. */
209       n_preds = get_Block_n_cfgpreds(pred);
210     } else {
211       /* b's pred blocks and pred's pred blocks must be pairwise disjunct.
212          Work preds < pos as if they were already removed. */
213       for (i = 0; i < pos; i++) {
214         ir_node *b_pred = get_nodes_block(get_Block_cfgpred(b, i));
215         if (get_Block_block_visited(b_pred) + 1
216             < get_irg_block_visited(current_ir_graph)) {
217           for (j = 0; j < get_Block_n_cfgpreds(b_pred); j++) {
218             ir_node *b_pred_pred = get_nodes_block(get_Block_cfgpred(b_pred, j));
219             if (is_pred_of(b_pred_pred, pred)) dispensable = 0;
220           }
221         } else {
222           if (is_pred_of(b_pred, pred)) dispensable = 0;
223         }
224       }
225       for (i = pos +1; i < get_Block_n_cfgpreds(b); i++) {
226         ir_node *b_pred = get_nodes_block(get_Block_cfgpred(b, i));
227         if (is_pred_of(b_pred, pred)) dispensable = 0;
228       }
229       if (!dispensable) {
230         set_Block_block_visited(pred, get_irg_block_visited(current_ir_graph)-1);
231         n_preds = 1;
232       } else {
233         n_preds = get_Block_n_cfgpreds(pred);
234       }
235     }
236   }
237
238   return n_preds;
239 }
240
241
242 /**
243  * This method removed Bad cf preds from Blocks and Phis, and removes
244  * empty blocks.  A block is empty if it only contains Phi and Jmp nodes.
245  *
246  * We first adapt Phi nodes, then Block nodes, as we need the old ins
247  * of the Block to adapt the Phi nodes.  We do this by computing new
248  * in arrays, and then replacing the old ones.  So far we compute new in arrays
249  * for all nodes, not regarding whether there is a possibility for optimization.
250  *
251  * For each predecessor p of a Block b there are three cases:
252  *  1. The predecessor p is a Bad node:  just skip it.  The in array of b shrinks by one.
253  *  2. The predecessor p is empty.  Remove p.  All predecessors of p are now
254  *     predecessors of b.
255  *  3. The predecessor p is a block containing useful code.  Just keep p as is.
256  *
257  * For Phi nodes f we have to check the conditions at the Block of f.
258  * For cases 1 and 3 we proceed as for Blocks.  For case 2 we can have two
259  * cases:
260  *  2a: The old precessor of the Phi f is a Phi pred_f IN THE BLOCK REMOVED.  In this
261  *      case we proceed as for blocks. We remove pred_f.  All
262  *      predecessors of pred_f now are predecessors of f.
263  *  2b: The old predecessor of f is NOT in the block removed. It might be a Phi, too.
264  *      We have to replicate f for each predecessor of the removed block. Or, with
265  *      other words, the removed predecessor block has exactly one predecessor.
266  *
267  * Further there is a special case for self referencing blocks:
268  *
269  *    then_b     else_b                              then_b  else_b
270  *       \      /                                      \      /
271  *        \    /                                        |    /
272  *        pred_b                                        |   /
273  *         |   ____                                     |  /
274  *         |  |    |                                    |  | |    |
275  *         |  |    |       === optimized to ===>        \  | |    |
276  *        loop_b   |                                     loop_b   |
277  *         |  |    |                                      |  |    |
278  *         |  |____|                                      |  |____|
279  *         |                                              |
280  *
281  * If there is a Phi in pred_b, but we remove pred_b, we have to generate a
282  * Phi in loop_b, that has the ins of the Phi in pred_b and a self referencing
283  * backedge.
284  * @@@ It is negotiable whether we should do this ... there might end up a copy
285  * from the Phi in the loop when removing the Phis.
286  */
287 static void optimize_blocks(ir_node *b, void *env) {
288   int i, j, k, n, max_preds, n_preds, p_preds;
289   ir_node *pred, *phi;
290   ir_node **in;
291
292   /* Count the number of predecessor if this block is merged with pred blocks
293      that are empty. */
294   max_preds = 0;
295   for (i = 0, k = get_Block_n_cfgpreds(b); i < k; ++i) {
296     max_preds += test_whether_dispensable(b, i);
297   }
298   in = (ir_node **) malloc(max_preds * sizeof(ir_node *));
299
300 /*-
301   printf(" working on "); DDMN(b);
302   for (i = 0; i < get_Block_n_cfgpreds(b); i++) {
303     pred = get_nodes_block(get_Block_cfgpred(b, i));
304     if (is_Bad(get_Block_cfgpred(b, i))) {
305       printf("  removing Bad %i\n ", i);
306     } else if (get_Block_block_visited(pred) +1
307            < get_irg_block_visited(current_ir_graph)) {
308       printf("  removing pred %i ", i); DDMN(pred);
309     } else { printf("  Nothing to do for "); DDMN(pred); }
310   }
311   * end Debug output -*/
312
313   /*- Fix the Phi nodes of the current block -*/
314   for (phi = get_irn_link(b); phi; ) {
315     assert(get_irn_op(phi) == op_Phi);
316
317     /* Find the new predecessors for the Phi */
318     p_preds = 0;
319     for (i = 0, n = get_Block_n_cfgpreds(b); i < n; ++i) {
320       pred = get_nodes_block(get_Block_cfgpred(b, i));
321
322       if (is_Bad(get_Block_cfgpred(b, i))) {
323         /* case Phi 1: Do nothing */
324       }
325       else if (get_Block_block_visited(pred) + 1
326                  < get_irg_block_visited(current_ir_graph)) {
327         /* case Phi 2: It's an empty block and not yet visited. */
328         ir_node *phi_pred = get_Phi_pred(phi, i);
329
330         for (j = 0, k = get_Block_n_cfgpreds(pred); j < k; j++) {
331           /* because of breaking loops, not all predecessors are Bad-clean,
332            * so we must check this here again */
333           if (! is_Bad(get_Block_cfgpred(pred, j))) {
334             if (get_nodes_block(phi_pred) == pred) {
335               /* case Phi 2a: */
336               assert(get_irn_op(phi_pred) == op_Phi);  /* Block is empty!! */
337
338               in[p_preds++] = get_Phi_pred(phi_pred, j);
339             } else {
340               /* case Phi 2b: */
341               in[p_preds++] = phi_pred;
342             }
343           }
344         }
345
346         /* The Phi_pred node is replaced now if it is a Phi.
347
348            Somehow the removed Phi node can be used legally in loops.
349            Therefore we replace the old phi by the new one.
350
351            Further we have to remove the old Phi node by replacing it
352            by Bad.  Else it will remain in the keepalive array of End
353            and cause illegal situations.  So if there is no loop, we should
354            replace it by Bad.
355         */
356         if (get_nodes_block(phi_pred) == pred) {
357           /* remove the Phi as it might be kept alive. Further there
358              might be other users. */
359           exchange(phi_pred, phi);  /* geht, ist aber doch semantisch falsch! Warum?? */
360         }
361       } else {
362         /* case Phi 3: */
363         in[p_preds++] = get_Phi_pred(phi, i);
364       }
365     }
366
367     /* Fix the node */
368     if (p_preds == 1)
369       /* By removal of Bad ins the Phi might be degenerated. */
370       exchange(phi, in[0]);
371     else
372       set_irn_in(phi, p_preds, in);
373
374     phi = get_irn_link(phi);
375   }
376
377   /*- This happens only if merge between loop backedge and single loop entry.
378       See special case above. -*/
379   for (k = 0, n = get_Block_n_cfgpreds(b); k < n; ++k) {
380     pred = get_nodes_block(get_Block_cfgpred(b, k));
381
382     if (get_Block_block_visited(pred) + 1 < get_irg_block_visited(current_ir_graph)) {
383       /* we found a predecessor block at position k that will be removed */
384       for (phi = get_irn_link(pred); phi;) {
385         /*
386          * the previous phase may already changed the phi, and even
387          * removed it at all, so check here if this node is still a phi
388          */
389         if (get_irn_op(phi) == op_Phi) {
390           int q_preds = 0;
391
392           /* move this phi from the predecessor into the block b */
393           set_nodes_block(phi, b);
394
395           /* first, copy all 0..k-1 predecessors */
396           for (i = 0; i < k; i++) {
397             pred = get_nodes_block(get_Block_cfgpred(b, i));
398
399             if (is_Bad(get_Block_cfgpred(b, i))) {
400               /* Do nothing */
401             } else if (get_Block_block_visited(pred) + 1
402                < get_irg_block_visited(current_ir_graph)) {
403               /* It's an empty block and not yet visited. */
404               for (j = 0; j < get_Block_n_cfgpreds(pred); j++) {
405                 /* @@@ Hier brauche ich Schleifeninformation!!! Kontrollflusskante
406                    muss Rueckwaertskante sein! (An allen vier in[q_preds] = phi
407                    Anweisungen.) Trotzdem tuts bisher!! */
408                 if (! is_Bad(get_Block_cfgpred(pred, j)))
409                   in[q_preds++] = phi;
410               }
411             } else {
412               in[q_preds++] = phi;
413             }
414           }
415
416           /* now we are at k, copy the phi predecessors */
417           pred = get_nodes_block(get_Block_cfgpred(b, k));
418           for (i = 0; i < get_Phi_n_preds(phi); i++) {
419             if (! is_Bad(get_Block_cfgpred(pred, i)))
420               in[q_preds++] = get_Phi_pred(phi, i);
421           }
422
423           /* and now all the rest */
424           for (i = k+1; i < get_Block_n_cfgpreds(b); i++) {
425             pred = get_nodes_block(get_Block_cfgpred(b, i));
426
427             if (is_Bad(get_Block_cfgpred(b, i))) {
428               /* Do nothing */
429             } else if (get_Block_block_visited(pred) +1
430                < get_irg_block_visited(current_ir_graph)) {
431               /* It's an empty block and not yet visited. */
432               for (j = 0; j < get_Block_n_cfgpreds(pred); j++) {
433                 if (! is_Bad(get_Block_cfgpred(pred, j)))
434                   in[q_preds++] = phi;
435               }
436             } else {
437               in[q_preds++] = phi;
438             }
439           }
440
441           /* Fix the node */
442           if (q_preds == 1)
443             exchange(phi, in[0]);
444           else
445             set_irn_in(phi, q_preds, in);
446
447 //          assert(p_preds == q_preds && "Wrong Phi Fix");
448         }
449         phi = get_irn_link(phi);
450       }
451     }
452   }
453
454   /*- Fix the block -*/
455   n_preds = 0;
456   for (i = 0; i < get_Block_n_cfgpreds(b); i++) {
457     pred = get_nodes_block(get_Block_cfgpred(b, i));
458
459     if (is_Bad(get_Block_cfgpred(b, i))) {
460       /* case 1: Do nothing */
461     } else if (get_Block_block_visited(pred) +1
462            < get_irg_block_visited(current_ir_graph)) {
463       /* case 2: It's an empty block and not yet visited. */
464       assert(get_Block_n_cfgpreds(b) > 1);
465                         /* Else it should be optimized by equivalent_node. */
466       for (j = 0; j < get_Block_n_cfgpreds(pred); j++) {
467         ir_node *pred_block = get_Block_cfgpred(pred, j);
468
469         /* because of breaking loops, not all predecessors are Bad-clean,
470          * so we must check this here again */
471         if (! is_Bad(pred_block))
472           in[n_preds++] = pred_block;
473       }
474       /* Remove block as it might be kept alive. */
475       exchange(pred, b/*new_Bad()*/);
476     } else {
477       /* case 3: */
478       in[n_preds++] = get_Block_cfgpred(b, i);
479     }
480   }
481   set_irn_in(b, n_preds, in);
482
483   assert(get_irn_link(b) == NULL || (n_preds == p_preds && "Wrong Phi Fix"));
484
485   free(in);
486 }
487
488
489 /* Optimizations of the control flow that also require changes of Phi nodes.
490  *
491  * This optimization performs two passes over the graph.
492  *
493  * The first pass collects all Phi nodes in a link list in the block
494  * nodes.  Further it performs simple control flow optimizations.
495  * Finally it marks all blocks that do not contain useful
496  * computations, i.e., these blocks might be removed.
497  *
498  * The second pass performs the optimizations intended by this algorithm.
499  * It walks only over block nodes and adapts these and the Phi nodes in these blocks,
500  * which it finds in a linked list computed by the first pass.
501  *
502  * We use the block_visited flag to mark empty blocks in the first
503  * phase.
504  * @@@ It would be better to add a struct in the link field
505  * that keeps the Phi list and the mark.  Place it on an obstack, as
506  * we will lose blocks and thereby generate mem leaks.
507  */
508 void optimize_cf(ir_graph *irg) {
509   int i;
510   ir_node **in;
511   ir_node *end = get_irg_end(irg);
512   ir_graph *rem = current_ir_graph;
513   irg_dom_state dom_state = get_irg_dom_state(current_ir_graph);
514   current_ir_graph = irg;
515
516   /* Handle graph state */
517   assert(get_irg_phase_state(irg) != phase_building);
518   if (get_irg_outs_state(current_ir_graph) == outs_consistent)
519     set_irg_outs_inconsistent(current_ir_graph);
520   if (get_irg_dom_state(current_ir_graph) == dom_consistent)
521     set_irg_dom_inconsistent(current_ir_graph);
522
523   if (dom_state == dom_consistent) {
524     /* we have dominace info, we can kill dead block */
525     irg_block_walk(get_irg_end_block(irg), NULL, remove_dead_blocks, NULL);
526   }
527
528   /* Use block visited flag to mark non-empty blocks. */
529   inc_irg_block_visited(irg);
530   irg_walk(end, merge_blocks, collect_nodes, NULL);
531
532   /* Optimize the standard code. */
533   irg_block_walk(get_irg_end_block(irg), optimize_blocks, NULL, NULL);
534
535   /* Walk all keep alives, optimize them if block, add to new in-array
536      for end if useful. */
537   in = NEW_ARR_F (ir_node *, 1);
538   in[0] = get_nodes_block(end);
539   inc_irg_visited(current_ir_graph);
540
541   for(i = 0; i < get_End_n_keepalives(end); i++) {
542     ir_node *ka = get_End_keepalive(end, i);
543
544     if (irn_not_visited(ka)) {
545       if ((get_irn_op(ka) == op_Block) && Block_not_block_visited(ka)) {
546         set_irg_block_visited(current_ir_graph,  /* Don't walk all the way to Start. */
547               get_irg_block_visited(current_ir_graph)-1);
548         irg_block_walk(ka, optimize_blocks, NULL, NULL);
549         mark_irn_visited(ka);
550         ARR_APP1 (ir_node *, in, ka);
551       } else if (get_irn_op(ka) == op_Phi) {
552         mark_irn_visited(ka);
553         ARR_APP1 (ir_node *, in, ka);
554       }
555     }
556   }
557   /* DEL_ARR_F(end->in);   GL @@@ tut nicht ! */
558   end->in = in;
559
560   /* after optimize_cf(), only Bad data flow may remain. */
561   if (irg_vrfy_bads(irg, BAD_DF | BAD_BLOCK | TUPLE)) {
562     dump_ir_block_graph(irg, "-vrfy-cf");
563     dump_ir_graph(irg, "-vrfy-cf");
564     fprintf(stderr, "VRFY_BAD in optimize_cf()\n");
565   }
566
567   current_ir_graph = rem;
568 }