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