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