Added Exception marking support --flo
[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(current_ir_graph,
154                    block,
155                    get_irn_op(n),
156                    get_irn_mode(n),
157                    new_arity,
158                    get_irn_in(n));
159   /* Copy the attributes.  These might point to additional data.  If this
160      was allocated on the old obstack the pointers now are dangling.  This
161      frees e.g. the memory of the graph_arr allocated in new_immBlock. */
162   copy_attrs(n, nn);
163   set_new_node(n, nn);
164
165   /*  printf("\n old node: "); DDMSG2(n);
166       printf(" new node: "); DDMSG2(nn); */
167
168 }
169
170 /* Copies new predecessors of old node to new node remembered in link.
171    Spare the Bad predecessors of Phi and Block nodes. */
172 void
173 copy_preds (ir_node *n, void *env) {
174   ir_node *nn, *block, *on;
175   int i, j;
176
177   nn = get_new_node(n);
178
179   /* printf("\n old node: "); DDMSG2(n);
180      printf(" new node: "); DDMSG2(nn);
181      printf(" arities: old: %d, new: %d\n", get_irn_arity(n), get_irn_arity(nn)); */
182
183   if (get_irn_opcode(n) == iro_Block) {
184     /* Don't copy Bad nodes. */
185     j = 0;
186     for (i = 0; i < get_irn_arity(n); i++)
187       if (get_irn_opcode(get_irn_n(n, i)) != iro_Bad) {
188         set_irn_n (nn, j, get_new_node(get_irn_n(n, i)));
189         j++;
190       }
191     /* repair the block visited flag from above misuse. Repair it in both
192        graphs so that the old one can still be used. */
193     set_Block_block_visited(nn, 0);
194     set_Block_block_visited(n, 0);
195     /* Local optimization could not merge two subsequent blocks if
196        in array contained Bads.  Now it's possible.
197        We don't call optimize_in_place as it requires
198        that the fields in ir_graph are set properly. */
199     if (get_Block_n_cfgpreds(nn) == 1
200         && get_irn_op(get_Block_cfgpred(nn, 0)) == op_Jmp)
201       exchange(nn, get_nodes_Block(get_Block_cfgpred(nn, 0)));
202   } else if (get_irn_opcode(n) == iro_Phi) {
203     /* Don't copy node if corresponding predecessor in block is Bad.
204        The Block itself should not be Bad. */
205     block = get_nodes_Block(n);
206     set_irn_n (nn, -1, get_new_node(block));
207     j = 0;
208     for (i = 0; i < get_irn_arity(n); i++)
209       if (get_irn_opcode(get_irn_n(block, i)) != iro_Bad) {
210         set_irn_n (nn, j, get_new_node(get_irn_n(n, i)));
211         j++;
212       }
213     /* If the pre walker reached this Phi after the post walker visited the
214        block block_visited is > 0. */
215     set_Block_block_visited(get_nodes_Block(n), 0);
216     /* Compacting the Phi's ins might generate Phis with only one
217        predecessor. */
218     if (get_irn_arity(n) == 1)
219       exchange(n, get_irn_n(n, 0));
220   } else {
221     for (i = -1; i < get_irn_arity(n); i++)
222       set_irn_n (nn, i, get_new_node(get_irn_n(n, i)));
223   }
224   /* Now the new node is complete.  We can add it to the hash table for cse.
225      @@@ inlinening aborts if we identify End. Why? */
226   if(get_irn_op(nn) != op_End)
227     add_identities (current_ir_graph->value_table, nn);
228 }
229
230 /* Copies the graph recursively, compacts the keepalive of the end node. */
231 void
232 copy_graph () {
233   ir_node *oe, *ne; /* old end, new end */
234   ir_node *ka;      /* keep alive */
235   int i;
236
237   oe = get_irg_end(current_ir_graph);
238   /* copy the end node by hand, allocate dynamic in array! */
239   ne = new_ir_node(current_ir_graph,
240                    NULL,
241                    op_End,
242                    mode_X,
243                    -1,
244                    NULL);
245   /* Copy the attributes.  Well, there might be some in the future... */
246   copy_attrs(oe, ne);
247   set_new_node(oe, ne);
248
249   /* copy the live nodes */
250   irg_walk(get_nodes_Block(oe), copy_node, copy_preds, NULL);
251   /* copy_preds for the end node ... */
252   set_nodes_Block(ne, get_new_node(get_nodes_Block(oe)));
253
254   /** ... and now the keep alives. **/
255   /* First pick the not marked block nodes and walk them.  We must pick these
256      first as else we will oversee blocks reachable from Phis. */
257   for (i = 0; i < get_irn_arity(oe); i++) {
258     ka = get_irn_n(oe, i);
259     if ((get_irn_op(ka) == op_Block) &&
260         (get_irn_visited(ka) < get_irg_visited(current_ir_graph))) {
261       /* We must keep the block alive and copy everything reachable */
262       set_irg_visited(current_ir_graph, get_irg_visited(current_ir_graph)-1);
263       irg_walk(ka, copy_node, copy_preds, NULL);
264       add_End_keepalive(ne, get_new_node(ka));
265     }
266   }
267
268   /* Now pick the Phis.  Here we will keep all! */
269   for (i = 0; i < get_irn_arity(oe); i++) {
270     ka = get_irn_n(oe, i);
271     if ((get_irn_op(ka) == op_Phi)) {
272       if (get_irn_visited(ka) < get_irg_visited(current_ir_graph)) {
273         /* We didn't copy the Phi yet.  */
274         set_irg_visited(current_ir_graph, get_irg_visited(current_ir_graph)-1);
275         irg_walk(ka, copy_node, copy_preds, NULL);
276       }
277       add_End_keepalive(ne, get_new_node(ka));
278     }
279   }
280 }
281
282 /* Copies the graph reachable from current_ir_graph->end to the obstack
283    in current_ir_graph and fixes the environment.
284    Then fixes the fields in current_ir_graph containing nodes of the
285    graph.  */
286 void
287 copy_graph_env () {
288   /* Not all nodes remembered in current_ir_graph might be reachable
289      from the end node.  Assure their link is set to NULL, so that
290      we can test whether new nodes have been computed. */
291   set_irn_link(get_irg_frame  (current_ir_graph), NULL);
292   set_irn_link(get_irg_globals(current_ir_graph), NULL);
293   set_irn_link(get_irg_args   (current_ir_graph), NULL);
294
295   /* we use the block walk flag for removing Bads from Blocks ins. */
296   inc_irg_block_visited(current_ir_graph);
297
298   /* copy the graph */
299   copy_graph();
300
301   /* fix the fields in current_ir_graph */
302   free_End(get_irg_end(current_ir_graph));
303   set_irg_end        (current_ir_graph, get_new_node(get_irg_end(current_ir_graph)));
304   set_irg_end_block  (current_ir_graph, get_new_node(get_irg_end_block(current_ir_graph)));
305   if (get_irn_link(get_irg_frame(current_ir_graph)) == NULL) {
306     copy_node (get_irg_frame(current_ir_graph), NULL);
307     copy_preds(get_irg_frame(current_ir_graph), NULL);
308   }
309   if (get_irn_link(get_irg_globals(current_ir_graph)) == NULL) {
310     copy_node (get_irg_globals(current_ir_graph), NULL);
311     copy_preds(get_irg_globals(current_ir_graph), NULL);
312   }
313   if (get_irn_link(get_irg_args(current_ir_graph)) == NULL) {
314     copy_node (get_irg_args(current_ir_graph), NULL);
315     copy_preds(get_irg_args(current_ir_graph), NULL);
316   }
317   set_irg_start  (current_ir_graph, get_new_node(get_irg_start(current_ir_graph)));
318
319   set_irg_start_block(current_ir_graph,
320                       get_new_node(get_irg_start_block(current_ir_graph)));
321   set_irg_frame  (current_ir_graph, get_new_node(get_irg_frame(current_ir_graph)));
322   set_irg_globals(current_ir_graph, get_new_node(get_irg_globals(current_ir_graph)));
323   set_irg_args   (current_ir_graph, get_new_node(get_irg_args(current_ir_graph)));
324   if (get_irn_link(get_irg_bad(current_ir_graph)) == NULL) {
325     copy_node(get_irg_bad(current_ir_graph), NULL);
326     copy_preds(get_irg_bad(current_ir_graph), NULL);
327   }
328   set_irg_bad(current_ir_graph, get_new_node(get_irg_bad(current_ir_graph)));
329 }
330
331 /* Copies all reachable nodes to a new obstack.  Removes bad inputs
332    from block nodes and the corresponding inputs from Phi nodes.
333    Merges single exit blocks with single entry blocks and removes
334    1-input Phis.
335    Adds all new nodes to a new hash table for cse.  Does not
336    perform cse, so the hash table might contain common subexpressions. */
337 /* Amroq call this emigrate() */
338 void
339 dead_node_elimination(ir_graph *irg) {
340   ir_graph *rem;
341   struct obstack *graveyard_obst = NULL;
342   struct obstack *rebirth_obst   = NULL;
343
344   /* Remember external state of current_ir_graph. */
345   rem = current_ir_graph;
346   current_ir_graph = irg;
347
348   /* Handle graph state */
349   assert(get_irg_phase_state(current_ir_graph) != phase_building);
350   free_outs(current_ir_graph);
351
352   if (get_optimize() && get_opt_dead_node_elimination()) {
353
354     /* A quiet place, where the old obstack can rest in peace,
355        until it will be cremated. */
356     graveyard_obst = irg->obst;
357
358     /* A new obstack, where the reachable nodes will be copied to. */
359     rebirth_obst = (struct obstack *) xmalloc (sizeof (struct obstack));
360     current_ir_graph->obst = rebirth_obst;
361     obstack_init (current_ir_graph->obst);
362
363     /* We also need a new hash table for cse */
364     del_identities (irg->value_table);
365     irg->value_table = new_identities ();
366
367     /* Copy the graph from the old to the new obstack */
368     copy_graph_env();
369
370     /* Free memory from old unoptimized obstack */
371     obstack_free(graveyard_obst, 0);  /* First empty the obstack ... */
372     xfree (graveyard_obst);           /* ... then free it.           */
373   }
374
375   current_ir_graph = rem;
376 }
377
378 /**********************************************************************/
379 /*  Funcionality for inlining                                         */
380 /**********************************************************************/
381
382 /* Copy node for inlineing.  Copies the node by calling copy_node and
383    then updates the entity if it's a local one.  env must be a pointer
384    to the frame type of the procedure. The new entities must be in
385    the link field of the entities. */
386 void
387 copy_node_inline (ir_node *n, void *env) {
388   ir_node *new;
389   type *frame_tp = (type *)env;
390
391   copy_node(n, NULL);
392   if (get_irn_op(n) == op_Sel) {
393     new = get_new_node (n);
394     assert(get_irn_op(new) == op_Sel);
395     if (get_entity_owner(get_Sel_entity(n)) == frame_tp) {
396       set_Sel_entity(new, get_entity_link(get_Sel_entity(n)));
397     }
398   }
399 }
400
401 void inline_method(ir_node *call, ir_graph *called_graph) {
402   ir_node *pre_call;
403   ir_node *post_call, *post_bl;
404   ir_node *in[5];
405   ir_node *end, *end_bl;
406   ir_node **res_pred;
407   ir_node **cf_pred;
408   ir_node *ret, *phi;
409   ir_node *cf_op, *bl;
410   int arity, n_ret, n_exc, n_res, i, j, rem_opt;
411   type *called_frame, *caller_frame;
412
413   if (!get_optimize() || !get_opt_inline()) return;
414   /** Turn off optimizations, this can cause problems when allocating new nodes. **/
415   rem_opt = get_optimize();
416   set_optimize(0);
417
418   /* Handle graph state */
419   assert(get_irg_phase_state(current_ir_graph) != phase_building);
420   assert(get_irg_pinned(current_ir_graph) == pinned);
421   assert(get_irg_pinned(called_graph) == pinned);
422   if (get_irg_outs_state(current_ir_graph) == outs_consistent)
423     set_irg_outs_inconsistent(current_ir_graph);
424
425   /** Check preconditions **/
426   assert(get_irn_op(call) == op_Call);
427   assert(get_Call_type(call) == get_entity_type(get_irg_ent(called_graph)));
428   assert(get_type_tpop(get_Call_type(call)) == type_method);
429   if (called_graph == current_ir_graph) return;
430
431
432   /** Part the Call node into two nodes.  Pre_call collects the parameters of
433           the procedure and later replaces the Start node of the called graph.
434           Post_call is the old Call node and collects the results of the called
435           graph. Both will end up being a tuple.  **/
436   post_bl = get_nodes_Block(call);
437   set_irg_current_block(current_ir_graph, post_bl);
438   /* XxMxPxP of Start + parameter of Call */
439   in[0] = new_Jmp();
440   in[1] = get_Call_mem(call);
441   in[2] = get_irg_frame(current_ir_graph);
442   in[3] = get_irg_globals(current_ir_graph);
443   in[4] = new_Tuple (get_Call_n_params(call), get_Call_param_arr(call));
444   pre_call = new_Tuple(5, in);
445   post_call = call;
446
447   /** Part the block of the Call node into two blocks.
448       The new block gets the ins of the old block, pre_call and all its
449       predecessors and all Phi nodes. **/
450   part_block(pre_call);
451
452   /** Prepare state for dead node elimination **/
453   /* Visited flags in calling irg must be >= flag in called irg.
454      Else walker and arity computation will not work. */
455   if (get_irg_visited(current_ir_graph) <= get_irg_visited(called_graph))
456     set_irg_visited(current_ir_graph, get_irg_visited(called_graph)+1);   /***/
457   if (get_irg_block_visited(current_ir_graph)< get_irg_block_visited(called_graph))
458     set_irg_block_visited(current_ir_graph, get_irg_block_visited(called_graph));
459   /* Set pre_call as new Start node in link field of the start node of
460      calling graph and pre_calls block as new block for the start block
461      of calling graph.
462      Further mark these nodes so that they are not visited by the
463      copying. */
464   set_irn_link(get_irg_start(called_graph), pre_call);
465   set_irn_visited(get_irg_start(called_graph),
466                                   get_irg_visited(current_ir_graph));/***/
467   set_irn_link(get_irg_start_block(called_graph),
468                            get_nodes_Block(pre_call));
469   set_irn_visited(get_irg_start_block(called_graph),
470                                   get_irg_visited(current_ir_graph));  /***/
471
472   /* Initialize for compaction of in arrays */
473   inc_irg_block_visited(current_ir_graph);
474   /*
475       set_Block_block_visited(get_irg_start_block(called_graph),
476       get_irg_block_visited(current_ir_graph) +1 +1); /* count for self edge */
477
478   /*** Replicate local entities of the called_graph ***/
479   /* copy the entities. */
480   called_frame = get_irg_frame_type(called_graph);
481   for (i = 0; i < get_class_n_member(called_frame); i++) {
482     entity *new_ent, *old_ent;
483     old_ent = get_class_member(called_frame, i);
484     new_ent = copy_entity_own(old_ent, get_cur_frame_type());
485     set_entity_link(old_ent, new_ent);
486   }
487
488   /* visited is > than that of called graph.  With this trick visited will
489      remain unchanged so that an outer walker, e.g., searching the call nodes
490      to inline, calling this inline will not visit the inlined nodes. */
491   set_irg_visited(current_ir_graph, get_irg_visited(current_ir_graph)-1);
492
493   /** Performing dead node elimination inlines the graph **/
494   /* Copies the nodes to the obstack of current_ir_graph. Updates links to new
495      entities. */
496   /* @@@ endless loops are not copied!! */
497   irg_walk(get_irg_end(called_graph), copy_node_inline, copy_preds,
498            get_irg_frame_type(called_graph));
499
500   /* Repair called_graph */
501   set_irg_visited(called_graph, get_irg_visited(current_ir_graph));
502   set_irg_block_visited(called_graph, get_irg_block_visited(current_ir_graph));
503   set_Block_block_visited(get_irg_start_block(called_graph), 0);
504
505   /*** Merge the end of the inlined procedure with the call site ***/
506   /* We will turn the old Call node into a Tuple with the following
507      predecessors:
508      -1:  Block of Tuple.
509      0: Phi of all Memories of Return statements.
510      1: Jmp from new Block that merges the control flow from all exception
511          predecessors of the old end block.
512      2: Tuple of all arguments.
513      3: Phi of Exception memories.
514   */
515
516   /** Precompute some values **/
517   end_bl = get_new_node(get_irg_end_block(called_graph));
518   end = get_new_node(get_irg_end(called_graph));
519   arity = get_irn_arity(end_bl);    /* arity = n_exc + n_ret  */
520   n_res = get_method_n_res(get_Call_type(call));
521
522   res_pred = (ir_node **) malloc (n_res * sizeof (ir_node *));
523   cf_pred = (ir_node **) malloc (arity * sizeof (ir_node *));
524
525   set_irg_current_block(current_ir_graph, post_bl); /* just to make sure */
526
527   /** archive keepalives **/
528   for (i = 0; i < get_irn_arity(end); i++)
529     add_End_keepalive(get_irg_end(current_ir_graph), get_irn_n(end, i));
530   /* The new end node will die, but the in array is not on the obstack ... */
531   free_End(end);
532
533   /** Collect control flow from Return blocks to post_calls block. Replace
534       Return nodes by Jump nodes. **/
535   n_ret = 0;
536   for (i = 0; i < arity; i++) {
537     ir_node *ret;
538     ret = get_irn_n(end_bl, i);
539     if (get_irn_op(ret) == op_Return) {
540       cf_pred[n_ret] = new_r_Jmp(current_ir_graph, get_nodes_Block(ret));
541       n_ret++;
542     }
543   }
544   set_irn_in(post_bl, n_ret, cf_pred);
545
546   /** Collect results from Return nodes to post_call. Post_call is
547       turned into a tuple. **/
548   turn_into_tuple(post_call, 4);
549   /* First the Memory-Phi */
550   n_ret = 0;
551   for (i = 0; i < arity; i++) {
552     ret = get_irn_n(end_bl, i);
553     if (get_irn_op(ret) == op_Return) {
554       cf_pred[n_ret] = get_Return_mem(ret);
555       n_ret++;
556     }
557   }
558   phi = new_Phi(n_ret, cf_pred, mode_M);
559   set_Tuple_pred(call, 0, phi);
560   set_irn_link(phi, get_irn_link(post_bl));  /* Conserve Phi-list for further inlinings */
561   set_irn_link(post_bl, phi);
562   /* Now the real results */
563   if (n_res > 0) {
564     for (j = 0; j < n_res; j++) {
565       n_ret = 0;
566       for (i = 0; i < arity; i++) {
567         ret = get_irn_n(end_bl, i);
568         if (get_irn_op(ret) == op_Return) {
569           cf_pred[n_ret] = get_Return_res(ret, j);
570           n_ret++;
571         }
572       }
573       phi = new_Phi(n_ret, cf_pred, get_irn_mode(cf_pred[0]));
574       res_pred[j] = phi;
575       set_irn_link(phi, get_irn_link(post_bl));  /* Conserve Phi-list for further inlinings */
576       set_irn_link(post_bl, phi);
577     }
578     set_Tuple_pred(call, 2, new_Tuple(n_res, res_pred));
579   } else {
580     set_Tuple_pred(call, 2, new_Bad());
581   }
582   /* Finally the exception control flow.  We need to add a Phi node to
583      collect the memory containing the exception objects.  Further we need
584      to add another block to get a correct representation of this Phi.  To
585      this block we add a Jmp that resolves into the X output of the Call
586      when the Call is turned into a tuple. */
587   n_exc = 0;
588   for (i = 0; i < arity; i++) {
589     ir_node *ret;
590     ret = get_irn_n(end_bl, i);
591     if (is_fragile_op(skip_Proj(ret)) || (get_irn_op(skip_Proj(ret)) == op_Raise)) {
592       cf_pred[n_exc] = ret;
593       n_exc++;
594     }
595   }
596   if (n_exc > 0) {
597     new_Block(n_exc, cf_pred);      /* whatch it: current_block is changed! */
598     set_Tuple_pred(call, 1, new_Jmp());
599     /* The Phi for the memories with the exception objects */
600     n_exc = 0;
601     for (i = 0; i < arity; i++) {
602       ir_node *ret;
603       ret = skip_Proj(get_irn_n(end_bl, i));
604       if (get_irn_op(ret) == op_Call) {
605         cf_pred[n_exc] = new_r_Proj(current_ir_graph, get_nodes_Block(ret), ret, mode_M, 3);
606         n_exc++;
607       } else if (is_fragile_op(ret)) {
608         /* We rely that all cfops have the memory output at the same position. */
609         cf_pred[n_exc] = new_r_Proj(current_ir_graph, get_nodes_Block(ret), ret, mode_M, 0);
610         n_exc++;
611       } else if (get_irn_op(ret) == op_Raise) {
612         cf_pred[n_exc] = new_r_Proj(current_ir_graph, get_nodes_Block(ret), ret, mode_M, 1);
613         n_exc++;
614       }
615     }
616     set_Tuple_pred(call, 3, new_Phi(n_exc, cf_pred, mode_M));
617   } else {
618     set_Tuple_pred(call, 1, new_Bad());
619     set_Tuple_pred(call, 3, new_Bad());
620   }
621   free(res_pred);
622   free(cf_pred);
623
624   /*** Correct the control flow to the end node.
625        If the exception control flow from the Call directly branched to the
626        end block we now have the following control flow predecessor pattern:
627        ProjX -> Tuple -> Jmp.
628        We must remove the Jmp along with it's empty block and add Jmp's
629        predecessors as predecessors of this end block. ***/
630   /* find the problematic predecessor of the end block. */
631   end_bl = get_irg_end_block(current_ir_graph);
632   for (i = 0; i < get_Block_n_cfgpreds(end_bl); i++) {
633     cf_op = get_Block_cfgpred(end_bl, i);
634     if (get_irn_op(cf_op) == op_Proj) {
635       cf_op = get_Proj_pred(cf_op);
636       if (get_irn_op(cf_op) == op_Tuple) {
637         cf_op = get_Tuple_pred(cf_op, 1);
638         assert(get_irn_op(cf_op) == op_Jmp);
639         break;
640       }
641     }
642   }
643   /* repair */
644   if (i < get_Block_n_cfgpreds(end_bl)) {
645     bl = get_nodes_Block(cf_op);
646     arity = get_Block_n_cfgpreds(end_bl) + get_Block_n_cfgpreds(bl) - 1;
647     cf_pred = (ir_node **) malloc (arity * sizeof (ir_node *));
648     for (j = 0; j < i; j++)
649       cf_pred[j] = get_Block_cfgpred(end_bl, j);
650     for (j = j; j < i + get_Block_n_cfgpreds(bl); j++)
651       cf_pred[j] = get_Block_cfgpred(bl, j-i);
652     for (j = j; j < arity; j++)
653       cf_pred[j] = get_Block_cfgpred(end_bl, j-get_Block_n_cfgpreds(bl) +1);
654     set_irn_in(end_bl, arity, cf_pred);
655     free(cf_pred);
656   }
657
658   /** Turn cse back on. **/
659   set_optimize(rem_opt);
660 }
661
662 /********************************************************************/
663 /* Apply inlineing to small methods.                                */
664 /********************************************************************/
665
666 static int pos;
667
668 /* It makes no sense to inline too many calls in one procedure. Anyways,
669    I didn't get a version with NEW_ARR_F to run. */
670 #define MAX_INLINE 1024
671
672 static void collect_calls(ir_node *call, void *env) {
673   ir_node **calls = (ir_node **)env;
674   ir_node *addr;
675   tarval *tv;
676   ir_graph *called_irg;
677
678   if (get_irn_op(call) != op_Call) return;
679
680   addr = get_Call_ptr(call);
681   if (get_irn_op(addr) == op_Const) {
682     /* Check whether the constant is the pointer to a compiled entity. */
683     tv = get_Const_tarval(addr);
684     if (tv->u.p.ent) {
685       called_irg = get_entity_irg(tv->u.p.ent);
686       if (called_irg && pos < MAX_INLINE) {
687         /* The Call node calls a locally defined method.  Remember to inline. */
688         calls[pos] = call;
689         pos++;
690       }
691     }
692   }
693 }
694
695
696 /* Inlines all small methods at call sites where the called address comes
697    from a Const node that references the entity representing the called
698    method.
699    The size argument is a rough measure for the code size of the method:
700    Methods where the obstack containing the firm graph is smaller than
701    size are inlined. */
702 void inline_small_irgs(ir_graph *irg, int size) {
703   int i;
704   ir_node *calls[MAX_INLINE];
705   ir_graph *rem = current_ir_graph;
706
707   if (!(get_optimize() && get_opt_inline())) return;
708
709   /*DDME(get_irg_ent(current_ir_graph));*/
710
711   current_ir_graph = irg;
712   /* Handle graph state */
713   assert(get_irg_phase_state(current_ir_graph) != phase_building);
714
715   /* Find Call nodes to inline.
716      (We can not inline during a walk of the graph, as inlineing the same
717      method several times changes the visited flag of the walked graph:
718      after the first inlineing visited of the callee equals visited of
719      the caller.  With the next inlineing both are increased.) */
720   pos = 0;
721   irg_walk(get_irg_end(irg), NULL, collect_calls, (void *) calls);
722
723   if ((pos > 0) && (pos < MAX_INLINE)) {
724     /* There are calls to inline */
725     collect_phiprojs(irg);
726     for (i = 0; i < pos; i++) {
727       tarval *tv;
728       ir_graph *callee;
729       tv = get_Const_tarval(get_Call_ptr(calls[i]));
730       callee = get_entity_irg(tv->u.p.ent);
731       if ((_obstack_memory_used(callee->obst) - obstack_room(callee->obst)) < size) {
732         /*printf(" inlineing "); DDME(tv->u.p.ent);*/
733         inline_method(calls[i], callee);
734       }
735     }
736   }
737
738   current_ir_graph = rem;
739 }
740
741
742 /********************************************************************/
743 /*  Code Placement.  Pinns all floating nodes to a block where they */
744 /*  will be executed only if needed.                                */
745 /********************************************************************/
746
747 static pdeq *worklist;          /* worklist of ir_node*s */
748
749 /* Find the earliest correct block for N.  --- Place N into the
750    same Block as its dominance-deepest Input.  */
751 static void
752 place_floats_early (ir_node *n)
753 {
754   int i, start;
755
756   /* we must not run into an infinite loop */
757   assert (irn_not_visited(n));
758   mark_irn_visited(n);
759
760   /* Place floating nodes. */
761   if (get_op_pinned(get_irn_op(n)) == floats) {
762     int depth = 0;
763     ir_node *b = new_Bad();   /* The block to place this node in */
764
765     assert(get_irn_op(n) != op_Block);
766
767     if ((get_irn_op(n) == op_Const) ||
768         (get_irn_op(n) == op_SymConst) ||
769         (is_Bad(n))) {
770       /* These nodes will not be placed by the loop below. */
771       b = get_irg_start_block(current_ir_graph);
772       depth = 1;
773     }
774
775     /* find the block for this node. */
776     for (i = 0; i < get_irn_arity(n); i++) {
777       ir_node *dep = get_irn_n(n, i);
778       ir_node *dep_block;
779       if ((irn_not_visited(dep)) &&
780           (get_op_pinned(get_irn_op(dep)) == floats)) {
781         place_floats_early (dep);
782       }
783       /* Because all loops contain at least one pinned node, now all
784          our inputs are either pinned or place_early has already
785          been finished on them.  We do not have any unfinished inputs!  */
786       dep_block = get_nodes_Block(dep);
787       if ((!is_Bad(dep_block)) &&
788           (get_Block_dom_depth(dep_block) > depth)) {
789         b = dep_block;
790         depth = get_Block_dom_depth(dep_block);
791       }
792       /* Avoid that the node is placed in the Start block */
793       if ((depth == 1) && (get_Block_dom_depth(get_nodes_Block(n)) > 1)) {
794         b = get_Block_cfg_out(get_irg_start_block(current_ir_graph), 0);
795         assert(b != get_irg_start_block(current_ir_graph));
796         depth = 2;
797       }
798     }
799     set_nodes_Block(n, b);
800   }
801
802   /* Add predecessors of non floating nodes on worklist. */
803   start = (get_irn_op(n) == op_Block) ? 0 : -1;
804   for (i = start; i < get_irn_arity(n); i++) {
805     ir_node *pred = get_irn_n(n, i);
806     if (irn_not_visited(pred)) {
807       pdeq_putr (worklist, pred);
808     }
809   }
810 }
811
812 /* Floating nodes form subgraphs that begin at nodes as Const, Load,
813    Start, Call and end at pinned nodes as Store, Call.  Place_early
814    places all floating nodes reachable from its argument through floating
815    nodes and adds all beginnings at pinned nodes to the worklist. */
816 inline void place_early () {
817   int i;
818   bool del_me;
819
820   assert(worklist);
821   inc_irg_visited(current_ir_graph);
822
823   /* this inits the worklist */
824   place_floats_early (get_irg_end(current_ir_graph));
825
826   /* Work the content of the worklist. */
827   while (!pdeq_empty (worklist)) {
828     ir_node *n = pdeq_getl (worklist);
829     if (irn_not_visited(n)) place_floats_early (n);
830   }
831
832   set_irg_outs_inconsistent(current_ir_graph);
833   current_ir_graph->pinned = pinned;
834 }
835
836
837 /* deepest common dominance ancestor of DCA and CONSUMER of PRODUCER */
838 static ir_node *
839 consumer_dom_dca (ir_node *dca, ir_node *consumer, ir_node *producer)
840 {
841   ir_node *block;
842
843   /* Compute the latest block into which we can place a node so that it is
844      before consumer. */
845   if (get_irn_op(consumer) == op_Phi) {
846     /* our comsumer is a Phi-node, the effective use is in all those
847        blocks through which the Phi-node reaches producer */
848     int i;
849     ir_node *phi_block = get_nodes_Block(consumer);
850     for (i = 0;  i < get_irn_arity(consumer); i++) {
851       if (get_irn_n(consumer, i) == producer) {
852         block = get_nodes_Block(get_Block_cfgpred(phi_block, i));
853       }
854     }
855   } else {
856     assert(is_no_Block(consumer));
857     block = get_nodes_Block(consumer);
858   }
859
860   /* Compute the deepest common ancestor of block and dca. */
861   assert(block);
862   if (!dca) return block;
863   while (get_Block_dom_depth(block) > get_Block_dom_depth(dca))
864     block = get_Block_idom(block);
865   while (get_Block_dom_depth(dca) > get_Block_dom_depth(block))
866     dca = get_Block_idom(dca);
867   while (block != dca)
868     { block = get_Block_idom(block); dca = get_Block_idom(dca); }
869
870   return dca;
871 }
872
873 #if 0
874 /* @@@ Needs loop informations.  Will implement later interprocedural. */
875 static void
876 move_out_of_loops (ir_node *n, ir_node *dca)
877 {
878   assert(dca);
879
880   /* Find the region deepest in the dominator tree dominating
881      dca with the least loop nesting depth, but still dominated
882      by our early placement. */
883   ir_node *best = dca;
884   while (dca != get_nodes_Block(n)) {
885     dca = get_Block_idom(dca);
886     if (!dca) break; /* should we put assert(dca)? */
887     if (get_Block_loop_depth(dca) < get_Block_loop_depth(best)) {
888       best = dca;
889     }
890   }
891   if (get_Block_dom_depth(best) >= get_Block_dom_depth(get_nodes_Block(n)))
892     set_nodes_Block(n, best);
893 }
894 #endif
895
896 /* Find the latest legal block for N and place N into the
897    `optimal' Block between the latest and earliest legal block.
898    The `optimal' block is the dominance-deepest block of those
899    with the least loop-nesting-depth.  This places N out of as many
900    loops as possible and then makes it as controldependant as
901    possible. */
902 static void
903 place_floats_late (ir_node *n)
904 {
905   int i;
906
907   assert (irn_not_visited(n)); /* no multiple placement */
908
909   /* no need to place block nodes, control nodes are already placed. */
910   if ((get_irn_op(n) != op_Block) && (!is_cfop(n)) && (get_irn_mode(n) != mode_X)) {
911     /* Assure that our users are all placed, except the Phi-nodes.
912        --- Each dataflow cycle contains at least one Phi-node.  We
913        have to break the `user has to be placed before the
914        producer' dependance cycle and the Phi-nodes are the
915        place to do so, because we need to base our placement on the
916        final region of our users, which is OK with Phi-nodes, as they
917        are pinned, and they never have to be placed after a
918        producer of one of their inputs in the same block anyway. */
919     for (i = 0; i < get_irn_n_outs(n); i++) {
920       ir_node *succ = get_irn_out(n, i);
921       if (irn_not_visited(succ) && (get_irn_op(succ) != op_Phi))
922         place_floats_late (succ);
923     }
924
925     /* We have to determine the final block of this node... except for constants. */
926     if ((get_op_pinned(get_irn_op(n)) == floats) &&
927         (get_irn_op(n) != op_Const) &&
928         (get_irn_op(n) != op_SymConst)) {
929       ir_node *dca = NULL;      /* deepest common ancestor in the
930                                    dominator tree of all nodes'
931                                    blocks depending on us; our final
932                                    placement has to dominate DCA. */
933       for (i = 0; i < get_irn_n_outs(n); i++) {
934         dca = consumer_dom_dca (dca, get_irn_out(n, i), n);
935       }
936       set_nodes_Block(n, dca);
937 #if 0
938       move_out_of_loops (n, dca);
939 #endif
940     }
941   }
942
943   mark_irn_visited(n);
944
945   /* Add predecessors of all non-floating nodes on list. (Those of floating
946      nodes are placeded already and therefore are marked.)  */
947   for (i = 0; i < get_irn_n_outs(n); i++) {
948     if (irn_not_visited(get_irn_out(n, i))) {
949       pdeq_putr (worklist, get_irn_out(n, i));
950     }
951   }
952 }
953
954 inline void place_late() {
955   assert(worklist);
956   inc_irg_visited(current_ir_graph);
957
958   /* This fills the worklist initially. */
959   place_floats_late(get_irg_start_block(current_ir_graph));
960   /* And now empty the worklist again... */
961   while (!pdeq_empty (worklist)) {
962     ir_node *n = pdeq_getl (worklist);
963     if (irn_not_visited(n)) place_floats_late(n);
964   }
965 }
966
967 void place_code(ir_graph *irg) {
968   ir_graph *rem = current_ir_graph;
969   current_ir_graph = irg;
970
971   if (!(get_optimize() && get_opt_global_cse())) return;
972
973   /* Handle graph state */
974   assert(get_irg_phase_state(irg) != phase_building);
975   if (get_irg_dom_state(irg) != dom_consistent)
976     compute_doms(irg);
977
978   /* Place all floating nodes as early as possible. This guarantees
979      a legal code placement. */
980   worklist = new_pdeq ();
981   place_early();
982
983   /* place_early invalidates the outs, place_late needs them. */
984   compute_outs(irg);
985   /* Now move the nodes down in the dominator tree. This reduces the
986      unnecessary executions of the node. */
987   place_late();
988
989   set_irg_outs_inconsistent(current_ir_graph);
990   del_pdeq (worklist);
991   current_ir_graph = rem;
992 }
993
994
995
996 /********************************************************************/
997 /* Control flow optimization.                                       */
998 /* Removes Bad control flow predecessors and empty blocks.  A block */
999 /* is empty if it contains only a Jmp node.                         */
1000 /* */
1001 /********************************************************************/
1002
1003
1004 static void merge_blocks(ir_node *n, void *env) {
1005   int i;
1006   set_irn_link(n, NULL);
1007
1008   if (get_irn_op(n) == op_Block) {
1009     /* Remove Tuples */
1010     for (i = 0; i < get_Block_n_cfgpreds(n); i++)
1011       set_Block_cfgpred(n, i, skip_Tuple(get_Block_cfgpred(n, i)));
1012   } else if (get_irn_mode(n) == mode_X) {
1013     /* We will soon visit a block.  Optimize it before visiting! */
1014     ir_node *b = get_nodes_Block(n);
1015     ir_node *new = equivalent_node(b);
1016     while (irn_not_visited(b) && (!is_Bad(new)) && (new != b)) {
1017       /* We would have to run gigo if new is bad. */
1018       if (get_optimize() && get_opt_control_flow()) exchange (b, new);
1019       b = new;
1020       new = equivalent_node(b);
1021     }
1022     if (is_Bad(new)) exchange (n, new_Bad());
1023   }
1024 }
1025
1026 static void collect_nodes(ir_node *n, void *env) {
1027   int i;
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   //DDME(get_irg_ent(irg));
1267
1268   /* Use block visited flag to mark non-empty blocks. */
1269   inc_irg_block_visited(irg);
1270   irg_walk(end, merge_blocks, collect_nodes, NULL);
1271
1272   /* Optimize the standard code. */
1273   irg_block_walk(get_irg_end_block(irg), optimize_blocks, NULL, NULL);
1274
1275   /* Walk all keep alives, optimize them if block, add to new in-array
1276      for end if useful. */
1277   in = NEW_ARR_F (ir_node *, 1);
1278   in[0] = get_nodes_Block(end);
1279
1280   inc_irg_visited(current_ir_graph);
1281   for(i = 0; i < get_End_n_keepalives(end); i++) {
1282     ir_node *ka = get_End_keepalive(end, i);
1283     if (irn_not_visited(ka))
1284       if ((get_irn_op(ka) == op_Block) && Block_not_block_visited(ka)) {
1285         set_irg_block_visited(current_ir_graph,  /* Don't walk all the way to Start. */
1286                               get_irg_block_visited(current_ir_graph)-1);
1287         irg_block_walk(ka, optimize_blocks, NULL, NULL);
1288         mark_irn_visited(ka);
1289         ARR_APP1 (ir_node *, in, ka);
1290       } else if (get_irn_op(ka) == op_Phi) {
1291         mark_irn_visited(ka);
1292         ARR_APP1 (ir_node *, in, ka);
1293       }
1294     }
1295   /* DEL_ARR_F(end->in);   GL @@@ tut nicht ! */
1296   end->in = in;
1297
1298   current_ir_graph = rem;
1299 }