Implemented debug support.
[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, *on;
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 }
332
333 /* Copies all reachable nodes to a new obstack.  Removes bad inputs
334    from block nodes and the corresponding inputs from Phi nodes.
335    Merges single exit blocks with single entry blocks and removes
336    1-input Phis.
337    Adds all new nodes to a new hash table for cse.  Does not
338    perform cse, so the hash table might contain common subexpressions. */
339 /* Amroq call this emigrate() */
340 void
341 dead_node_elimination(ir_graph *irg) {
342   ir_graph *rem;
343   struct obstack *graveyard_obst = NULL;
344   struct obstack *rebirth_obst   = NULL;
345
346   /* Remember external state of current_ir_graph. */
347   rem = current_ir_graph;
348   current_ir_graph = irg;
349
350   /* Handle graph state */
351   assert(get_irg_phase_state(current_ir_graph) != phase_building);
352   free_outs(current_ir_graph);
353
354   if (get_optimize() && get_opt_dead_node_elimination()) {
355
356     /* A quiet place, where the old obstack can rest in peace,
357        until it will be cremated. */
358     graveyard_obst = irg->obst;
359
360     /* A new obstack, where the reachable nodes will be copied to. */
361     rebirth_obst = (struct obstack *) xmalloc (sizeof (struct obstack));
362     current_ir_graph->obst = rebirth_obst;
363     obstack_init (current_ir_graph->obst);
364
365     /* We also need a new hash table for cse */
366     del_identities (irg->value_table);
367     irg->value_table = new_identities ();
368
369     /* Copy the graph from the old to the new obstack */
370     copy_graph_env();
371
372     /* Free memory from old unoptimized obstack */
373     obstack_free(graveyard_obst, 0);  /* First empty the obstack ... */
374     xfree (graveyard_obst);           /* ... then free it.           */
375   }
376
377   current_ir_graph = rem;
378 }
379
380 /**********************************************************************/
381 /*  Funcionality for inlining                                         */
382 /**********************************************************************/
383
384 /* Copy node for inlineing.  Copies the node by calling copy_node and
385    then updates the entity if it's a local one.  env must be a pointer
386    to the frame type of the procedure. The new entities must be in
387    the link field of the entities. */
388 void
389 copy_node_inline (ir_node *n, void *env) {
390   ir_node *new;
391   type *frame_tp = (type *)env;
392
393   copy_node(n, NULL);
394   if (get_irn_op(n) == op_Sel) {
395     new = get_new_node (n);
396     assert(get_irn_op(new) == op_Sel);
397     if (get_entity_owner(get_Sel_entity(n)) == frame_tp) {
398       set_Sel_entity(new, get_entity_link(get_Sel_entity(n)));
399     }
400   }
401 }
402
403 void inline_method(ir_node *call, ir_graph *called_graph) {
404   ir_node *pre_call;
405   ir_node *post_call, *post_bl;
406   ir_node *in[5];
407   ir_node *end, *end_bl;
408   ir_node **res_pred;
409   ir_node **cf_pred;
410   ir_node *ret, *phi;
411   ir_node *cf_op, *bl;
412   int arity, n_ret, n_exc, n_res, i, j, rem_opt;
413   type *called_frame, *caller_frame;
414
415   if (!get_optimize() || !get_opt_inline()) return;
416   /** Turn off optimizations, this can cause problems when allocating new nodes. **/
417   rem_opt = get_optimize();
418   set_optimize(0);
419
420   /* Handle graph state */
421   assert(get_irg_phase_state(current_ir_graph) != phase_building);
422   assert(get_irg_pinned(current_ir_graph) == pinned);
423   assert(get_irg_pinned(called_graph) == pinned);
424   if (get_irg_outs_state(current_ir_graph) == outs_consistent)
425     set_irg_outs_inconsistent(current_ir_graph);
426
427   /** Check preconditions **/
428   assert(get_irn_op(call) == op_Call);
429   assert(get_Call_type(call) == get_entity_type(get_irg_ent(called_graph)));
430   assert(get_type_tpop(get_Call_type(call)) == type_method);
431   if (called_graph == current_ir_graph) return;
432
433
434   /** Part the Call node into two nodes.  Pre_call collects the parameters of
435           the procedure and later replaces the Start node of the called graph.
436           Post_call is the old Call node and collects the results of the called
437           graph. Both will end up being a tuple.  **/
438   post_bl = get_nodes_Block(call);
439   set_irg_current_block(current_ir_graph, post_bl);
440   /* XxMxPxP of Start + parameter of Call */
441   in[0] = new_Jmp();
442   in[1] = get_Call_mem(call);
443   in[2] = get_irg_frame(current_ir_graph);
444   in[3] = get_irg_globals(current_ir_graph);
445   in[4] = new_Tuple (get_Call_n_params(call), get_Call_param_arr(call));
446   pre_call = new_Tuple(5, in);
447   post_call = call;
448
449   /** Part the block of the Call node into two blocks.
450       The new block gets the ins of the old block, pre_call and all its
451       predecessors and all Phi nodes. **/
452   part_block(pre_call);
453
454   /** Prepare state for dead node elimination **/
455   /* Visited flags in calling irg must be >= flag in called irg.
456      Else walker and arity computation will not work. */
457   if (get_irg_visited(current_ir_graph) <= get_irg_visited(called_graph))
458     set_irg_visited(current_ir_graph, get_irg_visited(called_graph)+1);   /***/
459   if (get_irg_block_visited(current_ir_graph)< get_irg_block_visited(called_graph))
460     set_irg_block_visited(current_ir_graph, get_irg_block_visited(called_graph));
461   /* Set pre_call as new Start node in link field of the start node of
462      calling graph and pre_calls block as new block for the start block
463      of calling graph.
464      Further mark these nodes so that they are not visited by the
465      copying. */
466   set_irn_link(get_irg_start(called_graph), pre_call);
467   set_irn_visited(get_irg_start(called_graph),
468                                   get_irg_visited(current_ir_graph));/***/
469   set_irn_link(get_irg_start_block(called_graph),
470                            get_nodes_Block(pre_call));
471   set_irn_visited(get_irg_start_block(called_graph),
472                                   get_irg_visited(current_ir_graph));  /***/
473
474   /* Initialize for compaction of in arrays */
475   inc_irg_block_visited(current_ir_graph);
476   /*
477       set_Block_block_visited(get_irg_start_block(called_graph),
478       get_irg_block_visited(current_ir_graph) +1 +1); /* count for self edge */
479
480   /*** Replicate local entities of the called_graph ***/
481   /* copy the entities. */
482   called_frame = get_irg_frame_type(called_graph);
483   for (i = 0; i < get_class_n_member(called_frame); i++) {
484     entity *new_ent, *old_ent;
485     old_ent = get_class_member(called_frame, i);
486     new_ent = copy_entity_own(old_ent, get_cur_frame_type());
487     set_entity_link(old_ent, new_ent);
488   }
489
490   /* visited is > than that of called graph.  With this trick visited will
491      remain unchanged so that an outer walker, e.g., searching the call nodes
492      to inline, calling this inline will not visit the inlined nodes. */
493   set_irg_visited(current_ir_graph, get_irg_visited(current_ir_graph)-1);
494
495   /** Performing dead node elimination inlines the graph **/
496   /* Copies the nodes to the obstack of current_ir_graph. Updates links to new
497      entities. */
498   /* @@@ endless loops are not copied!! */
499   irg_walk(get_irg_end(called_graph), copy_node_inline, copy_preds,
500            get_irg_frame_type(called_graph));
501
502   /* Repair called_graph */
503   set_irg_visited(called_graph, get_irg_visited(current_ir_graph));
504   set_irg_block_visited(called_graph, get_irg_block_visited(current_ir_graph));
505   set_Block_block_visited(get_irg_start_block(called_graph), 0);
506
507   /*** Merge the end of the inlined procedure with the call site ***/
508   /* We will turn the old Call node into a Tuple with the following
509      predecessors:
510      -1:  Block of Tuple.
511      0: Phi of all Memories of Return statements.
512      1: Jmp from new Block that merges the control flow from all exception
513          predecessors of the old end block.
514      2: Tuple of all arguments.
515      3: Phi of Exception memories.
516   */
517
518   /** Precompute some values **/
519   end_bl = get_new_node(get_irg_end_block(called_graph));
520   end = get_new_node(get_irg_end(called_graph));
521   arity = get_irn_arity(end_bl);    /* arity = n_exc + n_ret  */
522   n_res = get_method_n_res(get_Call_type(call));
523
524   res_pred = (ir_node **) malloc (n_res * sizeof (ir_node *));
525   cf_pred = (ir_node **) malloc (arity * sizeof (ir_node *));
526
527   set_irg_current_block(current_ir_graph, post_bl); /* just to make sure */
528
529   /** archive keepalives **/
530   for (i = 0; i < get_irn_arity(end); i++)
531     add_End_keepalive(get_irg_end(current_ir_graph), get_irn_n(end, i));
532   /* The new end node will die, but the in array is not on the obstack ... */
533   free_End(end);
534
535   /** Collect control flow from Return blocks to post_calls block. Replace
536       Return nodes by Jump nodes. **/
537   n_ret = 0;
538   for (i = 0; i < arity; i++) {
539     ir_node *ret;
540     ret = get_irn_n(end_bl, i);
541     if (get_irn_op(ret) == op_Return) {
542       cf_pred[n_ret] = new_r_Jmp(current_ir_graph, get_nodes_Block(ret));
543       n_ret++;
544     }
545   }
546   set_irn_in(post_bl, n_ret, cf_pred);
547
548   /** Collect results from Return nodes to post_call. Post_call is
549       turned into a tuple. **/
550   turn_into_tuple(post_call, 4);
551   /* First the Memory-Phi */
552   n_ret = 0;
553   for (i = 0; i < arity; i++) {
554     ret = get_irn_n(end_bl, i);
555     if (get_irn_op(ret) == op_Return) {
556       cf_pred[n_ret] = get_Return_mem(ret);
557       n_ret++;
558     }
559   }
560   phi = new_Phi(n_ret, cf_pred, mode_M);
561   set_Tuple_pred(call, 0, phi);
562   set_irn_link(phi, get_irn_link(post_bl));  /* Conserve Phi-list for further inlinings */
563   set_irn_link(post_bl, phi);
564   /* Now the real results */
565   if (n_res > 0) {
566     for (j = 0; j < n_res; j++) {
567       n_ret = 0;
568       for (i = 0; i < arity; i++) {
569         ret = get_irn_n(end_bl, i);
570         if (get_irn_op(ret) == op_Return) {
571           cf_pred[n_ret] = get_Return_res(ret, j);
572           n_ret++;
573         }
574       }
575       phi = new_Phi(n_ret, cf_pred, get_irn_mode(cf_pred[0]));
576       res_pred[j] = phi;
577       set_irn_link(phi, get_irn_link(post_bl));  /* Conserve Phi-list for further inlinings */
578       set_irn_link(post_bl, phi);
579     }
580     set_Tuple_pred(call, 2, new_Tuple(n_res, res_pred));
581   } else {
582     set_Tuple_pred(call, 2, new_Bad());
583   }
584   /* Finally the exception control flow.  We need to add a Phi node to
585      collect the memory containing the exception objects.  Further we need
586      to add another block to get a correct representation of this Phi.  To
587      this block we add a Jmp that resolves into the X output of the Call
588      when the Call is turned into a tuple. */
589   n_exc = 0;
590   for (i = 0; i < arity; i++) {
591     ir_node *ret;
592     ret = get_irn_n(end_bl, i);
593     if (is_fragile_op(skip_Proj(ret)) || (get_irn_op(skip_Proj(ret)) == op_Raise)) {
594       cf_pred[n_exc] = ret;
595       n_exc++;
596     }
597   }
598   if (n_exc > 0) {
599     new_Block(n_exc, cf_pred);      /* whatch it: current_block is changed! */
600     set_Tuple_pred(call, 1, new_Jmp());
601     /* The Phi for the memories with the exception objects */
602     n_exc = 0;
603     for (i = 0; i < arity; i++) {
604       ir_node *ret;
605       ret = skip_Proj(get_irn_n(end_bl, i));
606       if (get_irn_op(ret) == op_Call) {
607         cf_pred[n_exc] = new_r_Proj(current_ir_graph, get_nodes_Block(ret), ret, mode_M, 3);
608         n_exc++;
609       } else if (is_fragile_op(ret)) {
610         /* We rely that all cfops have the memory output at the same position. */
611         cf_pred[n_exc] = new_r_Proj(current_ir_graph, get_nodes_Block(ret), ret, mode_M, 0);
612         n_exc++;
613       } else if (get_irn_op(ret) == op_Raise) {
614         cf_pred[n_exc] = new_r_Proj(current_ir_graph, get_nodes_Block(ret), ret, mode_M, 1);
615         n_exc++;
616       }
617     }
618     set_Tuple_pred(call, 3, new_Phi(n_exc, cf_pred, mode_M));
619   } else {
620     set_Tuple_pred(call, 1, new_Bad());
621     set_Tuple_pred(call, 3, new_Bad());
622   }
623   free(res_pred);
624   free(cf_pred);
625
626   /*** Correct the control flow to the end node.
627        If the exception control flow from the Call directly branched to the
628        end block we now have the following control flow predecessor pattern:
629        ProjX -> Tuple -> Jmp.
630        We must remove the Jmp along with it's empty block and add Jmp's
631        predecessors as predecessors of this end block. ***/
632   /* find the problematic predecessor of the end block. */
633   end_bl = get_irg_end_block(current_ir_graph);
634   for (i = 0; i < get_Block_n_cfgpreds(end_bl); i++) {
635     cf_op = get_Block_cfgpred(end_bl, i);
636     if (get_irn_op(cf_op) == op_Proj) {
637       cf_op = get_Proj_pred(cf_op);
638       if (get_irn_op(cf_op) == op_Tuple) {
639         cf_op = get_Tuple_pred(cf_op, 1);
640         assert(get_irn_op(cf_op) == op_Jmp);
641         break;
642       }
643     }
644   }
645   /* repair */
646   if (i < get_Block_n_cfgpreds(end_bl)) {
647     bl = get_nodes_Block(cf_op);
648     arity = get_Block_n_cfgpreds(end_bl) + get_Block_n_cfgpreds(bl) - 1;
649     cf_pred = (ir_node **) malloc (arity * sizeof (ir_node *));
650     for (j = 0; j < i; j++)
651       cf_pred[j] = get_Block_cfgpred(end_bl, j);
652     for (j = j; j < i + get_Block_n_cfgpreds(bl); j++)
653       cf_pred[j] = get_Block_cfgpred(bl, j-i);
654     for (j = j; j < arity; j++)
655       cf_pred[j] = get_Block_cfgpred(end_bl, j-get_Block_n_cfgpreds(bl) +1);
656     set_irn_in(end_bl, arity, cf_pred);
657     free(cf_pred);
658   }
659
660   /** Turn cse back on. **/
661   set_optimize(rem_opt);
662 }
663
664 /********************************************************************/
665 /* Apply inlineing to small methods.                                */
666 /********************************************************************/
667
668 static int pos;
669
670 /* It makes no sense to inline too many calls in one procedure. Anyways,
671    I didn't get a version with NEW_ARR_F to run. */
672 #define MAX_INLINE 1024
673
674 static void collect_calls(ir_node *call, void *env) {
675   ir_node **calls = (ir_node **)env;
676   ir_node *addr;
677   tarval *tv;
678   ir_graph *called_irg;
679
680   if (get_irn_op(call) != op_Call) return;
681
682   addr = get_Call_ptr(call);
683   if (get_irn_op(addr) == op_Const) {
684     /* Check whether the constant is the pointer to a compiled entity. */
685     tv = get_Const_tarval(addr);
686     if (tv->u.p.ent) {
687       called_irg = get_entity_irg(tv->u.p.ent);
688       if (called_irg && pos < MAX_INLINE) {
689         /* The Call node calls a locally defined method.  Remember to inline. */
690         calls[pos] = call;
691         pos++;
692       }
693     }
694   }
695 }
696
697
698 /* Inlines all small methods at call sites where the called address comes
699    from a Const node that references the entity representing the called
700    method.
701    The size argument is a rough measure for the code size of the method:
702    Methods where the obstack containing the firm graph is smaller than
703    size are inlined. */
704 void inline_small_irgs(ir_graph *irg, int size) {
705   int i;
706   ir_node *calls[MAX_INLINE];
707   ir_graph *rem = current_ir_graph;
708
709   if (!(get_optimize() && get_opt_inline())) return;
710
711   /*DDME(get_irg_ent(current_ir_graph));*/
712
713   current_ir_graph = irg;
714   /* Handle graph state */
715   assert(get_irg_phase_state(current_ir_graph) != phase_building);
716
717   /* Find Call nodes to inline.
718      (We can not inline during a walk of the graph, as inlineing the same
719      method several times changes the visited flag of the walked graph:
720      after the first inlineing visited of the callee equals visited of
721      the caller.  With the next inlineing both are increased.) */
722   pos = 0;
723   irg_walk(get_irg_end(irg), NULL, collect_calls, (void *) calls);
724
725   if ((pos > 0) && (pos < MAX_INLINE)) {
726     /* There are calls to inline */
727     collect_phiprojs(irg);
728     for (i = 0; i < pos; i++) {
729       tarval *tv;
730       ir_graph *callee;
731       tv = get_Const_tarval(get_Call_ptr(calls[i]));
732       callee = get_entity_irg(tv->u.p.ent);
733       if ((_obstack_memory_used(callee->obst) - obstack_room(callee->obst)) < size) {
734         /*printf(" inlineing "); DDME(tv->u.p.ent);*/
735         inline_method(calls[i], callee);
736       }
737     }
738   }
739
740   current_ir_graph = rem;
741 }
742
743
744 /********************************************************************/
745 /*  Code Placement.  Pinns all floating nodes to a block where they */
746 /*  will be executed only if needed.                                */
747 /********************************************************************/
748
749 static pdeq *worklist;          /* worklist of ir_node*s */
750
751 /* Find the earliest correct block for N.  --- Place N into the
752    same Block as its dominance-deepest Input.  */
753 static void
754 place_floats_early (ir_node *n)
755 {
756   int i, start;
757
758   /* we must not run into an infinite loop */
759   assert (irn_not_visited(n));
760   mark_irn_visited(n);
761
762   /* Place floating nodes. */
763   if (get_op_pinned(get_irn_op(n)) == floats) {
764     int depth = 0;
765     ir_node *b = new_Bad();   /* The block to place this node in */
766
767     assert(get_irn_op(n) != op_Block);
768
769     if ((get_irn_op(n) == op_Const) ||
770         (get_irn_op(n) == op_SymConst) ||
771         (is_Bad(n))) {
772       /* These nodes will not be placed by the loop below. */
773       b = get_irg_start_block(current_ir_graph);
774       depth = 1;
775     }
776
777     /* find the block for this node. */
778     for (i = 0; i < get_irn_arity(n); i++) {
779       ir_node *dep = get_irn_n(n, i);
780       ir_node *dep_block;
781       if ((irn_not_visited(dep)) &&
782           (get_op_pinned(get_irn_op(dep)) == floats)) {
783         place_floats_early (dep);
784       }
785       /* Because all loops contain at least one pinned node, now all
786          our inputs are either pinned or place_early has already
787          been finished on them.  We do not have any unfinished inputs!  */
788       dep_block = get_nodes_Block(dep);
789       if ((!is_Bad(dep_block)) &&
790           (get_Block_dom_depth(dep_block) > depth)) {
791         b = dep_block;
792         depth = get_Block_dom_depth(dep_block);
793       }
794       /* Avoid that the node is placed in the Start block */
795       if ((depth == 1) && (get_Block_dom_depth(get_nodes_Block(n)) > 1)) {
796         b = get_Block_cfg_out(get_irg_start_block(current_ir_graph), 0);
797         assert(b != get_irg_start_block(current_ir_graph));
798         depth = 2;
799       }
800     }
801     set_nodes_Block(n, b);
802   }
803
804   /* Add predecessors of non floating nodes on worklist. */
805   start = (get_irn_op(n) == op_Block) ? 0 : -1;
806   for (i = start; i < get_irn_arity(n); i++) {
807     ir_node *pred = get_irn_n(n, i);
808     if (irn_not_visited(pred)) {
809       pdeq_putr (worklist, pred);
810     }
811   }
812 }
813
814 /* Floating nodes form subgraphs that begin at nodes as Const, Load,
815    Start, Call and end at pinned nodes as Store, Call.  Place_early
816    places all floating nodes reachable from its argument through floating
817    nodes and adds all beginnings at pinned nodes to the worklist. */
818 inline void place_early () {
819   int i;
820   bool del_me;
821
822   assert(worklist);
823   inc_irg_visited(current_ir_graph);
824
825   /* this inits the worklist */
826   place_floats_early (get_irg_end(current_ir_graph));
827
828   /* Work the content of the worklist. */
829   while (!pdeq_empty (worklist)) {
830     ir_node *n = pdeq_getl (worklist);
831     if (irn_not_visited(n)) place_floats_early (n);
832   }
833
834   set_irg_outs_inconsistent(current_ir_graph);
835   current_ir_graph->pinned = pinned;
836 }
837
838
839 /* deepest common dominance ancestor of DCA and CONSUMER of PRODUCER */
840 static ir_node *
841 consumer_dom_dca (ir_node *dca, ir_node *consumer, ir_node *producer)
842 {
843   ir_node *block;
844
845   /* Compute the latest block into which we can place a node so that it is
846      before consumer. */
847   if (get_irn_op(consumer) == op_Phi) {
848     /* our comsumer is a Phi-node, the effective use is in all those
849        blocks through which the Phi-node reaches producer */
850     int i;
851     ir_node *phi_block = get_nodes_Block(consumer);
852     for (i = 0;  i < get_irn_arity(consumer); i++) {
853       if (get_irn_n(consumer, i) == producer) {
854         block = get_nodes_Block(get_Block_cfgpred(phi_block, i));
855       }
856     }
857   } else {
858     assert(is_no_Block(consumer));
859     block = get_nodes_Block(consumer);
860   }
861
862   /* Compute the deepest common ancestor of block and dca. */
863   assert(block);
864   if (!dca) return block;
865   while (get_Block_dom_depth(block) > get_Block_dom_depth(dca))
866     block = get_Block_idom(block);
867   while (get_Block_dom_depth(dca) > get_Block_dom_depth(block))
868     dca = get_Block_idom(dca);
869   while (block != dca)
870     { block = get_Block_idom(block); dca = get_Block_idom(dca); }
871
872   return dca;
873 }
874
875 #if 0
876 /* @@@ Needs loop informations.  Will implement later interprocedural. */
877 static void
878 move_out_of_loops (ir_node *n, ir_node *dca)
879 {
880   assert(dca);
881
882   /* Find the region deepest in the dominator tree dominating
883      dca with the least loop nesting depth, but still dominated
884      by our early placement. */
885   ir_node *best = dca;
886   while (dca != get_nodes_Block(n)) {
887     dca = get_Block_idom(dca);
888     if (!dca) break; /* should we put assert(dca)? */
889     if (get_Block_loop_depth(dca) < get_Block_loop_depth(best)) {
890       best = dca;
891     }
892   }
893   if (get_Block_dom_depth(best) >= get_Block_dom_depth(get_nodes_Block(n)))
894     set_nodes_Block(n, best);
895 }
896 #endif
897
898 /* Find the latest legal block for N and place N into the
899    `optimal' Block between the latest and earliest legal block.
900    The `optimal' block is the dominance-deepest block of those
901    with the least loop-nesting-depth.  This places N out of as many
902    loops as possible and then makes it as controldependant as
903    possible. */
904 static void
905 place_floats_late (ir_node *n)
906 {
907   int i;
908
909   assert (irn_not_visited(n)); /* no multiple placement */
910
911   /* no need to place block nodes, control nodes are already placed. */
912   if ((get_irn_op(n) != op_Block) && (!is_cfop(n)) && (get_irn_mode(n) != mode_X)) {
913     /* Assure that our users are all placed, except the Phi-nodes.
914        --- Each dataflow cycle contains at least one Phi-node.  We
915        have to break the `user has to be placed before the
916        producer' dependance cycle and the Phi-nodes are the
917        place to do so, because we need to base our placement on the
918        final region of our users, which is OK with Phi-nodes, as they
919        are pinned, and they never have to be placed after a
920        producer of one of their inputs in the same block anyway. */
921     for (i = 0; i < get_irn_n_outs(n); i++) {
922       ir_node *succ = get_irn_out(n, i);
923       if (irn_not_visited(succ) && (get_irn_op(succ) != op_Phi))
924         place_floats_late (succ);
925     }
926
927     /* We have to determine the final block of this node... except for constants. */
928     if ((get_op_pinned(get_irn_op(n)) == floats) &&
929         (get_irn_op(n) != op_Const) &&
930         (get_irn_op(n) != op_SymConst)) {
931       ir_node *dca = NULL;      /* deepest common ancestor in the
932                                    dominator tree of all nodes'
933                                    blocks depending on us; our final
934                                    placement has to dominate DCA. */
935       for (i = 0; i < get_irn_n_outs(n); i++) {
936         dca = consumer_dom_dca (dca, get_irn_out(n, i), n);
937       }
938       set_nodes_Block(n, dca);
939 #if 0
940       move_out_of_loops (n, dca);
941 #endif
942     }
943   }
944
945   mark_irn_visited(n);
946
947   /* Add predecessors of all non-floating nodes on list. (Those of floating
948      nodes are placeded already and therefore are marked.)  */
949   for (i = 0; i < get_irn_n_outs(n); i++) {
950     if (irn_not_visited(get_irn_out(n, i))) {
951       pdeq_putr (worklist, get_irn_out(n, i));
952     }
953   }
954 }
955
956 inline void place_late() {
957   assert(worklist);
958   inc_irg_visited(current_ir_graph);
959
960   /* This fills the worklist initially. */
961   place_floats_late(get_irg_start_block(current_ir_graph));
962   /* And now empty the worklist again... */
963   while (!pdeq_empty (worklist)) {
964     ir_node *n = pdeq_getl (worklist);
965     if (irn_not_visited(n)) place_floats_late(n);
966   }
967 }
968
969 void place_code(ir_graph *irg) {
970   ir_graph *rem = current_ir_graph;
971   current_ir_graph = irg;
972
973   if (!(get_optimize() && get_opt_global_cse())) return;
974
975   /* Handle graph state */
976   assert(get_irg_phase_state(irg) != phase_building);
977   if (get_irg_dom_state(irg) != dom_consistent)
978     compute_doms(irg);
979
980   /* Place all floating nodes as early as possible. This guarantees
981      a legal code placement. */
982   worklist = new_pdeq ();
983   place_early();
984
985   /* place_early invalidates the outs, place_late needs them. */
986   compute_outs(irg);
987   /* Now move the nodes down in the dominator tree. This reduces the
988      unnecessary executions of the node. */
989   place_late();
990
991   set_irg_outs_inconsistent(current_ir_graph);
992   del_pdeq (worklist);
993   current_ir_graph = rem;
994 }
995
996
997
998 /********************************************************************/
999 /* Control flow optimization.                                       */
1000 /* Removes Bad control flow predecessors and empty blocks.  A block */
1001 /* is empty if it contains only a Jmp node.                         */
1002 /* */
1003 /********************************************************************/
1004
1005
1006 static void merge_blocks(ir_node *n, void *env) {
1007   int i;
1008   set_irn_link(n, NULL);
1009
1010   if (get_irn_op(n) == op_Block) {
1011     /* Remove Tuples */
1012     for (i = 0; i < get_Block_n_cfgpreds(n); i++)
1013       set_Block_cfgpred(n, i, skip_Tuple(get_Block_cfgpred(n, i)));
1014   } else if (get_irn_mode(n) == mode_X) {
1015     /* We will soon visit a block.  Optimize it before visiting! */
1016     ir_node *b = get_nodes_Block(n);
1017     ir_node *new = equivalent_node(b);
1018     while (irn_not_visited(b) && (!is_Bad(new)) && (new != b)) {
1019       /* We would have to run gigo if new is bad. */
1020       if (get_optimize() && get_opt_control_flow()) exchange (b, new);
1021       b = new;
1022       new = equivalent_node(b);
1023     }
1024     if (is_Bad(new)) exchange (n, new_Bad());
1025   }
1026 }
1027
1028 static void collect_nodes(ir_node *n, void *env) {
1029   int i;
1030   if (is_no_Block(n)) {
1031     ir_node *b = get_nodes_Block(n);
1032
1033     if ((get_irn_op(n) == op_Phi)) {
1034       /* Collect Phi nodes to compact ins along with block's ins. */
1035       set_irn_link(n, get_irn_link(b));
1036       set_irn_link(b, n);
1037     } else if (get_irn_op(n) != op_Jmp) {  /* Check for non empty block. */
1038       mark_Block_block_visited(b);
1039     }
1040   }
1041 }
1042
1043 /* Returns true if pred is pred of block */
1044 int is_pred_of(ir_node *pred, ir_node *b) {
1045   int i;
1046   for (i = 0; i < get_Block_n_cfgpreds(b); i++) {
1047     ir_node *b_pred = get_nodes_Block(get_Block_cfgpred(b, i));
1048     if (b_pred == pred) return 1;
1049   }
1050   return 0;
1051 }
1052
1053 int test_whether_dispensable(ir_node *b, int pos) {
1054   int i, j, n_preds = 1;
1055   int dispensable = 1;
1056   ir_node *cfop = get_Block_cfgpred(b, pos);
1057   ir_node *pred = get_nodes_Block(cfop);
1058
1059   if (get_Block_block_visited(pred) + 1
1060       < get_irg_block_visited(current_ir_graph)) {
1061     if (!get_optimize() || !get_opt_control_flow()) {
1062       /* Mark block so that is will not be removed. */
1063       set_Block_block_visited(pred, get_irg_block_visited(current_ir_graph)-1);
1064       return 1;
1065     }
1066     /* Seems to be empty. */
1067     if (!get_irn_link(b)) {
1068       /* There are no Phi nodes ==> dispensable. */
1069       n_preds = get_Block_n_cfgpreds(pred);
1070     } else {
1071       /* b's pred blocks and pred's pred blocks must be pairwise disjunct.
1072          Work preds < pos as if they were already removed. */
1073       for (i = 0; i < pos; i++) {
1074         ir_node *b_pred = get_nodes_Block(get_Block_cfgpred(b, i));
1075         if (get_Block_block_visited(b_pred) + 1
1076             < get_irg_block_visited(current_ir_graph)) {
1077           for (j = 0; j < get_Block_n_cfgpreds(b_pred); j++) {
1078             ir_node *b_pred_pred = get_nodes_Block(get_Block_cfgpred(b_pred, j));
1079             if (is_pred_of(b_pred_pred, pred)) dispensable = 0;
1080           }
1081         } else {
1082           if (is_pred_of(b_pred, pred)) dispensable = 0;
1083         }
1084       }
1085       for (i = pos +1; i < get_Block_n_cfgpreds(b); i++) {
1086         ir_node *b_pred = get_nodes_Block(get_Block_cfgpred(b, i));
1087         if (is_pred_of(b_pred, pred)) dispensable = 0;
1088       }
1089       if (!dispensable) {
1090         set_Block_block_visited(pred, get_irg_block_visited(current_ir_graph)-1);
1091         n_preds = 1;
1092       } else {
1093         n_preds = get_Block_n_cfgpreds(pred);
1094       }
1095     }
1096   }
1097
1098   return n_preds;
1099 }
1100
1101 void optimize_blocks(ir_node *b, void *env) {
1102   int i, j, k, max_preds, n_preds;
1103   ir_node *pred, *phi;
1104   ir_node **in;
1105
1106   max_preds = 0;
1107   for (i = 0; i < get_Block_n_cfgpreds(b); i++) {
1108     pred = get_Block_cfgpred(b, i);
1109     max_preds += test_whether_dispensable(b, i);
1110   }
1111   in = (ir_node **) malloc(max_preds * sizeof(ir_node *));
1112
1113
1114   /** Debug output **
1115   printf(" working on "); DDMN(b);
1116   for (i = 0; i < get_Block_n_cfgpreds(b); i++) {
1117     pred = get_nodes_Block(get_Block_cfgpred(b, i));
1118     if (is_Bad(get_Block_cfgpred(b, i))) {
1119       printf("  removing Bad %i\n ", i);
1120     } else if (get_Block_block_visited(pred) +1
1121                < get_irg_block_visited(current_ir_graph)) {
1122       printf("  removing pred %i ", i); DDMN(pred);
1123     } else { printf("  Nothing to do for "); DDMN(pred); }
1124   }
1125  ** end Debug output **/
1126
1127   /** Fix the Phi nodes **/
1128   phi = get_irn_link(b);
1129   while (phi) {
1130     assert(get_irn_op(phi) == op_Phi);
1131     /* Find the new predecessors for the Phi */
1132     n_preds = 0;
1133     for (i = 0; i < get_Block_n_cfgpreds(b); i++) {
1134       pred = get_nodes_Block(get_Block_cfgpred(b, i));
1135       if (is_Bad(get_Block_cfgpred(b, i))) {
1136         /* Do nothing */
1137       } else if (get_Block_block_visited(pred) +1
1138                  < get_irg_block_visited(current_ir_graph)) {
1139         /* It's an empty block and not yet visited. */
1140         ir_node *phi_pred = get_Phi_pred(phi, i);
1141         for (j = 0; j < get_Block_n_cfgpreds(pred); j++) {
1142           if (get_nodes_Block(phi_pred) == pred) {
1143             assert(get_irn_op(phi_pred) == op_Phi);  /* Block is empty!! */
1144             in[n_preds] = get_Phi_pred(phi_pred, j);
1145           } else {
1146             in[n_preds] = phi_pred;
1147           }
1148           n_preds++;
1149         }
1150 #if 0
1151         /* @@@ hier brauche ich schleifeninformation!!! Wenn keine Rueckwaertskante
1152            dann darfs auch keine Verwendung geben. */
1153         if (get_nodes_Block(phi_pred) == pred) {
1154           /* remove the Phi as it might be kept alive. Further there
1155              might be other users. */
1156           exchange(phi_pred, phi);  /* geht, is aber doch semantisch falsch! */
1157         }
1158 #endif
1159       } else {
1160         in[n_preds] = get_Phi_pred(phi, i);
1161         n_preds ++;
1162       }
1163     }
1164     /* Fix the node */
1165     set_irn_in(phi, n_preds, in);
1166     phi = get_irn_link(phi);
1167   }
1168
1169   /** Move Phi nodes from removed blocks to this one.
1170       This happens only if merge between loop backedge and single loop entry. **/
1171   for (k = 0; k < get_Block_n_cfgpreds(b); k++) {
1172     pred = get_nodes_Block(get_Block_cfgpred(b, k));
1173     if (get_Block_block_visited(pred) +1
1174         < get_irg_block_visited(current_ir_graph)) {
1175       phi = get_irn_link(pred);
1176       while (phi) {
1177         if (get_irn_op(phi) == op_Phi) {
1178           set_nodes_Block(phi, b);
1179
1180           n_preds = 0;
1181           for (i = 0; i < k; i++) {
1182             pred = get_nodes_Block(get_Block_cfgpred(b, i));
1183             if (is_Bad(get_Block_cfgpred(b, i))) {
1184               /* Do nothing */
1185             } else if (get_Block_block_visited(pred) +1
1186                        < get_irg_block_visited(current_ir_graph)) {
1187               /* It's an empty block and not yet visited. */
1188               for (j = 0; j < get_Block_n_cfgpreds(pred); j++) {
1189                 /* @@@ Hier brauche ich schleifeninformation!!! Kontrllflusskante
1190                    muss Rueckwaertskante sein! (An allen vier in[n_preds] = phi
1191                    Anweisungen.) Trotzdem tuts bisher!! */
1192                 in[n_preds] = phi;
1193                 n_preds++;
1194               }
1195             } else {
1196               in[n_preds] = phi;
1197               n_preds++;
1198             }
1199           }
1200           for (i = 0; i < get_Phi_n_preds(phi); i++) {
1201             in[n_preds] = get_Phi_pred(phi, i);
1202             n_preds++;
1203           }
1204           for (i = k+1; i < get_Block_n_cfgpreds(b); i++) {
1205             pred = get_nodes_Block(get_Block_cfgpred(b, i));
1206             if (is_Bad(get_Block_cfgpred(b, i))) {
1207               /* Do nothing */
1208             } else if (get_Block_block_visited(pred) +1
1209                        < get_irg_block_visited(current_ir_graph)) {
1210               /* It's an empty block and not yet visited. */
1211               for (j = 0; j < get_Block_n_cfgpreds(pred); j++) {
1212                 in[n_preds] = phi;
1213                 n_preds++;
1214               }
1215             } else {
1216               in[n_preds] = phi;
1217               n_preds++;
1218             }
1219           }
1220           set_irn_in(phi, n_preds, in);
1221         }
1222         phi = get_irn_link(phi);
1223       }
1224     }
1225   }
1226
1227   /** Fix the block **/
1228   n_preds = 0;
1229   for (i = 0; i < get_Block_n_cfgpreds(b); i++) {
1230     pred = get_nodes_Block(get_Block_cfgpred(b, i));
1231     if (is_Bad(get_Block_cfgpred(b, i))) {
1232       /* Do nothing */
1233     } else if (get_Block_block_visited(pred) +1
1234                < get_irg_block_visited(current_ir_graph)) {
1235       /* It's an empty block and not yet visited. */
1236       assert(get_Block_n_cfgpreds(b) > 1);
1237                         /* Else it should be optimized by equivalent_node. */
1238       for (j = 0; j < get_Block_n_cfgpreds(pred); j++) {
1239         in[n_preds] = get_Block_cfgpred(pred, j);
1240         n_preds++;
1241       }
1242       /* Remove block as it might be kept alive. */
1243       exchange(pred, b/*new_Bad()*/);
1244     } else {
1245       in[n_preds] = get_Block_cfgpred(b, i);
1246       n_preds ++;
1247     }
1248   }
1249   set_irn_in(b, n_preds, in);
1250   free(in);
1251 }
1252
1253 void optimize_cf(ir_graph *irg) {
1254   int i;
1255   ir_node **in;
1256   ir_node *end = get_irg_end(irg);
1257   ir_graph *rem = current_ir_graph;
1258   current_ir_graph = irg;
1259
1260
1261   /* Handle graph state */
1262   assert(get_irg_phase_state(irg) != phase_building);
1263   if (get_irg_outs_state(current_ir_graph) == outs_consistent)
1264     set_irg_outs_inconsistent(current_ir_graph);
1265   if (get_irg_dom_state(current_ir_graph) == dom_consistent)
1266     set_irg_dom_inconsistent(current_ir_graph);
1267
1268   //DDME(get_irg_ent(irg));
1269
1270   /* Use block visited flag to mark non-empty blocks. */
1271   inc_irg_block_visited(irg);
1272   irg_walk(end, merge_blocks, collect_nodes, NULL);
1273
1274   /* Optimize the standard code. */
1275   irg_block_walk(get_irg_end_block(irg), optimize_blocks, NULL, NULL);
1276
1277   /* Walk all keep alives, optimize them if block, add to new in-array
1278      for end if useful. */
1279   in = NEW_ARR_F (ir_node *, 1);
1280   in[0] = get_nodes_Block(end);
1281
1282   inc_irg_visited(current_ir_graph);
1283   for(i = 0; i < get_End_n_keepalives(end); i++) {
1284     ir_node *ka = get_End_keepalive(end, i);
1285     if (irn_not_visited(ka))
1286       if ((get_irn_op(ka) == op_Block) && Block_not_block_visited(ka)) {
1287         set_irg_block_visited(current_ir_graph,  /* Don't walk all the way to Start. */
1288                               get_irg_block_visited(current_ir_graph)-1);
1289         irg_block_walk(ka, optimize_blocks, NULL, NULL);
1290         mark_irn_visited(ka);
1291         ARR_APP1 (ir_node *, in, ka);
1292       } else if (get_irn_op(ka) == op_Phi) {
1293         mark_irn_visited(ka);
1294         ARR_APP1 (ir_node *, in, ka);
1295       }
1296     }
1297   /* DEL_ARR_F(end->in);   GL @@@ tut nicht ! */
1298   end->in = in;
1299
1300   current_ir_graph = rem;
1301 }