c86fd23676c4cbb52db074df6388ad9782a54643
[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 start, i;
47   ir_node *optimized;
48
49   if (get_irn_op(n) == op_Block)
50     start = 0;
51   else
52     start = -1;
53
54   /* optimize all sons after recursion, i.e., the sons' sons are
55      optimized already. */
56   for (i = start; i < get_irn_arity(n); i++) {
57     optimized = optimize_in_place_2(get_irn_n(n, i));
58     set_irn_n(n, i, optimized);
59     assert(get_irn_op(optimized) != op_Id);
60   }
61 }
62
63 void
64 local_optimize_graph (ir_graph *irg) {
65   ir_graph *rem = current_ir_graph;
66   current_ir_graph = irg;
67
68   /* Handle graph state */
69   assert(get_irg_phase_state(irg) != phase_building);
70   if (get_opt_global_cse())
71     set_irg_pinned(current_ir_graph, floats);
72   if (get_irg_outs_state(current_ir_graph) == outs_consistent)
73     set_irg_outs_inconsistent(current_ir_graph);
74   if (get_irg_dom_state(current_ir_graph) == dom_consistent)
75     set_irg_dom_inconsistent(current_ir_graph);
76
77   /* Clean the value_table in irg for the cse. */
78   del_identities(irg->value_table);
79   irg->value_table = new_identities();
80
81   /* walk over the graph */
82   irg_walk(irg->end, init_link, optimize_in_place_wrapper, NULL);
83
84   current_ir_graph = rem;
85 }
86
87 /********************************************************************/
88 /* Routines for dead node elimination / copying garbage collection  */
89 /* of the obstack.                                                  */
90 /********************************************************************/
91
92 /* Remeber the new node in the old node by using a field all nodes have. */
93 inline void
94 set_new_node (ir_node *old, ir_node *new)
95 {
96   old->link = new;
97 }
98
99 /* Get this new node, before the old node is forgotton.*/
100 inline ir_node *
101 get_new_node (ir_node * n)
102 {
103   return n->link;
104 }
105
106 /* We use the block_visited flag to mark that we have computed the
107    number of useful predecessors for this block.
108    Further we encode the new arity in this flag in the old blocks.
109    Remembering the arity is useful, as it saves a lot of pointer
110    accesses.  This function is called for all Phi and Block nodes
111    in a Block. */
112 inline int
113 compute_new_arity(ir_node *b) {
114   int i, res;
115   int irg_v, block_v;
116
117   irg_v = get_irg_block_visited(current_ir_graph);
118   block_v = get_Block_block_visited(b);
119   if (block_v >= irg_v) {
120     /* we computed the number of preds for this block and saved it in the
121        block_v flag */
122     return block_v - irg_v;
123   } else {
124     /* compute the number of good predecessors */
125     res = get_irn_arity(b);
126     for (i = 0; i < get_irn_arity(b); i++)
127       if (get_irn_opcode(get_irn_n(b, i)) == iro_Bad) res--;
128     /* save it in the flag. */
129     set_Block_block_visited(b, irg_v + res);
130     return res;
131   }
132 }
133
134 /* Copies the node to the new obstack. The Ins of the new node point to
135    the predecessors on the old obstack.  For block/phi nodes not all
136    predecessors might be copied.  n->link points to the new node.
137    For Phi and Block nodes the function allocates in-arrays with an arity
138    only for useful predecessors.  The arity is determined by counting
139    the non-bad predecessors of the block. */
140 void
141 copy_node (ir_node *n, void *env) {
142   ir_node *nn, *block;
143   int new_arity;
144
145   if (get_irn_opcode(n) == iro_Block) {
146     block = NULL;
147     new_arity = compute_new_arity(n);
148   } else {
149     block = get_nodes_Block(n);
150     if (get_irn_opcode(n) == iro_Phi) {
151       new_arity = compute_new_arity(block);
152     } else {
153       new_arity = get_irn_arity(n);
154     }
155   }
156   nn = new_ir_node(current_ir_graph,
157                    block,
158                    get_irn_op(n),
159                    get_irn_mode(n),
160                    new_arity,
161                    get_irn_in(n));
162   /* Copy the attributes.  These might point to additional data.  If this
163      was allocated on the old obstack the pointers now are dangling.  This
164      frees e.g. the memory of the graph_arr allocated in new_immBlock. */
165   copy_attrs(n, nn);
166   set_new_node(n, nn);
167
168   /*  printf("\n old node: "); DDMSG2(n);
169       printf(" new node: "); DDMSG2(nn); */
170
171 }
172
173 /* Copies new predecessors of old node to new node remembered in link.
174    Spare the Bad predecessors of Phi and Block nodes. */
175 void
176 copy_preds (ir_node *n, void *env) {
177   ir_node *nn, *block, *on;
178   int i, j;
179
180   nn = get_new_node(n);
181
182   /* printf("\n old node: "); DDMSG2(n);
183      printf(" new node: "); DDMSG2(nn);
184      printf(" arities: old: %d, new: %d\n", get_irn_arity(n), get_irn_arity(nn)); */
185
186   if (get_irn_opcode(n) == iro_Block) {
187     /* Don't copy Bad nodes. */
188     j = 0;
189     for (i = 0; i < get_irn_arity(n); i++)
190       if (get_irn_opcode(get_irn_n(n, i)) != iro_Bad) {
191         set_irn_n (nn, j, get_new_node(get_irn_n(n, i)));
192         j++;
193       }
194     /* repair the block visited flag from above misuse. Repair it in both
195        graphs so that the old one can still be used. */
196     set_Block_block_visited(nn, 0);
197     set_Block_block_visited(n, 0);
198     /* Local optimization could not merge two subsequent blocks if
199        in array contained Bads.  Now it's possible.
200        We don't call optimize_in_place as it requires
201        that the fields in ir_graph are set properly. */
202     if (get_Block_n_cfgpreds(nn) == 1
203         && get_irn_op(get_Block_cfgpred(nn, 0)) == op_Jmp)
204       exchange(nn, get_nodes_Block(get_Block_cfgpred(nn, 0)));
205   } else if (get_irn_opcode(n) == iro_Phi) {
206     /* Don't copy node if corresponding predecessor in block is Bad.
207        The Block itself should not be Bad. */
208     block = get_nodes_Block(n);
209     set_irn_n (nn, -1, get_new_node(block));
210     j = 0;
211     for (i = 0; i < get_irn_arity(n); i++)
212       if (get_irn_opcode(get_irn_n(block, i)) != iro_Bad) {
213         set_irn_n (nn, j, get_new_node(get_irn_n(n, i)));
214         j++;
215       }
216     /* If the pre walker reached this Phi after the post walker visited the
217        block block_visited is > 0. */
218     set_Block_block_visited(get_nodes_Block(n), 0);
219     /* Compacting the Phi's ins might generate Phis with only one
220        predecessor. */
221     if (get_irn_arity(n) == 1)
222       exchange(n, get_irn_n(n, 0));
223   } else {
224     for (i = -1; i < get_irn_arity(n); i++)
225       set_irn_n (nn, i, get_new_node(get_irn_n(n, i)));
226   }
227   /* Now the new node is complete.  We can add it to the hash table for cse.
228      @@@ inlinening aborts if we identify End. Why? */
229   if(get_irn_op(nn) != op_End)
230     add_identities (current_ir_graph->value_table, nn);
231 }
232
233 /* Copies the graph recursively, compacts the keepalive of the end node. */
234 void
235 copy_graph () {
236   ir_node *oe, *ne; /* old end, new end */
237   ir_node *ka;      /* keep alive */
238   int i;
239
240   oe = get_irg_end(current_ir_graph);
241   /* copy the end node by hand, allocate dynamic in array! */
242   ne = new_ir_node(current_ir_graph,
243                    NULL,
244                    op_End,
245                    mode_X,
246                    -1,
247                    NULL);
248   /* Copy the attributes.  Well, there might be some in the future... */
249   copy_attrs(oe, ne);
250   set_new_node(oe, ne);
251
252   /* copy the live nodes */
253   irg_walk(get_nodes_Block(oe), copy_node, copy_preds, NULL);
254   /* copy_preds for the end node ... */
255   set_nodes_Block(ne, get_new_node(get_nodes_Block(oe)));
256
257   /** ... and now the keep alives. **/
258   /* First pick the not marked block nodes and walk them.  We must pick these
259      first as else we will oversee blocks reachable from Phis. */
260   for (i = 0; i < get_irn_arity(oe); i++) {
261     ka = get_irn_n(oe, i);
262     if ((get_irn_op(ka) == op_Block) &&
263         (get_irn_visited(ka) < get_irg_visited(current_ir_graph))) {
264       /* We must keep the block alive and copy everything reachable */
265       set_irg_visited(current_ir_graph, get_irg_visited(current_ir_graph)-1);
266       irg_walk(ka, copy_node, copy_preds, NULL);
267       add_End_keepalive(ne, get_new_node(ka));
268     }
269   }
270
271   /* Now pick the Phis.  Here we will keep all! */
272   for (i = 0; i < get_irn_arity(oe); i++) {
273     ka = get_irn_n(oe, i);
274     if ((get_irn_op(ka) == op_Phi)) {
275       if (get_irn_visited(ka) < get_irg_visited(current_ir_graph)) {
276         /* We didn't copy the Phi yet.  */
277         set_irg_visited(current_ir_graph, get_irg_visited(current_ir_graph)-1);
278         irg_walk(ka, copy_node, copy_preds, NULL);
279       }
280       add_End_keepalive(ne, get_new_node(ka));
281     }
282   }
283 }
284
285 /* Copies the graph reachable from current_ir_graph->end to the obstack
286    in current_ir_graph and fixes the environment.
287    Then fixes the fields in current_ir_graph containing nodes of the
288    graph.  */
289 void
290 copy_graph_env () {
291   /* Not all nodes remembered in current_ir_graph might be reachable
292      from the end node.  Assure their link is set to NULL, so that
293      we can test whether new nodes have been computed. */
294   set_irn_link(get_irg_frame  (current_ir_graph), NULL);
295   set_irn_link(get_irg_globals(current_ir_graph), NULL);
296   set_irn_link(get_irg_args   (current_ir_graph), NULL);
297
298   /* we use the block walk flag for removing Bads from Blocks ins. */
299   inc_irg_block_visited(current_ir_graph);
300
301   /* copy the graph */
302   copy_graph();
303
304   /* fix the fields in current_ir_graph */
305   free_End(get_irg_end(current_ir_graph));
306   set_irg_end        (current_ir_graph, get_new_node(get_irg_end(current_ir_graph)));
307   set_irg_end_block  (current_ir_graph, get_new_node(get_irg_end_block(current_ir_graph)));
308   if (get_irn_link(get_irg_frame(current_ir_graph)) == NULL) {
309     copy_node (get_irg_frame(current_ir_graph), NULL);
310     copy_preds(get_irg_frame(current_ir_graph), NULL);
311   }
312   if (get_irn_link(get_irg_globals(current_ir_graph)) == NULL) {
313     copy_node (get_irg_globals(current_ir_graph), NULL);
314     copy_preds(get_irg_globals(current_ir_graph), NULL);
315   }
316   if (get_irn_link(get_irg_args(current_ir_graph)) == NULL) {
317     copy_node (get_irg_args(current_ir_graph), NULL);
318     copy_preds(get_irg_args(current_ir_graph), NULL);
319   }
320   set_irg_start  (current_ir_graph, get_new_node(get_irg_start(current_ir_graph)));
321
322   set_irg_start_block(current_ir_graph,
323                       get_new_node(get_irg_start_block(current_ir_graph)));
324   set_irg_frame  (current_ir_graph, get_new_node(get_irg_frame(current_ir_graph)));
325   set_irg_globals(current_ir_graph, get_new_node(get_irg_globals(current_ir_graph)));
326   set_irg_args   (current_ir_graph, get_new_node(get_irg_args(current_ir_graph)));
327   if (get_irn_link(get_irg_bad(current_ir_graph)) == NULL) {
328     copy_node(get_irg_bad(current_ir_graph), NULL);
329     copy_preds(get_irg_bad(current_ir_graph), NULL);
330   }
331   set_irg_bad(current_ir_graph, get_new_node(get_irg_bad(current_ir_graph)));
332 }
333
334 /* Copies all reachable nodes to a new obstack.  Removes bad inputs
335    from block nodes and the corresponding inputs from Phi nodes.
336    Merges single exit blocks with single entry blocks and removes
337    1-input Phis.
338    Adds all new nodes to a new hash table for cse.  Does not
339    perform cse, so the hash table might contain common subexpressions. */
340 /* Amroq call this emigrate() */
341 void
342 dead_node_elimination(ir_graph *irg) {
343   ir_graph *rem;
344   struct obstack *graveyard_obst = NULL;
345   struct obstack *rebirth_obst   = NULL;
346
347   /* Remember external state of current_ir_graph. */
348   rem = current_ir_graph;
349   current_ir_graph = irg;
350
351   /* Handle graph state */
352   assert(get_irg_phase_state(current_ir_graph) != phase_building);
353   free_outs(current_ir_graph);
354
355   if (get_optimize() && get_opt_dead_node_elimination()) {
356
357     /* A quiet place, where the old obstack can rest in peace,
358        until it will be cremated. */
359     graveyard_obst = irg->obst;
360
361     /* A new obstack, where the reachable nodes will be copied to. */
362     rebirth_obst = (struct obstack *) xmalloc (sizeof (struct obstack));
363     current_ir_graph->obst = rebirth_obst;
364     obstack_init (current_ir_graph->obst);
365
366     /* We also need a new hash table for cse */
367     del_identities (irg->value_table);
368     irg->value_table = new_identities ();
369
370     /* Copy the graph from the old to the new obstack */
371     copy_graph_env();
372
373     /* Free memory from old unoptimized obstack */
374     obstack_free(graveyard_obst, 0);  /* First empty the obstack ... */
375     xfree (graveyard_obst);           /* ... then free it.           */
376   }
377
378   current_ir_graph = rem;
379 }
380
381 /**********************************************************************/
382 /*  Funcionality for inlining                                         */
383 /**********************************************************************/
384
385 /* Copy node for inlineing.  Copies the node by calling copy_node and
386    then updates the entity if it's a local one.  env must be a pointer
387    to the frame type of the procedure. The new entities must be in
388    the link field of the entities. */
389 void
390 copy_node_inline (ir_node *n, void *env) {
391   ir_node *new;
392   type *frame_tp = (type *)env;
393
394   copy_node(n, NULL);
395   if (get_irn_op(n) == op_Sel) {
396     new = get_new_node (n);
397     assert(get_irn_op(new) == op_Sel);
398     if (get_entity_owner(get_Sel_entity(n)) == frame_tp) {
399       set_Sel_entity(new, get_entity_link(get_Sel_entity(n)));
400     }
401   }
402 }
403
404 void inline_method(ir_node *call, ir_graph *called_graph) {
405   ir_node *pre_call;
406   ir_node *post_call, *post_bl;
407   ir_node *in[5];
408   ir_node *end, *end_bl;
409   ir_node **res_pred;
410   ir_node **cf_pred;
411   ir_node *ret, *phi;
412   ir_node *cf_op, *bl;
413   int arity, n_ret, n_exc, n_res, i, j, rem_opt;
414   type *called_frame, *caller_frame;
415
416   if (!get_opt_inline()) return;
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   /** Turn off cse, this can cause problems when allocating new nodes. **/
432   rem_opt = get_opt_cse();
433   set_opt_cse(0);
434
435   /** Part the Call node into two nodes.  Pre_call collects the parameters of
436           the procedure and later replaces the Start node of the called graph.
437           Post_call is the old Call node and collects the results of the called
438           graph. Both will end up being a tuple.  **/
439   post_bl = get_nodes_Block(call);
440   set_irg_current_block(current_ir_graph, post_bl);
441   /* XxMxPxP of Start + parameter of Call */
442   in[0] = new_Jmp();
443   in[1] = get_Call_mem(call);
444   in[2] = get_irg_frame(current_ir_graph);
445   in[3] = get_irg_globals(current_ir_graph);
446   in[4] = new_Tuple (get_Call_n_params(call),
447                                          get_Call_param_arr(call));
448   pre_call = new_Tuple(5, in);
449   post_call = call;
450
451   /** Part the block of the Call node into two blocks.
452       The new block gets the ins of the old block, pre_call and all its
453       predecessors and all Phi nodes. **/
454   part_block(pre_call);
455
456   /** Prepare state for dead node elimination **/
457   /* Visited flags in calling irg must be >= flag in called irg.
458      Else walker and arity computation will not work. */
459   if (get_irg_visited(current_ir_graph) <= get_irg_visited(called_graph))
460     set_irg_visited(current_ir_graph, get_irg_visited(called_graph)+1);   /***/
461   if (get_irg_block_visited(current_ir_graph)< get_irg_block_visited(called_graph))
462     set_irg_block_visited(current_ir_graph, get_irg_block_visited(called_graph));
463   /* Set pre_call as new Start node in link field of the start node of
464          calling graph and pre_calls block as new block for the start block
465          of calling graph.
466          Further mark these nodes so that they are not visited by the
467          copying. */
468   set_irn_link(get_irg_start(called_graph), pre_call);
469   set_irn_visited(get_irg_start(called_graph),
470                                   get_irg_visited(current_ir_graph));/***/
471   set_irn_link(get_irg_start_block(called_graph),
472                            get_nodes_Block(pre_call));
473   set_irn_visited(get_irg_start_block(called_graph),
474                                   get_irg_visited(current_ir_graph));  /***/
475
476   /* Initialize for compaction of in arrays */
477   inc_irg_block_visited(current_ir_graph);
478   /*
479           set_Block_block_visited(get_irg_start_block(called_graph),
480           get_irg_block_visited(current_ir_graph) +1 +1); /* count for self edge */
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_member(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_res(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_opt_cse(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   int i;
822   bool del_me;
823
824   assert(worklist);
825   inc_irg_visited(current_ir_graph);
826
827   /* this inits the worklist */
828   place_floats_early (get_irg_end(current_ir_graph));
829
830   /* Work the content of the worklist. */
831   while (!pdeq_empty (worklist)) {
832     ir_node *n = pdeq_getl (worklist);
833     if (irn_not_visited(n)) place_floats_early (n);
834   }
835
836   set_irg_outs_inconsistent(current_ir_graph);
837   current_ir_graph->pinned = pinned;
838 }
839
840
841 /* deepest common dominance ancestor of DCA and CONSUMER of PRODUCER */
842 static ir_node *
843 consumer_dom_dca (ir_node *dca, ir_node *consumer, ir_node *producer)
844 {
845   ir_node *block;
846
847   /* Compute the latest block into which we can place a node so that it is
848      before consumer. */
849   if (get_irn_op(consumer) == op_Phi) {
850     /* our comsumer is a Phi-node, the effective use is in all those
851        blocks through which the Phi-node reaches producer */
852     int i;
853     ir_node *phi_block = get_nodes_Block(consumer);
854     for (i = 0;  i < get_irn_arity(consumer); i++) {
855       if (get_irn_n(consumer, i) == producer) {
856         block = get_nodes_Block(get_Block_cfgpred(phi_block, i));
857       }
858     }
859   } else {
860     assert(is_no_Block(consumer));
861     block = get_nodes_Block(consumer);
862   }
863
864   /* Compute the deepest common ancestor of block and dca. */
865   assert(block);
866   if (!dca) return block;
867   while (get_Block_dom_depth(block) > get_Block_dom_depth(dca))
868     block = get_Block_idom(block);
869   while (get_Block_dom_depth(dca) > get_Block_dom_depth(block))
870     dca = get_Block_idom(dca);
871   while (block != dca)
872     { block = get_Block_idom(block); dca = get_Block_idom(dca); }
873
874   return dca;
875 }
876
877 #if 0
878 /* @@@ Needs loop informations.  Will implement later interprocedural. */
879 static void
880 move_out_of_loops (ir_node *n, ir_node *dca)
881 {
882   assert(dca);
883
884   /* Find the region deepest in the dominator tree dominating
885      dca with the least loop nesting depth, but still dominated
886      by our early placement. */
887   ir_node *best = dca;
888   while (dca != get_nodes_Block(n)) {
889     dca = get_Block_idom(dca);
890     if (!dca) break; /* should we put assert(dca)? */
891     if (get_Block_loop_depth(dca) < get_Block_loop_depth(best)) {
892       best = dca;
893     }
894   }
895   if (get_Block_dom_depth(best) >= get_Block_dom_depth(get_nodes_Block(n)))
896     set_nodes_Block(n, best);
897 }
898 #endif
899
900 /* Find the latest legal block for N and place N into the
901    `optimal' Block between the latest and earliest legal block.
902    The `optimal' block is the dominance-deepest block of those
903    with the least loop-nesting-depth.  This places N out of as many
904    loops as possible and then makes it as controldependant as
905    possible. */
906 static void
907 place_floats_late (ir_node *n)
908 {
909   int i;
910
911   assert (irn_not_visited(n)); /* no multiple placement */
912
913   /* no need to place block nodes, control nodes are already placed. */
914   if ((get_irn_op(n) != op_Block) && (!is_cfop(n)) && (get_irn_mode(n) != mode_X)) {
915     /* Assure that our users are all placed, except the Phi-nodes.
916        --- Each dataflow cycle contains at least one Phi-node.  We
917        have to break the `user has to be placed before the
918        producer' dependance cycle and the Phi-nodes are the
919        place to do so, because we need to base our placement on the
920        final region of our users, which is OK with Phi-nodes, as they
921        are pinned, and they never have to be placed after a
922        producer of one of their inputs in the same block anyway. */
923     for (i = 0; i < get_irn_n_outs(n); i++) {
924       ir_node *succ = get_irn_out(n, i);
925       if (irn_not_visited(succ) && (get_irn_op(succ) != op_Phi))
926         place_floats_late (succ);
927     }
928
929     /* We have to determine the final block of this node... except for constants. */
930     if ((get_op_pinned(get_irn_op(n)) == floats) &&
931         (get_irn_op(n) != op_Const) &&
932         (get_irn_op(n) != op_SymConst)) {
933       ir_node *dca = NULL;      /* deepest common ancestor in the
934                                    dominator tree of all nodes'
935                                    blocks depending on us; our final
936                                    placement has to dominate DCA. */
937       for (i = 0; i < get_irn_n_outs(n); i++) {
938         dca = consumer_dom_dca (dca, get_irn_out(n, i), n);
939       }
940       set_nodes_Block(n, dca);
941 #if 0
942       move_out_of_loops (n, dca);
943 #endif
944     }
945   }
946
947   mark_irn_visited(n);
948
949   /* Add predecessors of all non-floating nodes on list. (Those of floating
950      nodes are placeded already and therefore are marked.)  */
951   for (i = 0; i < get_irn_n_outs(n); i++) {
952     if (irn_not_visited(get_irn_out(n, i))) {
953       pdeq_putr (worklist, get_irn_out(n, i));
954     }
955   }
956 }
957
958 inline void place_late() {
959   assert(worklist);
960   inc_irg_visited(current_ir_graph);
961
962   /* This fills the worklist initially. */
963   place_floats_late(get_irg_start_block(current_ir_graph));
964   /* And now empty the worklist again... */
965   while (!pdeq_empty (worklist)) {
966     ir_node *n = pdeq_getl (worklist);
967     if (irn_not_visited(n)) place_floats_late(n);
968   }
969 }
970
971 void place_code(ir_graph *irg) {
972   ir_graph *rem = current_ir_graph;
973   current_ir_graph = irg;
974
975   if (!(get_optimize() && get_opt_global_cse())) return;
976
977   /* Handle graph state */
978   assert(get_irg_phase_state(irg) != phase_building);
979   if (get_irg_dom_state(irg) != dom_consistent)
980     compute_doms(irg);
981
982   /* Place all floating nodes as early as possible. This guarantees
983      a legal code placement. */
984   worklist = new_pdeq ();
985   place_early();
986
987   /* place_early invalidates the outs, place_late needs them. */
988   compute_outs(irg);
989   /* Now move the nodes down in the dominator tree. This reduces the
990      unnecessary executions of the node. */
991   place_late();
992
993   set_irg_outs_inconsistent(current_ir_graph);
994   del_pdeq (worklist);
995   current_ir_graph = rem;
996 }
997
998
999
1000 /********************************************************************/
1001 /* Control flow optimization.                                       */
1002 /* Removes Bad control flow predecessors and empty blocks.  A block */
1003 /* is empty if it contains only a Jmp node.                         */
1004 /* */
1005 /********************************************************************/
1006
1007
1008 static void merge_blocks(ir_node *n, void *env) {
1009   int i;
1010   set_irn_link(n, NULL);
1011
1012   if (get_irn_op(n) == op_Block) {
1013     /* Remove Tuples */
1014     for (i = 0; i < get_Block_n_cfgpreds(n); i++)
1015       set_Block_cfgpred(n, i, skip_Tuple(get_Block_cfgpred(n, i)));
1016   } else if (get_irn_mode(n) == mode_X) {
1017     /* We will soon visit a block.  Optimize it before visiting! */
1018     ir_node *b = get_nodes_Block(n);
1019     ir_node *new = equivalent_node(b);
1020     while (irn_not_visited(b) && (!is_Bad(new)) && (new != b)) {
1021       /* We would have to run gigo if new is bad. */
1022       if (get_optimize() && get_opt_control_flow()) exchange (b, new);
1023       b = new;
1024       new = equivalent_node(b);
1025     }
1026     if (is_Bad(new)) exchange (n, new_Bad());
1027   }
1028 }
1029
1030 static void collect_nodes(ir_node *n, void *env) {
1031   int i;
1032   if (is_no_Block(n)) {
1033     ir_node *b = get_nodes_Block(n);
1034
1035     if ((get_irn_op(n) == op_Phi)) {
1036       /* Collect Phi nodes to compact ins along with block's ins. */
1037       set_irn_link(n, get_irn_link(b));
1038       set_irn_link(b, n);
1039     } else if (get_irn_op(n) != op_Jmp) {  /* Check for non empty block. */
1040       mark_Block_block_visited(b);
1041     }
1042   }
1043 }
1044
1045 /* Returns true if pred is pred of block */
1046 int is_pred_of(ir_node *pred, ir_node *b) {
1047   int i;
1048   for (i = 0; i < get_Block_n_cfgpreds(b); i++) {
1049     ir_node *b_pred = get_nodes_Block(get_Block_cfgpred(b, i));
1050     if (b_pred == pred) return 1;
1051   }
1052   return 0;
1053 }
1054
1055 int test_whether_dispensable(ir_node *b, int pos) {
1056   int i, j, n_preds = 1;
1057   int dispensable = 1;
1058   ir_node *cfop = get_Block_cfgpred(b, pos);
1059   ir_node *pred = get_nodes_Block(cfop);
1060
1061   if (get_Block_block_visited(pred) + 1
1062       < get_irg_block_visited(current_ir_graph)) {
1063     if (!get_optimize() || !get_opt_control_flow()) {
1064       /* Mark block so that is will not be removed. */
1065       set_Block_block_visited(pred, get_irg_block_visited(current_ir_graph)-1);
1066       return 1;
1067     }
1068     /* Seems to be empty. */
1069     if (!get_irn_link(b)) {
1070       /* There are no Phi nodes ==> dispensable. */
1071       n_preds = get_Block_n_cfgpreds(pred);
1072     } else {
1073       /* b's pred blocks and pred's pred blocks must be pairwise disjunct.
1074          Work preds < pos as if they were already removed. */
1075       for (i = 0; i < pos; i++) {
1076         ir_node *b_pred = get_nodes_Block(get_Block_cfgpred(b, i));
1077         if (get_Block_block_visited(b_pred) + 1
1078             < get_irg_block_visited(current_ir_graph)) {
1079           for (j = 0; j < get_Block_n_cfgpreds(b_pred); j++) {
1080             ir_node *b_pred_pred = get_nodes_Block(get_Block_cfgpred(b_pred, j));
1081             if (is_pred_of(b_pred_pred, pred)) dispensable = 0;
1082           }
1083         } else {
1084           if (is_pred_of(b_pred, pred)) dispensable = 0;
1085         }
1086       }
1087       for (i = pos +1; i < get_Block_n_cfgpreds(b); i++) {
1088         ir_node *b_pred = get_nodes_Block(get_Block_cfgpred(b, i));
1089         if (is_pred_of(b_pred, pred)) dispensable = 0;
1090       }
1091       if (!dispensable) {
1092         set_Block_block_visited(pred, get_irg_block_visited(current_ir_graph)-1);
1093         n_preds = 1;
1094       } else {
1095         n_preds = get_Block_n_cfgpreds(pred);
1096       }
1097     }
1098   }
1099
1100   return n_preds;
1101 }
1102
1103 void optimize_blocks(ir_node *b, void *env) {
1104   int i, j, k, max_preds, n_preds;
1105   ir_node *pred, *phi;
1106   ir_node **in;
1107
1108   max_preds = 0;
1109   for (i = 0; i < get_Block_n_cfgpreds(b); i++) {
1110     pred = get_Block_cfgpred(b, i);
1111     max_preds += test_whether_dispensable(b, i);
1112   }
1113   in = (ir_node **) malloc(max_preds * sizeof(ir_node *));
1114
1115
1116   /** Debug output **
1117   printf(" working on "); DDMN(b);
1118   for (i = 0; i < get_Block_n_cfgpreds(b); i++) {
1119     pred = get_nodes_Block(get_Block_cfgpred(b, i));
1120     if (is_Bad(get_Block_cfgpred(b, i))) {
1121       printf("  removing Bad %i\n ", i);
1122     } else if (get_Block_block_visited(pred) +1
1123                < get_irg_block_visited(current_ir_graph)) {
1124       printf("  removing pred %i ", i); DDMN(pred);
1125     } else { printf("  Nothing to do for "); DDMN(pred); }
1126   }
1127  ** end Debug output **/
1128
1129   /** Fix the Phi nodes **/
1130   phi = get_irn_link(b);
1131   while (phi) {
1132     assert(get_irn_op(phi) == op_Phi);
1133     /* Find the new predecessors for the Phi */
1134     n_preds = 0;
1135     for (i = 0; i < get_Block_n_cfgpreds(b); i++) {
1136       pred = get_nodes_Block(get_Block_cfgpred(b, i));
1137       if (is_Bad(get_Block_cfgpred(b, i))) {
1138         /* Do nothing */
1139       } else if (get_Block_block_visited(pred) +1
1140                  < get_irg_block_visited(current_ir_graph)) {
1141         /* It's an empty block and not yet visited. */
1142         ir_node *phi_pred = get_Phi_pred(phi, i);
1143         for (j = 0; j < get_Block_n_cfgpreds(pred); j++) {
1144           if (get_nodes_Block(phi_pred) == pred) {
1145             assert(get_irn_op(phi_pred) == op_Phi);  /* Block is empty!! */
1146             in[n_preds] = get_Phi_pred(phi_pred, j);
1147           } else {
1148             in[n_preds] = phi_pred;
1149           }
1150           n_preds++;
1151         }
1152 #if 0
1153         /* @@@ hier brauche ich schleifeninformation!!! Wenn keine Rueckwaertskante
1154            dann darfs auch keine Verwendung geben. */
1155         if (get_nodes_Block(phi_pred) == pred) {
1156           /* remove the Phi as it might be kept alive. Further there
1157              might be other users. */
1158           exchange(phi_pred, phi);  /* geht, is aber doch semantisch falsch! */
1159         }
1160 #endif
1161       } else {
1162         in[n_preds] = get_Phi_pred(phi, i);
1163         n_preds ++;
1164       }
1165     }
1166     /* Fix the node */
1167     set_irn_in(phi, n_preds, in);
1168     phi = get_irn_link(phi);
1169   }
1170
1171   /** Move Phi nodes from removed blocks to this one.
1172       This happens only if merge between loop backedge and single loop entry. **/
1173   for (k = 0; k < get_Block_n_cfgpreds(b); k++) {
1174     pred = get_nodes_Block(get_Block_cfgpred(b, k));
1175     if (get_Block_block_visited(pred) +1
1176         < get_irg_block_visited(current_ir_graph)) {
1177       phi = get_irn_link(pred);
1178       while (phi) {
1179         if (get_irn_op(phi) == op_Phi) {
1180           set_nodes_Block(phi, b);
1181
1182           n_preds = 0;
1183           for (i = 0; i < k; i++) {
1184             pred = get_nodes_Block(get_Block_cfgpred(b, i));
1185             if (is_Bad(get_Block_cfgpred(b, i))) {
1186               /* Do nothing */
1187             } else if (get_Block_block_visited(pred) +1
1188                        < get_irg_block_visited(current_ir_graph)) {
1189               /* It's an empty block and not yet visited. */
1190               for (j = 0; j < get_Block_n_cfgpreds(pred); j++) {
1191                 /* @@@ Hier brauche ich schleifeninformation!!! Kontrllflusskante
1192                    muss Rueckwaertskante sein! (An allen vier in[n_preds] = phi
1193                    Anweisungen.) Trotzdem tuts bisher!! */
1194                 in[n_preds] = phi;
1195                 n_preds++;
1196               }
1197             } else {
1198               in[n_preds] = phi;
1199               n_preds++;
1200             }
1201           }
1202           for (i = 0; i < get_Phi_n_preds(phi); i++) {
1203             in[n_preds] = get_Phi_pred(phi, i);
1204             n_preds++;
1205           }
1206           for (i = k+1; i < get_Block_n_cfgpreds(b); i++) {
1207             pred = get_nodes_Block(get_Block_cfgpred(b, i));
1208             if (is_Bad(get_Block_cfgpred(b, i))) {
1209               /* Do nothing */
1210             } else if (get_Block_block_visited(pred) +1
1211                        < get_irg_block_visited(current_ir_graph)) {
1212               /* It's an empty block and not yet visited. */
1213               for (j = 0; j < get_Block_n_cfgpreds(pred); j++) {
1214                 in[n_preds] = phi;
1215                 n_preds++;
1216               }
1217             } else {
1218               in[n_preds] = phi;
1219               n_preds++;
1220             }
1221           }
1222           set_irn_in(phi, n_preds, in);
1223         }
1224         phi = get_irn_link(phi);
1225       }
1226     }
1227   }
1228
1229   /** Fix the block **/
1230   n_preds = 0;
1231   for (i = 0; i < get_Block_n_cfgpreds(b); i++) {
1232     pred = get_nodes_Block(get_Block_cfgpred(b, i));
1233     if (is_Bad(get_Block_cfgpred(b, i))) {
1234       /* Do nothing */
1235     } else if (get_Block_block_visited(pred) +1
1236                < get_irg_block_visited(current_ir_graph)) {
1237       /* It's an empty block and not yet visited. */
1238       assert(get_Block_n_cfgpreds(b) > 1);
1239                         /* Else it should be optimized by equivalent_node. */
1240       for (j = 0; j < get_Block_n_cfgpreds(pred); j++) {
1241         in[n_preds] = get_Block_cfgpred(pred, j);
1242         n_preds++;
1243       }
1244       /* Remove block as it might be kept alive. */
1245       exchange(pred, b/*new_Bad()*/);
1246     } else {
1247       in[n_preds] = get_Block_cfgpred(b, i);
1248       n_preds ++;
1249     }
1250   }
1251   set_irn_in(b, n_preds, in);
1252   free(in);
1253 }
1254
1255 void optimize_cf(ir_graph *irg) {
1256   int i;
1257   ir_node **in;
1258   ir_node *end = get_irg_end(irg);
1259   ir_graph *rem = current_ir_graph;
1260   current_ir_graph = irg;
1261
1262
1263   /* Handle graph state */
1264   assert(get_irg_phase_state(irg) != phase_building);
1265   if (get_irg_outs_state(current_ir_graph) == outs_consistent)
1266     set_irg_outs_inconsistent(current_ir_graph);
1267   if (get_irg_dom_state(current_ir_graph) == dom_consistent)
1268     set_irg_dom_inconsistent(current_ir_graph);
1269
1270   //DDME(get_irg_ent(irg));
1271
1272   /* Use block visited flag to mark non-empty blocks. */
1273   inc_irg_block_visited(irg);
1274   irg_walk(end, merge_blocks, collect_nodes, NULL);
1275
1276   /* Optimize the standard code. */
1277   irg_block_walk(get_irg_end_block(irg), optimize_blocks, NULL, NULL);
1278
1279   /* Walk all keep alives, optimize them if block, add to new in-array
1280      for end if useful. */
1281   in = NEW_ARR_F (ir_node *, 1);
1282   in[0] = get_nodes_Block(end);
1283
1284   inc_irg_visited(current_ir_graph);
1285   for(i = 0; i < get_End_n_keepalives(end); i++) {
1286     ir_node *ka = get_End_keepalive(end, i);
1287     if (irn_not_visited(ka))
1288       if ((get_irn_op(ka) == op_Block) && Block_not_block_visited(ka)) {
1289         set_irg_block_visited(current_ir_graph,  /* Don't walk all the way to Start. */
1290                               get_irg_block_visited(current_ir_graph)-1);
1291         irg_block_walk(ka, optimize_blocks, NULL, NULL);
1292         mark_irn_visited(ka);
1293         ARR_APP1 (ir_node *, in, ka);
1294       } else if (get_irn_op(ka) == op_Phi) {
1295         mark_irn_visited(ka);
1296         ARR_APP1 (ir_node *, in, ka);
1297       }
1298     }
1299   /* DEL_ARR_F(end->in);   GL @@@ tut nicht ! */
1300   end->in = in;
1301
1302   current_ir_graph = rem;
1303 }