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