674e585ce3bd6070391cd0abb48e26c203c425cd
[libfirm] / ir / ir / irgopt.c
1 /* Coyright (C) 1998 - 2000 by Universitaet Karlsruhe
2 ** All rights reserved.
3 **
4 ** Author: Christian Schaefer
5 **
6 ** Optimizations for a whole ir graph, i.e., a procedure.
7 */
8
9 /* $Id$ */
10
11 #ifdef HAVE_CONFIG_H
12 # include <config.h>
13 #endif
14
15 # include <assert.h>
16
17 # include "irprog.h"
18 # include "irgopt.h"
19 # include "irnode_t.h"
20 # include "irgraph_t.h"
21 # include "iropt_t.h"
22 # include "irgwalk.h"
23 # include "ircons.h"
24 # include "misc.h"
25 # include "irgmod.h"
26 # include "array.h"
27 # include "pset.h"
28 # include "pdeq.h"       /* Fuer code placement */
29 # include "irouts.h"
30
31 /* Defined in iropt.c */
32 pset *new_identities (void);
33 void  del_identities (pset *value_table);
34 void  add_identities   (pset *value_table, ir_node *node);
35
36 /********************************************************************/
37 /* apply optimizations of iropt to all nodes.                       */
38 /********************************************************************/
39
40 void init_link (ir_node *n, void *env) {
41   set_irn_link(n, NULL);
42 }
43
44 void
45 optimize_in_place_wrapper (ir_node *n, void *env) {
46   int i;
47   ir_node *optimized;
48
49   for (i = 0; i < get_irn_arity(n); i++) {
50     optimized = optimize_in_place_2(get_irn_n(n, i));
51     set_irn_n(n, i, optimized);
52   }
53
54   if (get_irn_op(n) == op_Block) {
55     optimized = optimize_in_place_2(n);
56     if (optimized != n) exchange (n, optimized);
57   }
58 }
59
60 void
61 local_optimize_graph (ir_graph *irg) {
62   ir_graph *rem = current_ir_graph;
63   current_ir_graph = irg;
64
65   /* Handle graph state */
66   assert(get_irg_phase_state(irg) != phase_building);
67   if (get_opt_global_cse())
68     set_irg_pinned(current_ir_graph, floats);
69   if (get_irg_outs_state(current_ir_graph) == outs_consistent)
70     set_irg_outs_inconsistent(current_ir_graph);
71   if (get_irg_dom_state(current_ir_graph) == dom_consistent)
72     set_irg_dom_inconsistent(current_ir_graph);
73
74   /* Clean the value_table in irg for the cse. */
75   del_identities(irg->value_table);
76   irg->value_table = new_identities();
77
78   /* walk over the graph */
79   irg_walk(irg->end, init_link, optimize_in_place_wrapper, NULL);
80
81   current_ir_graph = rem;
82 }
83
84 /********************************************************************/
85 /* Routines for dead node elimination / copying garbage collection  */
86 /* of the obstack.                                                  */
87 /********************************************************************/
88
89 /* Remeber the new node in the old node by using a field all nodes have. */
90 inline void
91 set_new_node (ir_node *old, ir_node *new)
92 {
93   old->link = new;
94 }
95
96 /* Get this new node, before the old node is forgotton.*/
97 inline ir_node *
98 get_new_node (ir_node * n)
99 {
100   return n->link;
101 }
102
103 /* We use the block_visited flag to mark that we have computed the
104    number of useful predecessors for this block.
105    Further we encode the new arity in this flag in the old blocks.
106    Remembering the arity is useful, as it saves a lot of pointer
107    accesses.  This function is called for all Phi and Block nodes
108    in a Block. */
109 inline int
110 compute_new_arity(ir_node *b) {
111   int i, res;
112   int irg_v, block_v;
113
114   irg_v = get_irg_block_visited(current_ir_graph);
115   block_v = get_Block_block_visited(b);
116   if (block_v >= irg_v) {
117     /* we computed the number of preds for this block and saved it in the
118        block_v flag */
119     return block_v - irg_v;
120   } else {
121     /* compute the number of good predecessors */
122     res = get_irn_arity(b);
123     for (i = 0; i < get_irn_arity(b); i++)
124       if (get_irn_opcode(get_irn_n(b, i)) == iro_Bad) res--;
125     /* save it in the flag. */
126     set_Block_block_visited(b, irg_v + res);
127     return res;
128   }
129 }
130
131 /* Copies the node to the new obstack. The Ins of the new node point to
132    the predecessors on the old obstack.  For block/phi nodes not all
133    predecessors might be copied.  n->link points to the new node.
134    For Phi and Block nodes the function allocates in-arrays with an arity
135    only for useful predecessors.  The arity is determined by counting
136    the non-bad predecessors of the block. */
137 void
138 copy_node (ir_node *n, void *env) {
139   ir_node *nn, *block;
140   int new_arity;
141
142   if (get_irn_opcode(n) == iro_Block) {
143     block = NULL;
144     new_arity = compute_new_arity(n);
145   } else {
146     block = get_nodes_Block(n);
147     if (get_irn_opcode(n) == iro_Phi) {
148       new_arity = compute_new_arity(block);
149     } else {
150       new_arity = get_irn_arity(n);
151     }
152   }
153   nn = new_ir_node(get_irn_dbg_info(n),
154                    current_ir_graph,
155                    block,
156                    get_irn_op(n),
157                    get_irn_mode(n),
158                    new_arity,
159                    get_irn_in(n));
160   /* Copy the attributes.  These might point to additional data.  If this
161      was allocated on the old obstack the pointers now are dangling.  This
162      frees e.g. the memory of the graph_arr allocated in new_immBlock. */
163   copy_attrs(n, nn);
164   set_new_node(n, nn);
165
166   /*  printf("\n old node: "); DDMSG2(n);
167       printf(" new node: "); DDMSG2(nn); */
168
169 }
170
171 /* Copies new predecessors of old node to new node remembered in link.
172    Spare the Bad predecessors of Phi and Block nodes. */
173 void
174 copy_preds (ir_node *n, void *env) {
175   ir_node *nn, *block;
176   int i, j;
177
178   nn = get_new_node(n);
179
180   /* printf("\n old node: "); DDMSG2(n);
181      printf(" new node: "); DDMSG2(nn);
182      printf(" arities: old: %d, new: %d\n", get_irn_arity(n), get_irn_arity(nn)); */
183
184   if (get_irn_opcode(n) == iro_Block) {
185     /* Don't copy Bad nodes. */
186     j = 0;
187     for (i = 0; i < get_irn_arity(n); i++)
188       if (get_irn_opcode(get_irn_n(n, i)) != iro_Bad) {
189         set_irn_n (nn, j, get_new_node(get_irn_n(n, i)));
190         j++;
191       }
192     /* repair the block visited flag from above misuse. Repair it in both
193        graphs so that the old one can still be used. */
194     set_Block_block_visited(nn, 0);
195     set_Block_block_visited(n, 0);
196     /* Local optimization could not merge two subsequent blocks if
197        in array contained Bads.  Now it's possible.
198        We don't call optimize_in_place as it requires
199        that the fields in ir_graph are set properly. */
200     if (get_Block_n_cfgpreds(nn) == 1
201         && get_irn_op(get_Block_cfgpred(nn, 0)) == op_Jmp)
202       exchange(nn, get_nodes_Block(get_Block_cfgpred(nn, 0)));
203   } else if (get_irn_opcode(n) == iro_Phi) {
204     /* Don't copy node if corresponding predecessor in block is Bad.
205        The Block itself should not be Bad. */
206     block = get_nodes_Block(n);
207     set_irn_n (nn, -1, get_new_node(block));
208     j = 0;
209     for (i = 0; i < get_irn_arity(n); i++)
210       if (get_irn_opcode(get_irn_n(block, i)) != iro_Bad) {
211         set_irn_n (nn, j, get_new_node(get_irn_n(n, i)));
212         j++;
213       }
214     /* If the pre walker reached this Phi after the post walker visited the
215        block block_visited is > 0. */
216     set_Block_block_visited(get_nodes_Block(n), 0);
217     /* Compacting the Phi's ins might generate Phis with only one
218        predecessor. */
219     if (get_irn_arity(n) == 1)
220       exchange(n, get_irn_n(n, 0));
221   } else {
222     for (i = -1; i < get_irn_arity(n); i++)
223       set_irn_n (nn, i, get_new_node(get_irn_n(n, i)));
224   }
225   /* Now the new node is complete.  We can add it to the hash table for cse.
226      @@@ inlinening aborts if we identify End. Why? */
227   if(get_irn_op(nn) != op_End)
228     add_identities (current_ir_graph->value_table, nn);
229 }
230
231 /* Copies the graph recursively, compacts the keepalive of the end node. */
232 void
233 copy_graph () {
234   ir_node *oe, *ne; /* old end, new end */
235   ir_node *ka;      /* keep alive */
236   int i;
237
238   oe = get_irg_end(current_ir_graph);
239   /* copy the end node by hand, allocate dynamic in array! */
240   ne = new_ir_node(get_irn_dbg_info(oe),
241                    current_ir_graph,
242                    NULL,
243                    op_End,
244                    mode_X,
245                    -1,
246                    NULL);
247   /* Copy the attributes.  Well, there might be some in the future... */
248   copy_attrs(oe, ne);
249   set_new_node(oe, ne);
250
251   /* copy the live nodes */
252   irg_walk(get_nodes_Block(oe), copy_node, copy_preds, NULL);
253   /* copy_preds for the end node ... */
254   set_nodes_Block(ne, get_new_node(get_nodes_Block(oe)));
255
256   /** ... and now the keep alives. **/
257   /* First pick the not marked block nodes and walk them.  We must pick these
258      first as else we will oversee blocks reachable from Phis. */
259   for (i = 0; i < get_irn_arity(oe); i++) {
260     ka = get_irn_n(oe, i);
261     if ((get_irn_op(ka) == op_Block) &&
262         (get_irn_visited(ka) < get_irg_visited(current_ir_graph))) {
263       /* We must keep the block alive and copy everything reachable */
264       set_irg_visited(current_ir_graph, get_irg_visited(current_ir_graph)-1);
265       irg_walk(ka, copy_node, copy_preds, NULL);
266       add_End_keepalive(ne, get_new_node(ka));
267     }
268   }
269
270   /* Now pick the Phis.  Here we will keep all! */
271   for (i = 0; i < get_irn_arity(oe); i++) {
272     ka = get_irn_n(oe, i);
273     if ((get_irn_op(ka) == op_Phi)) {
274       if (get_irn_visited(ka) < get_irg_visited(current_ir_graph)) {
275         /* We didn't copy the Phi yet.  */
276         set_irg_visited(current_ir_graph, get_irg_visited(current_ir_graph)-1);
277         irg_walk(ka, copy_node, copy_preds, NULL);
278       }
279       add_End_keepalive(ne, get_new_node(ka));
280     }
281   }
282 }
283
284 /* Copies the graph reachable from current_ir_graph->end to the obstack
285    in current_ir_graph and fixes the environment.
286    Then fixes the fields in current_ir_graph containing nodes of the
287    graph.  */
288 void
289 copy_graph_env () {
290   /* Not all nodes remembered in current_ir_graph might be reachable
291      from the end node.  Assure their link is set to NULL, so that
292      we can test whether new nodes have been computed. */
293   set_irn_link(get_irg_frame  (current_ir_graph), NULL);
294   set_irn_link(get_irg_globals(current_ir_graph), NULL);
295   set_irn_link(get_irg_args   (current_ir_graph), NULL);
296
297   /* we use the block walk flag for removing Bads from Blocks ins. */
298   inc_irg_block_visited(current_ir_graph);
299
300   /* copy the graph */
301   copy_graph();
302
303   /* fix the fields in current_ir_graph */
304   free_End(get_irg_end(current_ir_graph));
305   set_irg_end        (current_ir_graph, get_new_node(get_irg_end(current_ir_graph)));
306   set_irg_end_block  (current_ir_graph, get_new_node(get_irg_end_block(current_ir_graph)));
307   if (get_irn_link(get_irg_frame(current_ir_graph)) == NULL) {
308     copy_node (get_irg_frame(current_ir_graph), NULL);
309     copy_preds(get_irg_frame(current_ir_graph), NULL);
310   }
311   if (get_irn_link(get_irg_globals(current_ir_graph)) == NULL) {
312     copy_node (get_irg_globals(current_ir_graph), NULL);
313     copy_preds(get_irg_globals(current_ir_graph), NULL);
314   }
315   if (get_irn_link(get_irg_args(current_ir_graph)) == NULL) {
316     copy_node (get_irg_args(current_ir_graph), NULL);
317     copy_preds(get_irg_args(current_ir_graph), NULL);
318   }
319   set_irg_start  (current_ir_graph, get_new_node(get_irg_start(current_ir_graph)));
320
321   set_irg_start_block(current_ir_graph,
322                       get_new_node(get_irg_start_block(current_ir_graph)));
323   set_irg_frame  (current_ir_graph, get_new_node(get_irg_frame(current_ir_graph)));
324   set_irg_globals(current_ir_graph, get_new_node(get_irg_globals(current_ir_graph)));
325   set_irg_args   (current_ir_graph, get_new_node(get_irg_args(current_ir_graph)));
326   if (get_irn_link(get_irg_bad(current_ir_graph)) == NULL) {
327     copy_node(get_irg_bad(current_ir_graph), NULL);
328     copy_preds(get_irg_bad(current_ir_graph), NULL);
329   }
330   set_irg_bad(current_ir_graph, get_new_node(get_irg_bad(current_ir_graph)));
331   if (get_irn_link(get_irg_unknown(current_ir_graph)) == NULL) {
332     copy_node(get_irg_unknown(current_ir_graph), NULL);
333     copy_preds(get_irg_unknown(current_ir_graph), NULL);
334   }
335   set_irg_unknown(current_ir_graph, get_new_node(get_irg_unknown(current_ir_graph)));
336 }
337
338 /* Copies all reachable nodes to a new obstack.  Removes bad inputs
339    from block nodes and the corresponding inputs from Phi nodes.
340    Merges single exit blocks with single entry blocks and removes
341    1-input Phis.
342    Adds all new nodes to a new hash table for cse.  Does not
343    perform cse, so the hash table might contain common subexpressions. */
344 /* Amroq call this emigrate() */
345 void
346 dead_node_elimination(ir_graph *irg) {
347   ir_graph *rem;
348   struct obstack *graveyard_obst = NULL;
349   struct obstack *rebirth_obst   = NULL;
350
351   /* Remember external state of current_ir_graph. */
352   rem = current_ir_graph;
353   current_ir_graph = irg;
354
355   /* Handle graph state */
356   assert(get_irg_phase_state(current_ir_graph) != phase_building);
357   free_outs(current_ir_graph);
358
359   if (get_optimize() && get_opt_dead_node_elimination()) {
360
361     /* A quiet place, where the old obstack can rest in peace,
362        until it will be cremated. */
363     graveyard_obst = irg->obst;
364
365     /* A new obstack, where the reachable nodes will be copied to. */
366     rebirth_obst = (struct obstack *) xmalloc (sizeof (struct obstack));
367     current_ir_graph->obst = rebirth_obst;
368     obstack_init (current_ir_graph->obst);
369
370     /* We also need a new hash table for cse */
371     del_identities (irg->value_table);
372     irg->value_table = new_identities ();
373
374     /* Copy the graph from the old to the new obstack */
375     copy_graph_env();
376
377     /* Free memory from old unoptimized obstack */
378     obstack_free(graveyard_obst, 0);  /* First empty the obstack ... */
379     xfree (graveyard_obst);           /* ... then free it.           */
380   }
381
382   current_ir_graph = rem;
383 }
384
385 /**********************************************************************/
386 /*  Funcionality for inlining                                         */
387 /**********************************************************************/
388
389 /* Copy node for inlineing.  Copies the node by calling copy_node and
390    then updates the entity if it's a local one.  env must be a pointer
391    to the frame type of the procedure. The new entities must be in
392    the link field of the entities. */
393 void
394 copy_node_inline (ir_node *n, void *env) {
395   ir_node *new;
396   type *frame_tp = (type *)env;
397
398   copy_node(n, NULL);
399   if (get_irn_op(n) == op_Sel) {
400     new = get_new_node (n);
401     assert(get_irn_op(new) == op_Sel);
402     if (get_entity_owner(get_Sel_entity(n)) == frame_tp) {
403       set_Sel_entity(new, get_entity_link(get_Sel_entity(n)));
404     }
405   }
406 }
407
408 void inline_method(ir_node *call, ir_graph *called_graph) {
409   ir_node *pre_call;
410   ir_node *post_call, *post_bl;
411   ir_node *in[5];
412   ir_node *end, *end_bl;
413   ir_node **res_pred;
414   ir_node **cf_pred;
415   ir_node *ret, *phi;
416   ir_node *cf_op, *bl;
417   int arity, n_ret, n_exc, n_res, i, j, rem_opt;
418   type *called_frame;
419
420   if (!get_optimize() || !get_opt_inline()) return;
421   /** Turn off optimizations, this can cause problems when allocating new nodes. **/
422   rem_opt = get_optimize();
423   set_optimize(0);
424
425   /* Handle graph state */
426   assert(get_irg_phase_state(current_ir_graph) != phase_building);
427   assert(get_irg_pinned(current_ir_graph) == pinned);
428   assert(get_irg_pinned(called_graph) == pinned);
429   if (get_irg_outs_state(current_ir_graph) == outs_consistent)
430     set_irg_outs_inconsistent(current_ir_graph);
431
432   /** Check preconditions **/
433   assert(get_irn_op(call) == op_Call);
434   assert(get_Call_type(call) == get_entity_type(get_irg_ent(called_graph)));
435   assert(get_type_tpop(get_Call_type(call)) == type_method);
436   if (called_graph == current_ir_graph) return;
437
438
439   /** Part the Call node into two nodes.  Pre_call collects the parameters of
440           the procedure and later replaces the Start node of the called graph.
441           Post_call is the old Call node and collects the results of the called
442           graph. Both will end up being a tuple.  **/
443   post_bl = get_nodes_Block(call);
444   set_irg_current_block(current_ir_graph, post_bl);
445   /* XxMxPxP of Start + parameter of Call */
446   in[0] = new_Jmp();
447   in[1] = get_Call_mem(call);
448   in[2] = get_irg_frame(current_ir_graph);
449   in[3] = get_irg_globals(current_ir_graph);
450   in[4] = new_Tuple (get_Call_n_params(call), get_Call_param_arr(call));
451   pre_call = new_Tuple(5, in);
452   post_call = call;
453
454   /** Part the block of the Call node into two blocks.
455       The new block gets the ins of the old block, pre_call and all its
456       predecessors and all Phi nodes. **/
457   part_block(pre_call);
458
459   /** Prepare state for dead node elimination **/
460   /* Visited flags in calling irg must be >= flag in called irg.
461      Else walker and arity computation will not work. */
462   if (get_irg_visited(current_ir_graph) <= get_irg_visited(called_graph))
463     set_irg_visited(current_ir_graph, get_irg_visited(called_graph)+1);   /***/
464   if (get_irg_block_visited(current_ir_graph)< get_irg_block_visited(called_graph))
465     set_irg_block_visited(current_ir_graph, get_irg_block_visited(called_graph));
466   /* Set pre_call as new Start node in link field of the start node of
467      calling graph and pre_calls block as new block for the start block
468      of calling graph.
469      Further mark these nodes so that they are not visited by the
470      copying. */
471   set_irn_link(get_irg_start(called_graph), pre_call);
472   set_irn_visited(get_irg_start(called_graph),
473                                   get_irg_visited(current_ir_graph));/***/
474   set_irn_link(get_irg_start_block(called_graph),
475                            get_nodes_Block(pre_call));
476   set_irn_visited(get_irg_start_block(called_graph),
477                                   get_irg_visited(current_ir_graph));  /***/
478
479   /* Initialize for compaction of in arrays */
480   inc_irg_block_visited(current_ir_graph);
481   /*
482       set_Block_block_visited(get_irg_start_block(called_graph),
483       get_irg_block_visited(current_ir_graph) +1 +1); /* count for self edge */
484
485   /*** Replicate local entities of the called_graph ***/
486   /* copy the entities. */
487   called_frame = get_irg_frame_type(called_graph);
488   for (i = 0; i < get_class_n_member(called_frame); i++) {
489     entity *new_ent, *old_ent;
490     old_ent = get_class_member(called_frame, i);
491     new_ent = copy_entity_own(old_ent, get_cur_frame_type());
492     set_entity_link(old_ent, new_ent);
493   }
494
495   /* visited is > than that of called graph.  With this trick visited will
496      remain unchanged so that an outer walker, e.g., searching the call nodes
497      to inline, calling this inline will not visit the inlined nodes. */
498   set_irg_visited(current_ir_graph, get_irg_visited(current_ir_graph)-1);
499
500   /** Performing dead node elimination inlines the graph **/
501   /* Copies the nodes to the obstack of current_ir_graph. Updates links to new
502      entities. */
503   /* @@@ endless loops are not copied!! */
504   irg_walk(get_irg_end(called_graph), copy_node_inline, copy_preds,
505            get_irg_frame_type(called_graph));
506
507   /* Repair called_graph */
508   set_irg_visited(called_graph, get_irg_visited(current_ir_graph));
509   set_irg_block_visited(called_graph, get_irg_block_visited(current_ir_graph));
510   set_Block_block_visited(get_irg_start_block(called_graph), 0);
511
512   /*** Merge the end of the inlined procedure with the call site ***/
513   /* We will turn the old Call node into a Tuple with the following
514      predecessors:
515      -1:  Block of Tuple.
516      0: Phi of all Memories of Return statements.
517      1: Jmp from new Block that merges the control flow from all exception
518          predecessors of the old end block.
519      2: Tuple of all arguments.
520      3: Phi of Exception memories.
521   */
522
523   /** Precompute some values **/
524   end_bl = get_new_node(get_irg_end_block(called_graph));
525   end = get_new_node(get_irg_end(called_graph));
526   arity = get_irn_arity(end_bl);    /* arity = n_exc + n_ret  */
527   n_res = get_method_n_res(get_Call_type(call));
528
529   res_pred = (ir_node **) malloc (n_res * sizeof (ir_node *));
530   cf_pred = (ir_node **) malloc (arity * sizeof (ir_node *));
531
532   set_irg_current_block(current_ir_graph, post_bl); /* just to make sure */
533
534   /** archive keepalives **/
535   for (i = 0; i < get_irn_arity(end); i++)
536     add_End_keepalive(get_irg_end(current_ir_graph), get_irn_n(end, i));
537   /* The new end node will die, but the in array is not on the obstack ... */
538   free_End(end);
539
540   /** Collect control flow from Return blocks to post_calls block. Replace
541       Return nodes by Jump nodes. **/
542   n_ret = 0;
543   for (i = 0; i < arity; i++) {
544     ir_node *ret;
545     ret = get_irn_n(end_bl, i);
546     if (get_irn_op(ret) == op_Return) {
547       cf_pred[n_ret] = new_r_Jmp(current_ir_graph, get_nodes_Block(ret));
548       n_ret++;
549     }
550   }
551   set_irn_in(post_bl, n_ret, cf_pred);
552
553   /** Collect results from Return nodes to post_call. Post_call is
554       turned into a tuple. **/
555   turn_into_tuple(post_call, 4);
556   /* First the Memory-Phi */
557   n_ret = 0;
558   for (i = 0; i < arity; i++) {
559     ret = get_irn_n(end_bl, i);
560     if (get_irn_op(ret) == op_Return) {
561       cf_pred[n_ret] = get_Return_mem(ret);
562       n_ret++;
563     }
564   }
565   phi = new_Phi(n_ret, cf_pred, mode_M);
566   set_Tuple_pred(call, 0, phi);
567   set_irn_link(phi, get_irn_link(post_bl));  /* Conserve Phi-list for further inlinings */
568   set_irn_link(post_bl, phi);
569   /* Now the real results */
570   if (n_res > 0) {
571     for (j = 0; j < n_res; j++) {
572       n_ret = 0;
573       for (i = 0; i < arity; i++) {
574         ret = get_irn_n(end_bl, i);
575         if (get_irn_op(ret) == op_Return) {
576           cf_pred[n_ret] = get_Return_res(ret, j);
577           n_ret++;
578         }
579       }
580       phi = new_Phi(n_ret, cf_pred, get_irn_mode(cf_pred[0]));
581       res_pred[j] = phi;
582       set_irn_link(phi, get_irn_link(post_bl));  /* Conserve Phi-list for further inlinings */
583       set_irn_link(post_bl, phi);
584     }
585     set_Tuple_pred(call, 2, new_Tuple(n_res, res_pred));
586   } else {
587     set_Tuple_pred(call, 2, new_Bad());
588   }
589   /* Finally the exception control flow.  We need to add a Phi node to
590      collect the memory containing the exception objects.  Further we need
591      to add another block to get a correct representation of this Phi.  To
592      this block we add a Jmp that resolves into the X output of the Call
593      when the Call is turned into a tuple. */
594   n_exc = 0;
595   for (i = 0; i < arity; i++) {
596     ir_node *ret;
597     ret = get_irn_n(end_bl, i);
598     if (is_fragile_op(skip_Proj(ret)) || (get_irn_op(skip_Proj(ret)) == op_Raise)) {
599       cf_pred[n_exc] = ret;
600       n_exc++;
601     }
602   }
603   if (n_exc > 0) {
604     new_Block(n_exc, cf_pred);      /* whatch it: current_block is changed! */
605     set_Tuple_pred(call, 1, new_Jmp());
606     /* The Phi for the memories with the exception objects */
607     n_exc = 0;
608     for (i = 0; i < arity; i++) {
609       ir_node *ret;
610       ret = skip_Proj(get_irn_n(end_bl, i));
611       if (get_irn_op(ret) == op_Call) {
612         cf_pred[n_exc] = new_r_Proj(current_ir_graph, get_nodes_Block(ret), ret, mode_M, 3);
613         n_exc++;
614       } else if (is_fragile_op(ret)) {
615         /* We rely that all cfops have the memory output at the same position. */
616         cf_pred[n_exc] = new_r_Proj(current_ir_graph, get_nodes_Block(ret), ret, mode_M, 0);
617         n_exc++;
618       } else if (get_irn_op(ret) == op_Raise) {
619         cf_pred[n_exc] = new_r_Proj(current_ir_graph, get_nodes_Block(ret), ret, mode_M, 1);
620         n_exc++;
621       }
622     }
623     set_Tuple_pred(call, 3, new_Phi(n_exc, cf_pred, mode_M));
624   } else {
625     set_Tuple_pred(call, 1, new_Bad());
626     set_Tuple_pred(call, 3, new_Bad());
627   }
628   free(res_pred);
629   free(cf_pred);
630
631   /*** Correct the control flow to the end node.
632        If the exception control flow from the Call directly branched to the
633        end block we now have the following control flow predecessor pattern:
634        ProjX -> Tuple -> Jmp.
635        We must remove the Jmp along with it's empty block and add Jmp's
636        predecessors as predecessors of this end block. ***/
637   /* find the problematic predecessor of the end block. */
638   end_bl = get_irg_end_block(current_ir_graph);
639   for (i = 0; i < get_Block_n_cfgpreds(end_bl); i++) {
640     cf_op = get_Block_cfgpred(end_bl, i);
641     if (get_irn_op(cf_op) == op_Proj) {
642       cf_op = get_Proj_pred(cf_op);
643       if (get_irn_op(cf_op) == op_Tuple) {
644         cf_op = get_Tuple_pred(cf_op, 1);
645         assert(get_irn_op(cf_op) == op_Jmp);
646         break;
647       }
648     }
649   }
650   /* repair */
651   if (i < get_Block_n_cfgpreds(end_bl)) {
652     bl = get_nodes_Block(cf_op);
653     arity = get_Block_n_cfgpreds(end_bl) + get_Block_n_cfgpreds(bl) - 1;
654     cf_pred = (ir_node **) malloc (arity * sizeof (ir_node *));
655     for (j = 0; j < i; j++)
656       cf_pred[j] = get_Block_cfgpred(end_bl, j);
657     for (j = j; j < i + get_Block_n_cfgpreds(bl); j++)
658       cf_pred[j] = get_Block_cfgpred(bl, j-i);
659     for (j = j; j < arity; j++)
660       cf_pred[j] = get_Block_cfgpred(end_bl, j-get_Block_n_cfgpreds(bl) +1);
661     set_irn_in(end_bl, arity, cf_pred);
662     free(cf_pred);
663   }
664
665   /** Turn cse back on. **/
666   set_optimize(rem_opt);
667 }
668
669 /********************************************************************/
670 /* Apply inlineing to small methods.                                */
671 /********************************************************************/
672
673 static int pos;
674
675 /* It makes no sense to inline too many calls in one procedure. Anyways,
676    I didn't get a version with NEW_ARR_F to run. */
677 #define MAX_INLINE 1024
678
679 static void collect_calls(ir_node *call, void *env) {
680   ir_node **calls = (ir_node **)env;
681   ir_node *addr;
682   tarval *tv;
683   ir_graph *called_irg;
684
685   if (get_irn_op(call) != op_Call) return;
686
687   addr = get_Call_ptr(call);
688   if (get_irn_op(addr) == op_Const) {
689     /* Check whether the constant is the pointer to a compiled entity. */
690     tv = get_Const_tarval(addr);
691     if (tv->u.p.ent) {
692       called_irg = get_entity_irg(tv->u.p.ent);
693       if (called_irg && pos < MAX_INLINE) {
694         /* The Call node calls a locally defined method.  Remember to inline. */
695         calls[pos] = call;
696         pos++;
697       }
698     }
699   }
700 }
701
702
703 /* Inlines all small methods at call sites where the called address comes
704    from a Const node that references the entity representing the called
705    method.
706    The size argument is a rough measure for the code size of the method:
707    Methods where the obstack containing the firm graph is smaller than
708    size are inlined. */
709 void inline_small_irgs(ir_graph *irg, int size) {
710   int i;
711   ir_node *calls[MAX_INLINE];
712   ir_graph *rem = current_ir_graph;
713
714   if (!(get_optimize() && get_opt_inline())) return;
715
716   /*DDME(get_irg_ent(current_ir_graph));*/
717
718   current_ir_graph = irg;
719   /* Handle graph state */
720   assert(get_irg_phase_state(current_ir_graph) != phase_building);
721
722   /* Find Call nodes to inline.
723      (We can not inline during a walk of the graph, as inlineing the same
724      method several times changes the visited flag of the walked graph:
725      after the first inlineing visited of the callee equals visited of
726      the caller.  With the next inlineing both are increased.) */
727   pos = 0;
728   irg_walk(get_irg_end(irg), NULL, collect_calls, (void *) calls);
729
730   if ((pos > 0) && (pos < MAX_INLINE)) {
731     /* There are calls to inline */
732     collect_phiprojs(irg);
733     for (i = 0; i < pos; i++) {
734       tarval *tv;
735       ir_graph *callee;
736       tv = get_Const_tarval(get_Call_ptr(calls[i]));
737       callee = get_entity_irg(tv->u.p.ent);
738       if ((_obstack_memory_used(callee->obst) - obstack_room(callee->obst)) < size) {
739         /*printf(" inlineing "); DDME(tv->u.p.ent);*/
740         inline_method(calls[i], callee);
741       }
742     }
743   }
744
745   current_ir_graph = rem;
746 }
747
748
749 /********************************************************************/
750 /*  Code Placement.  Pinns all floating nodes to a block where they */
751 /*  will be executed only if needed.                                */
752 /********************************************************************/
753
754 static pdeq *worklist;          /* worklist of ir_node*s */
755
756 /* Find the earliest correct block for N.  --- Place N into the
757    same Block as its dominance-deepest Input.  */
758 static void
759 place_floats_early (ir_node *n)
760 {
761   int i, start;
762
763   /* we must not run into an infinite loop */
764   assert (irn_not_visited(n));
765   mark_irn_visited(n);
766
767   /* Place floating nodes. */
768   if (get_op_pinned(get_irn_op(n)) == floats) {
769     int depth = 0;
770     ir_node *b = new_Bad();   /* The block to place this node in */
771
772     assert(get_irn_op(n) != op_Block);
773
774     if ((get_irn_op(n) == op_Const) ||
775         (get_irn_op(n) == op_SymConst) ||
776         (is_Bad(n))) {
777       /* These nodes will not be placed by the loop below. */
778       b = get_irg_start_block(current_ir_graph);
779       depth = 1;
780     }
781
782     /* find the block for this node. */
783     for (i = 0; i < get_irn_arity(n); i++) {
784       ir_node *dep = get_irn_n(n, i);
785       ir_node *dep_block;
786       if ((irn_not_visited(dep)) &&
787           (get_op_pinned(get_irn_op(dep)) == floats)) {
788         place_floats_early (dep);
789       }
790       /* Because all loops contain at least one pinned node, now all
791          our inputs are either pinned or place_early has already
792          been finished on them.  We do not have any unfinished inputs!  */
793       dep_block = get_nodes_Block(dep);
794       if ((!is_Bad(dep_block)) &&
795           (get_Block_dom_depth(dep_block) > depth)) {
796         b = dep_block;
797         depth = get_Block_dom_depth(dep_block);
798       }
799       /* Avoid that the node is placed in the Start block */
800       if ((depth == 1) && (get_Block_dom_depth(get_nodes_Block(n)) > 1)) {
801         b = get_Block_cfg_out(get_irg_start_block(current_ir_graph), 0);
802         assert(b != get_irg_start_block(current_ir_graph));
803         depth = 2;
804       }
805     }
806     set_nodes_Block(n, b);
807   }
808
809   /* Add predecessors of non floating nodes on worklist. */
810   start = (get_irn_op(n) == op_Block) ? 0 : -1;
811   for (i = start; i < get_irn_arity(n); i++) {
812     ir_node *pred = get_irn_n(n, i);
813     if (irn_not_visited(pred)) {
814       pdeq_putr (worklist, pred);
815     }
816   }
817 }
818
819 /* Floating nodes form subgraphs that begin at nodes as Const, Load,
820    Start, Call and end at pinned nodes as Store, Call.  Place_early
821    places all floating nodes reachable from its argument through floating
822    nodes and adds all beginnings at pinned nodes to the worklist. */
823 inline void place_early () {
824   assert(worklist);
825   inc_irg_visited(current_ir_graph);
826
827   /* this inits the worklist */
828   place_floats_early (get_irg_end(current_ir_graph));
829
830   /* Work the content of the worklist. */
831   while (!pdeq_empty (worklist)) {
832     ir_node *n = pdeq_getl (worklist);
833     if (irn_not_visited(n)) place_floats_early (n);
834   }
835
836   set_irg_outs_inconsistent(current_ir_graph);
837   current_ir_graph->pinned = pinned;
838 }
839
840
841 /* deepest common dominance ancestor of DCA and CONSUMER of PRODUCER */
842 static ir_node *
843 consumer_dom_dca (ir_node *dca, ir_node *consumer, ir_node *producer)
844 {
845   ir_node *block;
846
847   /* Compute the latest block into which we can place a node so that it is
848      before consumer. */
849   if (get_irn_op(consumer) == op_Phi) {
850     /* our comsumer is a Phi-node, the effective use is in all those
851        blocks through which the Phi-node reaches producer */
852     int i;
853     ir_node *phi_block = get_nodes_Block(consumer);
854     for (i = 0;  i < get_irn_arity(consumer); i++) {
855       if (get_irn_n(consumer, i) == producer) {
856         block = get_nodes_Block(get_Block_cfgpred(phi_block, i));
857       }
858     }
859   } else {
860     assert(is_no_Block(consumer));
861     block = get_nodes_Block(consumer);
862   }
863
864   /* Compute the deepest common ancestor of block and dca. */
865   assert(block);
866   if (!dca) return block;
867   while (get_Block_dom_depth(block) > get_Block_dom_depth(dca))
868     block = get_Block_idom(block);
869   while (get_Block_dom_depth(dca) > get_Block_dom_depth(block))
870     dca = get_Block_idom(dca);
871   while (block != dca)
872     { block = get_Block_idom(block); dca = get_Block_idom(dca); }
873
874   return dca;
875 }
876
877 #if 0
878 /* @@@ Needs loop informations.  Will implement later interprocedural. */
879 static void
880 move_out_of_loops (ir_node *n, ir_node *dca)
881 {
882   assert(dca);
883
884   /* Find the region deepest in the dominator tree dominating
885      dca with the least loop nesting depth, but still dominated
886      by our early placement. */
887   ir_node *best = dca;
888   while (dca != get_nodes_Block(n)) {
889     dca = get_Block_idom(dca);
890     if (!dca) break; /* should we put assert(dca)? */
891     if (get_Block_loop_depth(dca) < get_Block_loop_depth(best)) {
892       best = dca;
893     }
894   }
895   if (get_Block_dom_depth(best) >= get_Block_dom_depth(get_nodes_Block(n)))
896     set_nodes_Block(n, best);
897 }
898 #endif
899
900 /* Find the latest legal block for N and place N into the
901    `optimal' Block between the latest and earliest legal block.
902    The `optimal' block is the dominance-deepest block of those
903    with the least loop-nesting-depth.  This places N out of as many
904    loops as possible and then makes it as controldependant as
905    possible. */
906 static void
907 place_floats_late (ir_node *n)
908 {
909   int i;
910
911   assert (irn_not_visited(n)); /* no multiple placement */
912
913   /* no need to place block nodes, control nodes are already placed. */
914   if ((get_irn_op(n) != op_Block) && (!is_cfop(n)) && (get_irn_mode(n) != mode_X)) {
915     /* Assure that our users are all placed, except the Phi-nodes.
916        --- Each dataflow cycle contains at least one Phi-node.  We
917        have to break the `user has to be placed before the
918        producer' dependance cycle and the Phi-nodes are the
919        place to do so, because we need to base our placement on the
920        final region of our users, which is OK with Phi-nodes, as they
921        are pinned, and they never have to be placed after a
922        producer of one of their inputs in the same block anyway. */
923     for (i = 0; i < get_irn_n_outs(n); i++) {
924       ir_node *succ = get_irn_out(n, i);
925       if (irn_not_visited(succ) && (get_irn_op(succ) != op_Phi))
926         place_floats_late (succ);
927     }
928
929     /* We have to determine the final block of this node... except for constants. */
930     if ((get_op_pinned(get_irn_op(n)) == floats) &&
931         (get_irn_op(n) != op_Const) &&
932         (get_irn_op(n) != op_SymConst)) {
933       ir_node *dca = NULL;      /* deepest common ancestor in the
934                                    dominator tree of all nodes'
935                                    blocks depending on us; our final
936                                    placement has to dominate DCA. */
937       for (i = 0; i < get_irn_n_outs(n); i++) {
938         dca = consumer_dom_dca (dca, get_irn_out(n, i), n);
939       }
940       set_nodes_Block(n, dca);
941 #if 0
942       move_out_of_loops (n, dca);
943 #endif
944     }
945   }
946
947   mark_irn_visited(n);
948
949   /* Add predecessors of all non-floating nodes on list. (Those of floating
950      nodes are placeded already and therefore are marked.)  */
951   for (i = 0; i < get_irn_n_outs(n); i++) {
952     if (irn_not_visited(get_irn_out(n, i))) {
953       pdeq_putr (worklist, get_irn_out(n, i));
954     }
955   }
956 }
957
958 inline void place_late() {
959   assert(worklist);
960   inc_irg_visited(current_ir_graph);
961
962   /* This fills the worklist initially. */
963   place_floats_late(get_irg_start_block(current_ir_graph));
964   /* And now empty the worklist again... */
965   while (!pdeq_empty (worklist)) {
966     ir_node *n = pdeq_getl (worklist);
967     if (irn_not_visited(n)) place_floats_late(n);
968   }
969 }
970
971 void place_code(ir_graph *irg) {
972   ir_graph *rem = current_ir_graph;
973   current_ir_graph = irg;
974
975   if (!(get_optimize() && get_opt_global_cse())) return;
976
977   /* Handle graph state */
978   assert(get_irg_phase_state(irg) != phase_building);
979   if (get_irg_dom_state(irg) != dom_consistent)
980     compute_doms(irg);
981
982   /* Place all floating nodes as early as possible. This guarantees
983      a legal code placement. */
984   worklist = new_pdeq ();
985   place_early();
986
987   /* place_early invalidates the outs, place_late needs them. */
988   compute_outs(irg);
989   /* Now move the nodes down in the dominator tree. This reduces the
990      unnecessary executions of the node. */
991   place_late();
992
993   set_irg_outs_inconsistent(current_ir_graph);
994   del_pdeq (worklist);
995   current_ir_graph = rem;
996 }
997
998
999
1000 /********************************************************************/
1001 /* Control flow optimization.                                       */
1002 /* Removes Bad control flow predecessors and empty blocks.  A block */
1003 /* is empty if it contains only a Jmp node.                         */
1004 /* */
1005 /********************************************************************/
1006
1007
1008 static void merge_blocks(ir_node *n, void *env) {
1009   int i;
1010   set_irn_link(n, NULL);
1011
1012   if (get_irn_op(n) == op_Block) {
1013     /* Remove Tuples */
1014     for (i = 0; i < get_Block_n_cfgpreds(n); i++)
1015       set_Block_cfgpred(n, i, skip_Tuple(get_Block_cfgpred(n, i)));
1016   } else if (get_irn_mode(n) == mode_X) {
1017     /* We will soon visit a block.  Optimize it before visiting! */
1018     ir_node *b = get_nodes_Block(n);
1019     ir_node *new = equivalent_node(b);
1020     while (irn_not_visited(b) && (!is_Bad(new)) && (new != b)) {
1021       /* We would have to run gigo if new is bad. */
1022       if (get_optimize() && get_opt_control_flow()) exchange (b, new);
1023       b = new;
1024       new = equivalent_node(b);
1025     }
1026     if (is_Bad(new)) exchange (n, new_Bad());
1027   }
1028 }
1029
1030 static void collect_nodes(ir_node *n, void *env) {
1031   if (is_no_Block(n)) {
1032     ir_node *b = get_nodes_Block(n);
1033
1034     if ((get_irn_op(n) == op_Phi)) {
1035       /* Collect Phi nodes to compact ins along with block's ins. */
1036       set_irn_link(n, get_irn_link(b));
1037       set_irn_link(b, n);
1038     } else if (get_irn_op(n) != op_Jmp) {  /* Check for non empty block. */
1039       mark_Block_block_visited(b);
1040     }
1041   }
1042 }
1043
1044 /* Returns true if pred is pred of block */
1045 int is_pred_of(ir_node *pred, ir_node *b) {
1046   int i;
1047   for (i = 0; i < get_Block_n_cfgpreds(b); i++) {
1048     ir_node *b_pred = get_nodes_Block(get_Block_cfgpred(b, i));
1049     if (b_pred == pred) return 1;
1050   }
1051   return 0;
1052 }
1053
1054 int test_whether_dispensable(ir_node *b, int pos) {
1055   int i, j, n_preds = 1;
1056   int dispensable = 1;
1057   ir_node *cfop = get_Block_cfgpred(b, pos);
1058   ir_node *pred = get_nodes_Block(cfop);
1059
1060   if (get_Block_block_visited(pred) + 1
1061       < get_irg_block_visited(current_ir_graph)) {
1062     if (!get_optimize() || !get_opt_control_flow()) {
1063       /* Mark block so that is will not be removed. */
1064       set_Block_block_visited(pred, get_irg_block_visited(current_ir_graph)-1);
1065       return 1;
1066     }
1067     /* Seems to be empty. */
1068     if (!get_irn_link(b)) {
1069       /* There are no Phi nodes ==> dispensable. */
1070       n_preds = get_Block_n_cfgpreds(pred);
1071     } else {
1072       /* b's pred blocks and pred's pred blocks must be pairwise disjunct.
1073          Work preds < pos as if they were already removed. */
1074       for (i = 0; i < pos; i++) {
1075         ir_node *b_pred = get_nodes_Block(get_Block_cfgpred(b, i));
1076         if (get_Block_block_visited(b_pred) + 1
1077             < get_irg_block_visited(current_ir_graph)) {
1078           for (j = 0; j < get_Block_n_cfgpreds(b_pred); j++) {
1079             ir_node *b_pred_pred = get_nodes_Block(get_Block_cfgpred(b_pred, j));
1080             if (is_pred_of(b_pred_pred, pred)) dispensable = 0;
1081           }
1082         } else {
1083           if (is_pred_of(b_pred, pred)) dispensable = 0;
1084         }
1085       }
1086       for (i = pos +1; i < get_Block_n_cfgpreds(b); i++) {
1087         ir_node *b_pred = get_nodes_Block(get_Block_cfgpred(b, i));
1088         if (is_pred_of(b_pred, pred)) dispensable = 0;
1089       }
1090       if (!dispensable) {
1091         set_Block_block_visited(pred, get_irg_block_visited(current_ir_graph)-1);
1092         n_preds = 1;
1093       } else {
1094         n_preds = get_Block_n_cfgpreds(pred);
1095       }
1096     }
1097   }
1098
1099   return n_preds;
1100 }
1101
1102 void optimize_blocks(ir_node *b, void *env) {
1103   int i, j, k, max_preds, n_preds;
1104   ir_node *pred, *phi;
1105   ir_node **in;
1106
1107   max_preds = 0;
1108   for (i = 0; i < get_Block_n_cfgpreds(b); i++) {
1109     pred = get_Block_cfgpred(b, i);
1110     max_preds += test_whether_dispensable(b, i);
1111   }
1112   in = (ir_node **) malloc(max_preds * sizeof(ir_node *));
1113
1114
1115   /** Debug output **
1116   printf(" working on "); DDMN(b);
1117   for (i = 0; i < get_Block_n_cfgpreds(b); i++) {
1118     pred = get_nodes_Block(get_Block_cfgpred(b, i));
1119     if (is_Bad(get_Block_cfgpred(b, i))) {
1120       printf("  removing Bad %i\n ", i);
1121     } else if (get_Block_block_visited(pred) +1
1122                < get_irg_block_visited(current_ir_graph)) {
1123       printf("  removing pred %i ", i); DDMN(pred);
1124     } else { printf("  Nothing to do for "); DDMN(pred); }
1125   }
1126  ** end Debug output **/
1127
1128   /** Fix the Phi nodes **/
1129   phi = get_irn_link(b);
1130   while (phi) {
1131     assert(get_irn_op(phi) == op_Phi);
1132     /* Find the new predecessors for the Phi */
1133     n_preds = 0;
1134     for (i = 0; i < get_Block_n_cfgpreds(b); i++) {
1135       pred = get_nodes_Block(get_Block_cfgpred(b, i));
1136       if (is_Bad(get_Block_cfgpred(b, i))) {
1137         /* Do nothing */
1138       } else if (get_Block_block_visited(pred) +1
1139                  < get_irg_block_visited(current_ir_graph)) {
1140         /* It's an empty block and not yet visited. */
1141         ir_node *phi_pred = get_Phi_pred(phi, i);
1142         for (j = 0; j < get_Block_n_cfgpreds(pred); j++) {
1143           if (get_nodes_Block(phi_pred) == pred) {
1144             assert(get_irn_op(phi_pred) == op_Phi);  /* Block is empty!! */
1145             in[n_preds] = get_Phi_pred(phi_pred, j);
1146           } else {
1147             in[n_preds] = phi_pred;
1148           }
1149           n_preds++;
1150         }
1151 #if 0
1152         /* @@@ hier brauche ich schleifeninformation!!! Wenn keine Rueckwaertskante
1153            dann darfs auch keine Verwendung geben. */
1154         if (get_nodes_Block(phi_pred) == pred) {
1155           /* remove the Phi as it might be kept alive. Further there
1156              might be other users. */
1157           exchange(phi_pred, phi);  /* geht, is aber doch semantisch falsch! */
1158         }
1159 #endif
1160       } else {
1161         in[n_preds] = get_Phi_pred(phi, i);
1162         n_preds ++;
1163       }
1164     }
1165     /* Fix the node */
1166     set_irn_in(phi, n_preds, in);
1167     phi = get_irn_link(phi);
1168   }
1169
1170   /** Move Phi nodes from removed blocks to this one.
1171       This happens only if merge between loop backedge and single loop entry. **/
1172   for (k = 0; k < get_Block_n_cfgpreds(b); k++) {
1173     pred = get_nodes_Block(get_Block_cfgpred(b, k));
1174     if (get_Block_block_visited(pred) +1
1175         < get_irg_block_visited(current_ir_graph)) {
1176       phi = get_irn_link(pred);
1177       while (phi) {
1178         if (get_irn_op(phi) == op_Phi) {
1179           set_nodes_Block(phi, b);
1180
1181           n_preds = 0;
1182           for (i = 0; i < k; i++) {
1183             pred = get_nodes_Block(get_Block_cfgpred(b, i));
1184             if (is_Bad(get_Block_cfgpred(b, i))) {
1185               /* Do nothing */
1186             } else if (get_Block_block_visited(pred) +1
1187                        < get_irg_block_visited(current_ir_graph)) {
1188               /* It's an empty block and not yet visited. */
1189               for (j = 0; j < get_Block_n_cfgpreds(pred); j++) {
1190                 /* @@@ Hier brauche ich schleifeninformation!!! Kontrllflusskante
1191                    muss Rueckwaertskante sein! (An allen vier in[n_preds] = phi
1192                    Anweisungen.) Trotzdem tuts bisher!! */
1193                 in[n_preds] = phi;
1194                 n_preds++;
1195               }
1196             } else {
1197               in[n_preds] = phi;
1198               n_preds++;
1199             }
1200           }
1201           for (i = 0; i < get_Phi_n_preds(phi); i++) {
1202             in[n_preds] = get_Phi_pred(phi, i);
1203             n_preds++;
1204           }
1205           for (i = k+1; i < get_Block_n_cfgpreds(b); i++) {
1206             pred = get_nodes_Block(get_Block_cfgpred(b, i));
1207             if (is_Bad(get_Block_cfgpred(b, i))) {
1208               /* Do nothing */
1209             } else if (get_Block_block_visited(pred) +1
1210                        < get_irg_block_visited(current_ir_graph)) {
1211               /* It's an empty block and not yet visited. */
1212               for (j = 0; j < get_Block_n_cfgpreds(pred); j++) {
1213                 in[n_preds] = phi;
1214                 n_preds++;
1215               }
1216             } else {
1217               in[n_preds] = phi;
1218               n_preds++;
1219             }
1220           }
1221           set_irn_in(phi, n_preds, in);
1222         }
1223         phi = get_irn_link(phi);
1224       }
1225     }
1226   }
1227
1228   /** Fix the block **/
1229   n_preds = 0;
1230   for (i = 0; i < get_Block_n_cfgpreds(b); i++) {
1231     pred = get_nodes_Block(get_Block_cfgpred(b, i));
1232     if (is_Bad(get_Block_cfgpred(b, i))) {
1233       /* Do nothing */
1234     } else if (get_Block_block_visited(pred) +1
1235                < get_irg_block_visited(current_ir_graph)) {
1236       /* It's an empty block and not yet visited. */
1237       assert(get_Block_n_cfgpreds(b) > 1);
1238                         /* Else it should be optimized by equivalent_node. */
1239       for (j = 0; j < get_Block_n_cfgpreds(pred); j++) {
1240         in[n_preds] = get_Block_cfgpred(pred, j);
1241         n_preds++;
1242       }
1243       /* Remove block as it might be kept alive. */
1244       exchange(pred, b/*new_Bad()*/);
1245     } else {
1246       in[n_preds] = get_Block_cfgpred(b, i);
1247       n_preds ++;
1248     }
1249   }
1250   set_irn_in(b, n_preds, in);
1251   free(in);
1252 }
1253
1254 void optimize_cf(ir_graph *irg) {
1255   int i;
1256   ir_node **in;
1257   ir_node *end = get_irg_end(irg);
1258   ir_graph *rem = current_ir_graph;
1259   current_ir_graph = irg;
1260
1261
1262   /* Handle graph state */
1263   assert(get_irg_phase_state(irg) != phase_building);
1264   if (get_irg_outs_state(current_ir_graph) == outs_consistent)
1265     set_irg_outs_inconsistent(current_ir_graph);
1266   if (get_irg_dom_state(current_ir_graph) == dom_consistent)
1267     set_irg_dom_inconsistent(current_ir_graph);
1268
1269   //DDME(get_irg_ent(irg));
1270
1271   /* Use block visited flag to mark non-empty blocks. */
1272   inc_irg_block_visited(irg);
1273   irg_walk(end, merge_blocks, collect_nodes, NULL);
1274
1275   /* Optimize the standard code. */
1276   irg_block_walk(get_irg_end_block(irg), optimize_blocks, NULL, NULL);
1277
1278   /* Walk all keep alives, optimize them if block, add to new in-array
1279      for end if useful. */
1280   in = NEW_ARR_F (ir_node *, 1);
1281   in[0] = get_nodes_Block(end);
1282
1283   inc_irg_visited(current_ir_graph);
1284   for(i = 0; i < get_End_n_keepalives(end); i++) {
1285     ir_node *ka = get_End_keepalive(end, i);
1286     if (irn_not_visited(ka))
1287       if ((get_irn_op(ka) == op_Block) && Block_not_block_visited(ka)) {
1288         set_irg_block_visited(current_ir_graph,  /* Don't walk all the way to Start. */
1289                               get_irg_block_visited(current_ir_graph)-1);
1290         irg_block_walk(ka, optimize_blocks, NULL, NULL);
1291         mark_irn_visited(ka);
1292         ARR_APP1 (ir_node *, in, ka);
1293       } else if (get_irn_op(ka) == op_Phi) {
1294         mark_irn_visited(ka);
1295         ARR_APP1 (ir_node *, in, ka);
1296       }
1297     }
1298   /* DEL_ARR_F(end->in);   GL @@@ tut nicht ! */
1299   end->in = in;
1300
1301   current_ir_graph = rem;
1302 }