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