Added .cvsignore files --flo
[libfirm] / ir / ir / irgopt.c
1 /*
2  * Project:     libFIRM
3  * File name:   ir/ir/irgopt.c
4  * Purpose:     Optimizations for a whole ir graph, i.e., a procedure.
5  * Author:      Christian Schaefer, Goetz Lindenmaier
6  * Modified by: Sebastian Felis
7  * Created:
8  * CVS-ID:      $Id$
9  * Copyright:   (c) 1998-2003 Universität Karlsruhe
10  * Licence:     This file protected by GPL -  GNU GENERAL PUBLIC LICENSE.
11  */
12
13
14 #ifdef HAVE_CONFIG_H
15 # include <config.h>
16 #endif
17
18 # include <assert.h>
19 # include <stdbool.h>
20
21 # include "irprog.h"
22 # include "irgopt.h"
23 # include "irnode_t.h"
24 # include "irgraph_t.h"
25 # include "iropt_t.h"
26 # include "irgwalk.h"
27 # include "ircons.h"
28 # include "irgmod.h"
29 # include "array.h"
30 # include "pset.h"
31 # include "eset.h"
32 # include "pdeq.h"       /* Fuer code placement */
33 # include "irouts.h"
34 # include "irloop.h"
35 # include "irbackedge_t.h"
36 # include "irflag_t.h"
37
38 /* Defined in iropt.c */
39 pset *new_identities (void);
40 void  del_identities (pset *value_table);
41 void  add_identities   (pset *value_table, ir_node *node);
42
43 /*------------------------------------------------------------------*/
44 /* apply optimizations of iropt to all nodes.                       */
45 /*------------------------------------------------------------------*/
46
47 static void init_link (ir_node *n, void *env) {
48   set_irn_link(n, NULL);
49 }
50
51 #if 0   /* Old version. Avoids Ids.
52            This is not necessary:  we do a postwalk, and get_irn_n
53            removes ids anyways.  So it's much cheaper to call the
54            optimization less often and use the exchange() algorithm. */
55 static void
56 optimize_in_place_wrapper (ir_node *n, void *env) {
57   int i, irn_arity;
58   ir_node *optimized, *old;
59
60   irn_arity = get_irn_arity(n);
61   for (i = 0; i < irn_arity; i++) {
62     /* get_irn_n skips Id nodes, so comparison old != optimized does not
63        show all optimizations. Therefore always set new predecessor. */
64     old = get_irn_n(n, i);
65     optimized = optimize_in_place_2(old);
66     set_irn_n(n, i, optimized);
67   }
68
69   if (get_irn_op(n) == op_Block) {
70     optimized = optimize_in_place_2(n);
71     if (optimized != n) exchange (n, optimized);
72   }
73 }
74 #else
75 static void
76 optimize_in_place_wrapper (ir_node *n, void *env) {
77   ir_node *optimized = optimize_in_place_2(n);
78   if (optimized != n) exchange (n, optimized);
79 }
80 #endif
81
82
83
84 void
85 local_optimize_graph (ir_graph *irg) {
86   ir_graph *rem = current_ir_graph;
87   current_ir_graph = irg;
88
89   /* Handle graph state */
90   assert(get_irg_phase_state(irg) != phase_building);
91   if (get_opt_global_cse())
92     set_irg_pinned(current_ir_graph, floats);
93   if (get_irg_outs_state(current_ir_graph) == outs_consistent)
94     set_irg_outs_inconsistent(current_ir_graph);
95   if (get_irg_dom_state(current_ir_graph) == dom_consistent)
96     set_irg_dom_inconsistent(current_ir_graph);
97
98   /* Clean the value_table in irg for the cse. */
99   del_identities(irg->value_table);
100   irg->value_table = new_identities();
101
102   /* walk over the graph */
103   irg_walk(irg->end, init_link, optimize_in_place_wrapper, NULL);
104
105   current_ir_graph = rem;
106 }
107
108 /*------------------------------------------------------------------*/
109 /* Routines for dead node elimination / copying garbage collection  */
110 /* of the obstack.                                                  */
111 /*------------------------------------------------------------------*/
112
113 /**
114  * Remember the new node in the old node by using a field all nodes have.
115  */
116 static INLINE void
117 set_new_node (ir_node *old, ir_node *new)
118 {
119   old->link = new;
120 }
121
122 /**
123  * Get this new node, before the old node is forgotton.
124  */
125 static INLINE ir_node *
126 get_new_node (ir_node * n)
127 {
128   return n->link;
129 }
130
131 /**
132  * We use the block_visited flag to mark that we have computed the
133  * number of useful predecessors for this block.
134  * Further we encode the new arity in this flag in the old blocks.
135  * Remembering the arity is useful, as it saves a lot of pointer
136  * accesses.  This function is called for all Phi and Block nodes
137  * in a Block.
138  */
139 static INLINE int
140 compute_new_arity(ir_node *b) {
141   int i, res, irn_arity;
142   int irg_v, block_v;
143
144   irg_v = get_irg_block_visited(current_ir_graph);
145   block_v = get_Block_block_visited(b);
146   if (block_v >= irg_v) {
147     /* we computed the number of preds for this block and saved it in the
148        block_v flag */
149     return block_v - irg_v;
150   } else {
151     /* compute the number of good predecessors */
152     res = irn_arity = get_irn_arity(b);
153     for (i = 0; i < irn_arity; i++)
154       if (get_irn_opcode(get_irn_n(b, i)) == iro_Bad) res--;
155     /* save it in the flag. */
156     set_Block_block_visited(b, irg_v + res);
157     return res;
158   }
159 }
160
161 /* TODO: add an ir_op operation */
162 static INLINE void new_backedge_info(ir_node *n) {
163   switch(get_irn_opcode(n)) {
164   case iro_Block:
165     n->attr.block.cg_backedge = NULL;
166     n->attr.block.backedge = new_backedge_arr(current_ir_graph->obst, get_irn_arity(n));
167     break;
168   case iro_Phi:
169     n->attr.phi_backedge = new_backedge_arr(current_ir_graph->obst, get_irn_arity(n));
170     break;
171   case iro_Filter:
172     n->attr.filter.backedge = new_backedge_arr(current_ir_graph->obst, get_irn_arity(n));
173     break;
174   default: ;
175   }
176 }
177
178 /**
179  * Copies the node to the new obstack. The Ins of the new node point to
180  * the predecessors on the old obstack.  For block/phi nodes not all
181  * predecessors might be copied.  n->link points to the new node.
182  * For Phi and Block nodes the function allocates in-arrays with an arity
183  * only for useful predecessors.  The arity is determined by counting
184  * the non-bad predecessors of the block.
185  */
186 static void
187 copy_node (ir_node *n, void *env) {
188   ir_node *nn, *block;
189   int new_arity;
190
191   /* The end node looses it's flexible in array.  This doesn't matter,
192      as dead node elimination builds End by hand, inlineing doesn't use
193      the End node. */
194   //assert(n->op == op_End ||  ((_ARR_DESCR(n->in))->cookie != ARR_F_MAGIC));
195
196   if (get_irn_opcode(n) == iro_Block) {
197     block = NULL;
198     new_arity = compute_new_arity(n);
199     n->attr.block.graph_arr = NULL;
200   } else {
201     block = get_nodes_Block(n);
202     if (get_irn_opcode(n) == iro_Phi) {
203       new_arity = compute_new_arity(block);
204     } else {
205       new_arity = get_irn_arity(n);
206     }
207   }
208   nn = new_ir_node(get_irn_dbg_info(n),
209                    current_ir_graph,
210                    block,
211                    get_irn_op(n),
212                    get_irn_mode(n),
213                    new_arity,
214                    get_irn_in(n));
215   /* Copy the attributes.  These might point to additional data.  If this
216      was allocated on the old obstack the pointers now are dangling.  This
217      frees e.g. the memory of the graph_arr allocated in new_immBlock. */
218   copy_attrs(n, nn);
219   new_backedge_info(nn);
220   set_new_node(n, nn);
221
222   /*  printf("\n old node: "); DDMSG2(n);
223       printf(" new node: "); DDMSG2(nn); */
224
225 }
226
227 /**
228  * Copies new predecessors of old node to new node remembered in link.
229  * Spare the Bad predecessors of Phi and Block nodes.
230  */
231 static void
232 copy_preds (ir_node *n, void *env) {
233   ir_node *nn, *block;
234   int i, j, irn_arity;
235
236   nn = get_new_node(n);
237
238   /* printf("\n old node: "); DDMSG2(n);
239      printf(" new node: "); DDMSG2(nn);
240      printf(" arities: old: %d, new: %d\n", get_irn_arity(n), get_irn_arity(nn)); */
241
242   if (get_irn_opcode(n) == iro_Block) {
243     /* Don't copy Bad nodes. */
244     j = 0;
245     irn_arity = get_irn_arity(n);
246     for (i = 0; i < irn_arity; i++)
247       if (get_irn_opcode(get_irn_n(n, i)) != iro_Bad) {
248         set_irn_n (nn, j, get_new_node(get_irn_n(n, i)));
249         /*if (is_backedge(n, i)) set_backedge(nn, j);*/
250         j++;
251       }
252     /* repair the block visited flag from above misuse. Repair it in both
253        graphs so that the old one can still be used. */
254     set_Block_block_visited(nn, 0);
255     set_Block_block_visited(n, 0);
256     /* Local optimization could not merge two subsequent blocks if
257        in array contained Bads.  Now it's possible.
258        We don't call optimize_in_place as it requires
259        that the fields in ir_graph are set properly. */
260     if ((get_opt_control_flow_straightening()) &&
261         (get_Block_n_cfgpreds(nn) == 1) &&
262         (get_irn_op(get_Block_cfgpred(nn, 0)) == op_Jmp))
263       exchange(nn, get_nodes_Block(get_Block_cfgpred(nn, 0)));
264   } else if (get_irn_opcode(n) == iro_Phi) {
265     /* Don't copy node if corresponding predecessor in block is Bad.
266        The Block itself should not be Bad. */
267     block = get_nodes_Block(n);
268     set_irn_n (nn, -1, get_new_node(block));
269     j = 0;
270     irn_arity = get_irn_arity(n);
271     for (i = 0; i < irn_arity; i++)
272       if (get_irn_opcode(get_irn_n(block, i)) != iro_Bad) {
273         set_irn_n (nn, j, get_new_node(get_irn_n(n, i)));
274         /*if (is_backedge(n, i)) set_backedge(nn, j);*/
275         j++;
276       }
277     /* If the pre walker reached this Phi after the post walker visited the
278        block block_visited is > 0. */
279     set_Block_block_visited(get_nodes_Block(n), 0);
280     /* Compacting the Phi's ins might generate Phis with only one
281        predecessor. */
282     if (get_irn_arity(n) == 1)
283       exchange(n, get_irn_n(n, 0));
284   } else {
285     irn_arity = get_irn_arity(n);
286     for (i = -1; i < irn_arity; i++)
287       set_irn_n (nn, i, get_new_node(get_irn_n(n, i)));
288   }
289   /* Now the new node is complete.  We can add it to the hash table for cse.
290      @@@ inlinening aborts if we identify End. Why? */
291   if(get_irn_op(nn) != op_End)
292     add_identities (current_ir_graph->value_table, nn);
293 }
294
295 /**
296  * Copies the graph recursively, compacts the keepalive of the end node.
297  */
298 static void
299 copy_graph (void) {
300   ir_node *oe, *ne; /* old end, new end */
301   ir_node *ka;      /* keep alive */
302   int i, irn_arity;
303
304   oe = get_irg_end(current_ir_graph);
305   /* copy the end node by hand, allocate dynamic in array! */
306   ne = new_ir_node(get_irn_dbg_info(oe),
307                    current_ir_graph,
308                    NULL,
309                    op_End,
310                    mode_X,
311                    -1,
312                    NULL);
313   /* Copy the attributes.  Well, there might be some in the future... */
314   copy_attrs(oe, ne);
315   set_new_node(oe, ne);
316
317   /* copy the live nodes */
318   irg_walk(get_nodes_Block(oe), copy_node, copy_preds, NULL);
319   /* copy_preds for the end node ... */
320   set_nodes_Block(ne, get_new_node(get_nodes_Block(oe)));
321
322   /*- ... and now the keep alives. -*/
323   /* First pick the not marked block nodes and walk them.  We must pick these
324      first as else we will oversee blocks reachable from Phis. */
325   irn_arity = get_irn_arity(oe);
326   for (i = 0; i < irn_arity; i++) {
327     ka = get_irn_n(oe, i);
328     if ((get_irn_op(ka) == op_Block) &&
329         (get_irn_visited(ka) < get_irg_visited(current_ir_graph))) {
330       /* We must keep the block alive and copy everything reachable */
331       set_irg_visited(current_ir_graph, get_irg_visited(current_ir_graph)-1);
332       irg_walk(ka, copy_node, copy_preds, NULL);
333       add_End_keepalive(ne, get_new_node(ka));
334     }
335   }
336
337   /* Now pick the Phis.  Here we will keep all! */
338   irn_arity = get_irn_arity(oe);
339   for (i = 0; i < irn_arity; i++) {
340     ka = get_irn_n(oe, i);
341     if ((get_irn_op(ka) == op_Phi)) {
342       if (get_irn_visited(ka) < get_irg_visited(current_ir_graph)) {
343         /* We didn't copy the Phi yet.  */
344         set_irg_visited(current_ir_graph, get_irg_visited(current_ir_graph)-1);
345         irg_walk(ka, copy_node, copy_preds, NULL);
346       }
347       add_End_keepalive(ne, get_new_node(ka));
348     }
349   }
350 }
351
352 /**
353  * Copies the graph reachable from current_ir_graph->end to the obstack
354  * in current_ir_graph and fixes the environment.
355  * Then fixes the fields in current_ir_graph containing nodes of the
356  * graph.
357  */
358 static void
359 copy_graph_env (void) {
360   ir_node *old_end;
361   /* Not all nodes remembered in current_ir_graph might be reachable
362      from the end node.  Assure their link is set to NULL, so that
363      we can test whether new nodes have been computed. */
364   set_irn_link(get_irg_frame  (current_ir_graph), NULL);
365   set_irn_link(get_irg_globals(current_ir_graph), NULL);
366   set_irn_link(get_irg_args   (current_ir_graph), NULL);
367
368   /* we use the block walk flag for removing Bads from Blocks ins. */
369   inc_irg_block_visited(current_ir_graph);
370
371   /* copy the graph */
372   copy_graph();
373
374   /* fix the fields in current_ir_graph */
375   old_end = get_irg_end(current_ir_graph);
376   set_irg_end (current_ir_graph, get_new_node(old_end));
377   free_End(old_end);
378   set_irg_end_block  (current_ir_graph, get_new_node(get_irg_end_block(current_ir_graph)));
379   if (get_irn_link(get_irg_frame(current_ir_graph)) == NULL) {
380     copy_node (get_irg_frame(current_ir_graph), NULL);
381     copy_preds(get_irg_frame(current_ir_graph), NULL);
382   }
383   if (get_irn_link(get_irg_globals(current_ir_graph)) == NULL) {
384     copy_node (get_irg_globals(current_ir_graph), NULL);
385     copy_preds(get_irg_globals(current_ir_graph), NULL);
386   }
387   if (get_irn_link(get_irg_args(current_ir_graph)) == NULL) {
388     copy_node (get_irg_args(current_ir_graph), NULL);
389     copy_preds(get_irg_args(current_ir_graph), NULL);
390   }
391   set_irg_start  (current_ir_graph, get_new_node(get_irg_start(current_ir_graph)));
392
393   set_irg_start_block(current_ir_graph,
394                       get_new_node(get_irg_start_block(current_ir_graph)));
395   set_irg_frame  (current_ir_graph, get_new_node(get_irg_frame(current_ir_graph)));
396   set_irg_globals(current_ir_graph, get_new_node(get_irg_globals(current_ir_graph)));
397   set_irg_args   (current_ir_graph, get_new_node(get_irg_args(current_ir_graph)));
398   if (get_irn_link(get_irg_bad(current_ir_graph)) == NULL) {
399     copy_node(get_irg_bad(current_ir_graph), NULL);
400     copy_preds(get_irg_bad(current_ir_graph), NULL);
401   }
402   set_irg_bad(current_ir_graph, get_new_node(get_irg_bad(current_ir_graph)));
403   /* GL removed: we need unknown with mode for analyses.
404   if (get_irn_link(get_irg_unknown(current_ir_graph)) == NULL) {
405     copy_node(get_irg_unknown(current_ir_graph), NULL);
406     copy_preds(get_irg_unknown(current_ir_graph), NULL);
407   }
408   set_irg_unknown(current_ir_graph, get_new_node(get_irg_unknown(current_ir_graph)));
409   */
410 }
411
412 /**
413  * Copies all reachable nodes to a new obstack.  Removes bad inputs
414  * from block nodes and the corresponding inputs from Phi nodes.
415  * Merges single exit blocks with single entry blocks and removes
416  * 1-input Phis.
417  * Adds all new nodes to a new hash table for cse.  Does not
418  * perform cse, so the hash table might contain common subexpressions.
419  */
420 /* Amroq call this emigrate() */
421 void
422 dead_node_elimination(ir_graph *irg) {
423   ir_graph *rem;
424   struct obstack *graveyard_obst = NULL;
425   struct obstack *rebirth_obst   = NULL;
426
427   /* Remember external state of current_ir_graph. */
428   rem = current_ir_graph;
429   current_ir_graph = irg;
430
431   /* Handle graph state */
432   assert(get_irg_phase_state(current_ir_graph) != phase_building);
433   assert(get_irg_callee_info_state(current_ir_graph) == irg_callee_info_none);
434   free_outs(current_ir_graph);
435
436   /* @@@ so far we loose loops when copying */
437   set_irg_loop(current_ir_graph, NULL);
438
439   if (get_opt_optimize() && get_opt_dead_node_elimination()) {
440
441     /* A quiet place, where the old obstack can rest in peace,
442        until it will be cremated. */
443     graveyard_obst = irg->obst;
444
445     /* A new obstack, where the reachable nodes will be copied to. */
446     rebirth_obst = (struct obstack *) xmalloc (sizeof (struct obstack));
447     current_ir_graph->obst = rebirth_obst;
448     obstack_init (current_ir_graph->obst);
449
450     /* We also need a new hash table for cse */
451     del_identities (irg->value_table);
452     irg->value_table = new_identities ();
453
454     /* Copy the graph from the old to the new obstack */
455     copy_graph_env();
456
457     /* Free memory from old unoptimized obstack */
458     obstack_free(graveyard_obst, 0);  /* First empty the obstack ... */
459     xfree (graveyard_obst);           /* ... then free it.           */
460   }
461
462   current_ir_graph = rem;
463 }
464
465 /**
466  * Relink bad predeseccors of a block and store the old in array to the
467  * link field. This function is called by relink_bad_predecessors().
468  * The array of link field starts with the block operand at position 0.
469  * If block has bad predecessors, create a new in array without bad preds.
470  * Otherwise let in array untouched.
471  */
472 static void relink_bad_block_predecessors(ir_node *n, void *env) {
473   ir_node **new_in, *irn;
474   int i, new_irn_n, old_irn_arity, new_irn_arity = 0;
475
476   /* if link field of block is NULL, look for bad predecessors otherwise
477      this is allready done */
478   if (get_irn_op(n) == op_Block &&
479       get_irn_link(n) == NULL) {
480
481     /* save old predecessors in link field (position 0 is the block operand)*/
482     set_irn_link(n, (void *)get_irn_in(n));
483
484     /* count predecessors without bad nodes */
485     old_irn_arity = get_irn_arity(n);
486     for (i = 0; i < old_irn_arity; i++)
487       if (!is_Bad(get_irn_n(n, i))) new_irn_arity++;
488
489     /* arity changing: set new predecessors without bad nodes */
490     if (new_irn_arity < old_irn_arity) {
491       /* get new predecessor array without Block predecessor */
492       new_in = NEW_ARR_D (ir_node *, current_ir_graph->obst, (new_irn_arity+1));
493
494       /* set new predeseccors in array */
495       new_in[0] = NULL;
496       new_irn_n = 1;
497       for (i = 1; i < old_irn_arity; i++) {
498         irn = get_irn_n(n, i);
499         if (!is_Bad(irn)) new_in[new_irn_n++] = irn;
500       }
501       n->in = new_in;
502     } /* ir node has bad predecessors */
503
504   } /* Block is not relinked */
505 }
506
507 /**
508  * Relinks Bad predecesors from Bocks and Phis called by walker
509  * remove_bad_predecesors(). If n is a Block, call
510  * relink_bad_block_redecessors(). If n is a Phinode, call also the relinking
511  * function of Phi's Block. If this block has bad predecessors, relink preds
512  * of the Phinode.
513  */
514 static void relink_bad_predecessors(ir_node *n, void *env) {
515   ir_node *block, **old_in;
516   int i, old_irn_arity, new_irn_arity;
517
518   /* relink bad predeseccors of a block */
519   if (get_irn_op(n) == op_Block)
520     relink_bad_block_predecessors(n, env);
521
522   /* If Phi node relink its block and its predecessors */
523   if (get_irn_op(n) == op_Phi) {
524
525     /* Relink predeseccors of phi's block */
526     block = get_nodes_Block(n);
527     if (get_irn_link(block) == NULL)
528       relink_bad_block_predecessors(block, env);
529
530     old_in = (ir_node **)get_irn_link(block); /* Of Phi's Block */
531     old_irn_arity = ARR_LEN(old_in);
532
533     /* Relink Phi predeseccors if count of predeseccors changed */
534     if (old_irn_arity != ARR_LEN(get_irn_in(block))) {
535       /* set new predeseccors in array
536          n->in[0] remains the same block */
537       new_irn_arity = 1;
538       for(i = 1; i < old_irn_arity; i++)
539         if (!is_Bad((ir_node *)old_in[i])) n->in[new_irn_arity++] = n->in[i];
540
541       ARR_SETLEN(ir_node *, n->in, new_irn_arity);
542     }
543
544   } /* n is a Phi node */
545 }
546
547 /**
548  * Removes Bad Bad predecesors from Blocks and the corresponding
549  * inputs to Phi nodes as in dead_node_elimination but without
550  * copying the graph.
551  * On walking up set the link field to NULL, on walking down call
552  * relink_bad_predecessors() (This function stores the old in array
553  * to the link field and sets a new in array if arity of predecessors
554  * changes).
555  */
556 void remove_bad_predecessors(ir_graph *irg) {
557   irg_walk_graph(irg, init_link, relink_bad_predecessors, NULL);
558 }
559
560
561 /*--------------------------------------------------------------------*/
562 /*  Funcionality for inlining                                         */
563 /*--------------------------------------------------------------------*/
564
565 /**
566  * Copy node for inlineing.  Updates attributes that change when
567  * inlineing but not for dead node elimination.
568  *
569  * Copies the node by calling copy_node and then updates the entity if
570  * it's a local one.  env must be a pointer of the frame type of the
571  * inlined procedure. The new entities must be in the link field of
572  * the entities.
573  */
574 static INLINE void
575 copy_node_inline (ir_node *n, void *env) {
576   ir_node *new;
577   type *frame_tp = (type *)env;
578
579   copy_node(n, NULL);
580   if (get_irn_op(n) == op_Sel) {
581     new = get_new_node (n);
582     assert(get_irn_op(new) == op_Sel);
583     if (get_entity_owner(get_Sel_entity(n)) == frame_tp) {
584       set_Sel_entity(new, get_entity_link(get_Sel_entity(n)));
585     }
586   } else if (get_irn_op(n) == op_Block) {
587     new = get_new_node (n);
588     new->attr.block.irg = current_ir_graph;
589   }
590 }
591
592
593 void inline_method(ir_node *call, ir_graph *called_graph) {
594   ir_node *pre_call;
595   ir_node *post_call, *post_bl;
596   ir_node *in[5];
597   ir_node *end, *end_bl;
598   ir_node **res_pred;
599   ir_node **cf_pred;
600   ir_node *ret, *phi;
601   int arity, n_ret, n_exc, n_res, i, j, rem_opt, irn_arity;
602   int exc_handling;
603   type *called_frame;
604
605   if ( !(get_irg_inline_property(called_graph) == irg_inline_forced) && (!get_opt_optimize() || !get_opt_inline() ||
606       (get_irg_inline_property(called_graph) == irg_inline_forbidden))) return;
607
608   /* --  Turn off optimizations, this can cause problems when allocating new nodes. -- */
609   rem_opt = get_opt_optimize();
610   set_optimize(0);
611
612   /* Handle graph state */
613   assert(get_irg_phase_state(current_ir_graph) != phase_building);
614   assert(get_irg_pinned(current_ir_graph) == pinned);
615   assert(get_irg_pinned(called_graph) == pinned);
616   if (get_irg_outs_state(current_ir_graph) == outs_consistent)
617     set_irg_outs_inconsistent(current_ir_graph);
618
619   /* -- Check preconditions -- */
620   assert(get_irn_op(call) == op_Call);
621   /* @@@ does not work for InterfaceIII.java after cgana
622      assert(get_Call_type(call) == get_entity_type(get_irg_ent(called_graph)));
623      assert(smaller_type(get_entity_type(get_irg_ent(called_graph)),
624      get_Call_type(call)));
625   */
626   assert(get_type_tpop(get_Call_type(call)) == type_method);
627   if (called_graph == current_ir_graph) {
628     set_optimize(rem_opt);
629     return;
630   }
631
632   /* -- Decide how to handle exception control flow: Is there a handler
633      for the Call node, or do we branch directly to End on an exception?
634      exc_handling: 0 There is a handler.
635                    1 Branches to End.
636                    2 Exception handling not represented in Firm. -- */
637   {
638     ir_node *proj, *Mproj = NULL, *Xproj = NULL;
639     for (proj = (ir_node *)get_irn_link(call); proj; proj = (ir_node *)get_irn_link(proj)) {
640       assert(get_irn_op(proj) == op_Proj);
641       if (get_Proj_proj(proj) == pn_Call_X_except) Xproj = proj;
642       if (get_Proj_proj(proj) == pn_Call_M_except) Mproj = proj;
643     }
644     if      (Mproj) { assert(Xproj); exc_handling = 0; } // Mproj
645     else if (Xproj) {                exc_handling = 1; } //!Mproj &&  Xproj
646     else            {                exc_handling = 2; } //!Mproj && !Xproj
647   }
648
649
650   /* --
651       the procedure and later replaces the Start node of the called graph.
652       Post_call is the old Call node and collects the results of the called
653       graph. Both will end up being a tuple.  -- */
654   post_bl = get_nodes_Block(call);
655   set_irg_current_block(current_ir_graph, post_bl);
656   /* XxMxPxP of Start + parameter of Call */
657   in[0] = new_Jmp();
658   in[1] = get_Call_mem(call);
659   in[2] = get_irg_frame(current_ir_graph);
660   in[3] = get_irg_globals(current_ir_graph);
661   in[4] = new_Tuple (get_Call_n_params(call), get_Call_param_arr(call));
662   pre_call = new_Tuple(5, in);
663   post_call = call;
664
665   /* --
666       The new block gets the ins of the old block, pre_call and all its
667       predecessors and all Phi nodes. -- */
668   part_block(pre_call);
669
670   /* -- Prepare state for dead node elimination -- */
671   /* Visited flags in calling irg must be >= flag in called irg.
672      Else walker and arity computation will not work. */
673   if (get_irg_visited(current_ir_graph) <= get_irg_visited(called_graph))
674     set_irg_visited(current_ir_graph, get_irg_visited(called_graph)+1);
675   if (get_irg_block_visited(current_ir_graph)< get_irg_block_visited(called_graph))
676     set_irg_block_visited(current_ir_graph, get_irg_block_visited(called_graph));
677   /* Set pre_call as new Start node in link field of the start node of
678      calling graph and pre_calls block as new block for the start block
679      of calling graph.
680      Further mark these nodes so that they are not visited by the
681      copying. */
682   set_irn_link(get_irg_start(called_graph), pre_call);
683   set_irn_visited(get_irg_start(called_graph),
684                   get_irg_visited(current_ir_graph));
685   set_irn_link(get_irg_start_block(called_graph),
686                get_nodes_Block(pre_call));
687   set_irn_visited(get_irg_start_block(called_graph),
688                   get_irg_visited(current_ir_graph));
689
690   /* Initialize for compaction of in arrays */
691   inc_irg_block_visited(current_ir_graph);
692
693   /* -- Replicate local entities of the called_graph -- */
694   /* copy the entities. */
695   called_frame = get_irg_frame_type(called_graph);
696   for (i = 0; i < get_class_n_members(called_frame); i++) {
697     entity *new_ent, *old_ent;
698     old_ent = get_class_member(called_frame, i);
699     new_ent = copy_entity_own(old_ent, get_cur_frame_type());
700     set_entity_link(old_ent, new_ent);
701   }
702
703   /* visited is > than that of called graph.  With this trick visited will
704      remain unchanged so that an outer walker, e.g., searching the call nodes
705      to inline, calling this inline will not visit the inlined nodes. */
706   set_irg_visited(current_ir_graph, get_irg_visited(current_ir_graph)-1);
707
708   /* -- Performing dead node elimination inlines the graph -- */
709   /* Copies the nodes to the obstack of current_ir_graph. Updates links to new
710      entities. */
711   /* @@@ endless loops are not copied!! -- they should be, I think... */
712   irg_walk(get_irg_end(called_graph), copy_node_inline, copy_preds,
713            get_irg_frame_type(called_graph));
714
715   /* Repair called_graph */
716   set_irg_visited(called_graph, get_irg_visited(current_ir_graph));
717   set_irg_block_visited(called_graph, get_irg_block_visited(current_ir_graph));
718   set_Block_block_visited(get_irg_start_block(called_graph), 0);
719
720   /* -- Merge the end of the inlined procedure with the call site -- */
721   /* We will turn the old Call node into a Tuple with the following
722      predecessors:
723        -1:  Block of Tuple.
724        0: Phi of all Memories of Return statements.
725        1: Jmp from new Block that merges the control flow from all exception
726           predecessors of the old end block.
727        2: Tuple of all arguments.
728        3: Phi of Exception memories.
729      In case the old Call directly branches to End on an exception we don't
730      need the block merging all exceptions nor the Phi of the exception
731      memories.
732   */
733
734   /* -- Precompute some values -- */
735   end_bl = get_new_node(get_irg_end_block(called_graph));
736   end = get_new_node(get_irg_end(called_graph));
737   arity = get_irn_arity(end_bl);    /* arity = n_exc + n_ret  */
738   n_res = get_method_n_ress(get_Call_type(call));
739
740   res_pred = (ir_node **) malloc (n_res * sizeof (ir_node *));
741   cf_pred =  (ir_node **) malloc (arity * sizeof (ir_node *));
742
743   set_irg_current_block(current_ir_graph, post_bl); /* just to make sure */
744
745   /* -- archive keepalives -- */
746   irn_arity = get_irn_arity(end);
747   for (i = 0; i < irn_arity; i++)
748     add_End_keepalive(get_irg_end(current_ir_graph), get_irn_n(end, i));
749
750   /* The new end node will die.  We need not free as the in array is on the obstack:
751      copy_node only generated 'D' arrays. */
752
753   /* -- Replace Return nodes by Jump nodes. -- */
754   n_ret = 0;
755   for (i = 0; i < arity; i++) {
756     ir_node *ret;
757     ret = get_irn_n(end_bl, i);
758     if (get_irn_op(ret) == op_Return) {
759       cf_pred[n_ret] = new_r_Jmp(current_ir_graph, get_nodes_Block(ret));
760       n_ret++;
761     }
762   }
763   set_irn_in(post_bl, n_ret, cf_pred);
764
765   /* -- Build a Tuple for all results of the method.
766      Add Phi node if there was more than one Return.  -- */
767   turn_into_tuple(post_call, 4);
768   /* First the Memory-Phi */
769   n_ret = 0;
770   for (i = 0; i < arity; i++) {
771     ret = get_irn_n(end_bl, i);
772     if (get_irn_op(ret) == op_Return) {
773       cf_pred[n_ret] = get_Return_mem(ret);
774       n_ret++;
775     }
776   }
777   phi = new_Phi(n_ret, cf_pred, mode_M);
778   set_Tuple_pred(call, 0, phi);
779   /* Conserve Phi-list for further inlinings -- but might be optimized */
780   if (get_nodes_Block(phi) == post_bl) {
781     set_irn_link(phi, get_irn_link(post_bl));
782     set_irn_link(post_bl, phi);
783   }
784   /* Now the real results */
785   if (n_res > 0) {
786     for (j = 0; j < n_res; j++) {
787       n_ret = 0;
788       for (i = 0; i < arity; i++) {
789         ret = get_irn_n(end_bl, i);
790         if (get_irn_op(ret) == op_Return) {
791           cf_pred[n_ret] = get_Return_res(ret, j);
792           n_ret++;
793         }
794       }
795       phi = new_Phi(n_ret, cf_pred, get_irn_mode(cf_pred[0]));
796       res_pred[j] = phi;
797       /* Conserve Phi-list for further inlinings -- but might be optimized */
798       if (get_nodes_Block(phi) == post_bl) {
799         set_irn_link(phi, get_irn_link(post_bl));
800         set_irn_link(post_bl, phi);
801       }
802     }
803     set_Tuple_pred(call, 2, new_Tuple(n_res, res_pred));
804   } else {
805     set_Tuple_pred(call, 2, new_Bad());
806   }
807   /* Finally the exception control flow.
808      We have two (three) possible situations:
809      First if the Call branches to an exception handler: We need to add a Phi node to
810      collect the memory containing the exception objects.  Further we need
811      to add another block to get a correct representation of this Phi.  To
812      this block we add a Jmp that resolves into the X output of the Call
813      when the Call is turned into a tuple.
814      Second the Call branches to End, the exception is not handled.  Just
815      add all inlined exception branches to the End node.
816      Third: there is no Exception edge at all. Handle as case two. */
817   if (exc_handling == 0) {
818     n_exc = 0;
819     for (i = 0; i < arity; i++) {
820       ir_node *ret;
821       ret = get_irn_n(end_bl, i);
822       if (is_fragile_op(skip_Proj(ret)) || (get_irn_op(skip_Proj(ret)) == op_Raise)) {
823         cf_pred[n_exc] = ret;
824         n_exc++;
825       }
826     }
827     if (n_exc > 0) {
828       new_Block(n_exc, cf_pred);      /* watch it: current_block is changed! */
829       set_Tuple_pred(call, 1, new_Jmp());
830       /* The Phi for the memories with the exception objects */
831       n_exc = 0;
832       for (i = 0; i < arity; i++) {
833         ir_node *ret;
834         ret = skip_Proj(get_irn_n(end_bl, i));
835         if (get_irn_op(ret) == op_Call) {
836           cf_pred[n_exc] = new_r_Proj(current_ir_graph, get_nodes_Block(ret), ret, mode_M, 3);
837           n_exc++;
838         } else if (is_fragile_op(ret)) {
839         /* We rely that all cfops have the memory output at the same position. */
840           cf_pred[n_exc] = new_r_Proj(current_ir_graph, get_nodes_Block(ret), ret, mode_M, 0);
841           n_exc++;
842         } else if (get_irn_op(ret) == op_Raise) {
843           cf_pred[n_exc] = new_r_Proj(current_ir_graph, get_nodes_Block(ret), ret, mode_M, 1);
844           n_exc++;
845         }
846       }
847       set_Tuple_pred(call, 3, new_Phi(n_exc, cf_pred, mode_M));
848     } else {
849       set_Tuple_pred(call, 1, new_Bad());
850       set_Tuple_pred(call, 3, new_Bad());
851     }
852   } else {
853     ir_node *main_end_bl;
854     int main_end_bl_arity;
855     ir_node **end_preds;
856
857     /* assert(exc_handling == 1 || no exceptions. ) */
858     n_exc = 0;
859     for (i = 0; i < arity; i++) {
860       ir_node *ret = get_irn_n(end_bl, i);
861
862       if (is_fragile_op(skip_Proj(ret)) || (get_irn_op(skip_Proj(ret)) == op_Raise)) {
863         cf_pred[n_exc] = ret;
864         n_exc++;
865       }
866     }
867     main_end_bl = get_irg_end_block(current_ir_graph);
868     main_end_bl_arity = get_irn_arity(main_end_bl);
869     end_preds =  (ir_node **) malloc ((n_exc + main_end_bl_arity) * sizeof (ir_node *));
870
871     for (i = 0; i < main_end_bl_arity; ++i)
872       end_preds[i] = get_irn_n(main_end_bl, i);
873     for (i = 0; i < n_exc; ++i)
874       end_preds[main_end_bl_arity + i] = cf_pred[i];
875     set_irn_in(main_end_bl, n_exc + main_end_bl_arity, end_preds);
876     set_Tuple_pred(call, 1, new_Bad());
877     set_Tuple_pred(call, 3, new_Bad());
878     free(end_preds);
879   }
880   free(res_pred);
881   free(cf_pred);
882
883 #if 0  /* old. now better, correcter, faster implementation. */
884   if (n_exc > 0) {
885     /* -- If the exception control flow from the inlined Call directly
886        branched to the end block we now have the following control
887        flow predecessor pattern: ProjX -> Tuple -> Jmp.  We must
888        remove the Jmp along with it's empty block and add Jmp's
889        predecessors as predecessors of this end block.  No problem if
890        there is no exception, because then branches Bad to End which
891        is fine. --
892        @@@ can't we know this beforehand: by getting the Proj(1) from
893        the Call link list and checking whether it goes to Proj. */
894     /* find the problematic predecessor of the end block. */
895     end_bl = get_irg_end_block(current_ir_graph);
896     for (i = 0; i < get_Block_n_cfgpreds(end_bl); i++) {
897       cf_op = get_Block_cfgpred(end_bl, i);
898       if (get_irn_op(cf_op) == op_Proj) {
899         cf_op = get_Proj_pred(cf_op);
900         if ((get_irn_op(cf_op) == op_Tuple) && (cf_op == call)) {
901           // There are unoptimized tuples from inlineing before when no exc
902           assert(get_Proj_proj(get_Block_cfgpred(end_bl, i)) == pn_Call_X_except);
903           cf_op = get_Tuple_pred(cf_op, pn_Call_X_except);
904           assert(get_irn_op(cf_op) == op_Jmp);
905           break;
906         }
907       }
908     }
909     /* repair */
910     if (i < get_Block_n_cfgpreds(end_bl)) {
911       bl = get_nodes_Block(cf_op);
912       arity = get_Block_n_cfgpreds(end_bl) + get_Block_n_cfgpreds(bl) - 1;
913       cf_pred = (ir_node **) malloc (arity * sizeof (ir_node *));
914       for (j = 0; j < i; j++)
915         cf_pred[j] = get_Block_cfgpred(end_bl, j);
916       for (j = j; j < i + get_Block_n_cfgpreds(bl); j++)
917         cf_pred[j] = get_Block_cfgpred(bl, j-i);
918       for (j = j; j < arity; j++)
919         cf_pred[j] = get_Block_cfgpred(end_bl, j-get_Block_n_cfgpreds(bl) +1);
920       set_irn_in(end_bl, arity, cf_pred);
921       free(cf_pred);
922       // Remove the exception pred from post-call Tuple.
923       set_Tuple_pred(call, pn_Call_X_except, new_Bad());
924     }
925   }
926 #endif
927
928   /* --  Turn cse back on. -- */
929   set_optimize(rem_opt);
930 }
931
932 /********************************************************************/
933 /* Apply inlineing to small methods.                                */
934 /********************************************************************/
935
936 static int pos;
937
938 /* It makes no sense to inline too many calls in one procedure. Anyways,
939    I didn't get a version with NEW_ARR_F to run. */
940 #define MAX_INLINE 1024
941
942 /**
943  * Returns the irg called from a Call node. If the irg is not
944  * known, NULL is returned.
945  */
946 static ir_graph *get_call_called_irg(ir_node *call) {
947   ir_node *addr;
948   tarval *tv;
949   ir_graph *called_irg = NULL;
950
951   assert(get_irn_op(call) == op_Call);
952
953   addr = get_Call_ptr(call);
954   if (get_irn_op(addr) == op_Const) {
955     /* Check whether the constant is the pointer to a compiled entity. */
956     tv = get_Const_tarval(addr);
957     if (tarval_to_entity(tv))
958       called_irg = get_entity_irg(tarval_to_entity(tv));
959   }
960   return called_irg;
961 }
962
963 static void collect_calls(ir_node *call, void *env) {
964
965   ir_node **calls = (ir_node **)env;
966   ir_node *addr;
967   tarval *tv;
968   ir_graph *called_irg;
969
970   if (get_irn_op(call) != op_Call) return;
971
972   addr = get_Call_ptr(call);
973   if (get_irn_op(addr) == op_Const) {
974     /* Check whether the constant is the pointer to a compiled entity. */
975     tv = get_Const_tarval(addr);
976     if (tarval_to_entity(tv)) {
977       called_irg = get_entity_irg(tarval_to_entity(tv));
978       if (called_irg && pos < MAX_INLINE) {
979         /* The Call node calls a locally defined method.  Remember to inline. */
980         calls[pos] = call;
981         pos++;
982       }
983     }
984   }
985 }
986
987 /**
988  * Inlines all small methods at call sites where the called address comes
989  * from a Const node that references the entity representing the called
990  * method.
991  * The size argument is a rough measure for the code size of the method:
992  * Methods where the obstack containing the firm graph is smaller than
993  * size are inlined.
994  */
995 void inline_small_irgs(ir_graph *irg, int size) {
996   int i;
997   ir_node *calls[MAX_INLINE];
998   ir_graph *rem = current_ir_graph;
999
1000   if (!(get_opt_optimize() && get_opt_inline())) return;
1001
1002   current_ir_graph = irg;
1003   /* Handle graph state */
1004   assert(get_irg_phase_state(current_ir_graph) != phase_building);
1005   assert(get_irg_callee_info_state(current_ir_graph) == irg_callee_info_none);
1006
1007   /* Find Call nodes to inline.
1008      (We can not inline during a walk of the graph, as inlineing the same
1009      method several times changes the visited flag of the walked graph:
1010      after the first inlineing visited of the callee equals visited of
1011      the caller.  With the next inlineing both are increased.) */
1012   pos = 0;
1013   irg_walk(get_irg_end(irg), NULL, collect_calls, (void *) calls);
1014
1015   if ((pos > 0) && (pos < MAX_INLINE)) {
1016     /* There are calls to inline */
1017     collect_phiprojs(irg);
1018     for (i = 0; i < pos; i++) {
1019       tarval *tv;
1020       ir_graph *callee;
1021       tv = get_Const_tarval(get_Call_ptr(calls[i]));
1022       callee = get_entity_irg(tarval_to_entity(tv));
1023       if (((_obstack_memory_used(callee->obst) - obstack_room(callee->obst)) < size) ||
1024           (get_irg_inline_property(callee) == irg_inline_forced)) {
1025         inline_method(calls[i], callee);
1026       }
1027     }
1028   }
1029
1030   current_ir_graph = rem;
1031 }
1032
1033 /**
1034  * Environment for inlining irgs.
1035  */
1036 typedef struct {
1037   int n_nodes;       /**< Nodes in graph except Id, Tuple, Proj, Start, End */
1038   int n_nodes_orig;  /**< for statistics */
1039   eset *call_nodes;  /**< All call nodes in this graph */
1040   int n_call_nodes;
1041   int n_call_nodes_orig; /**< for statistics */
1042   int n_callers;   /**< Number of known graphs that call this graphs. */
1043   int n_callers_orig; /**< for statistics */
1044 } inline_irg_env;
1045
1046 static inline_irg_env *new_inline_irg_env(void) {
1047   inline_irg_env *env = malloc(sizeof(inline_irg_env));
1048   env->n_nodes = -2; /* uncount Start, End */
1049   env->n_nodes_orig = -2; /* uncount Start, End */
1050   env->call_nodes = eset_create();
1051   env->n_call_nodes = 0;
1052   env->n_call_nodes_orig = 0;
1053   env->n_callers = 0;
1054   env->n_callers_orig = 0;
1055   return env;
1056 }
1057
1058 static void free_inline_irg_env(inline_irg_env *env) {
1059   eset_destroy(env->call_nodes);
1060   free(env);
1061 }
1062
1063 static void collect_calls2(ir_node *call, void *env) {
1064   inline_irg_env *x = (inline_irg_env *)env;
1065   ir_op *op = get_irn_op(call);
1066   ir_graph *callee;
1067
1068   /* count nodes in irg */
1069   if (op != op_Proj && op != op_Tuple && op != op_Sync) {
1070     x->n_nodes++;
1071     x->n_nodes_orig++;
1072   }
1073
1074   if (op != op_Call) return;
1075
1076   /* collect all call nodes */
1077   eset_insert(x->call_nodes, (void *)call);
1078   x->n_call_nodes++;
1079   x->n_call_nodes_orig++;
1080
1081   /* count all static callers */
1082   callee = get_call_called_irg(call);
1083   if (callee) {
1084     ((inline_irg_env *)get_irg_link(callee))->n_callers++;
1085     ((inline_irg_env *)get_irg_link(callee))->n_callers_orig++;
1086   }
1087 }
1088
1089 INLINE static int is_leave(ir_graph *irg) {
1090   return (((inline_irg_env *)get_irg_link(irg))->n_call_nodes == 0);
1091 }
1092
1093 INLINE static int is_smaller(ir_graph *callee, int size) {
1094   return (((inline_irg_env *)get_irg_link(callee))->n_nodes < size);
1095 }
1096
1097
1098 /**
1099  * Inlines small leave methods at call sites where the called address comes
1100  * from a Const node that references the entity representing the called
1101  * method.
1102  * The size argument is a rough measure for the code size of the method:
1103  * Methods where the obstack containing the firm graph is smaller than
1104  * size are inlined.
1105  */
1106 void inline_leave_functions(int maxsize, int leavesize, int size) {
1107   inline_irg_env *env;
1108   int i, n_irgs = get_irp_n_irgs();
1109   ir_graph *rem = current_ir_graph;
1110   int did_inline = 1;
1111
1112   if (!(get_opt_optimize() && get_opt_inline())) return;
1113
1114   /* extend all irgs by a temporary data structure for inlineing. */
1115   for (i = 0; i < n_irgs; ++i)
1116     set_irg_link(get_irp_irg(i), new_inline_irg_env());
1117
1118   /* Precompute information in temporary data structure. */
1119   for (i = 0; i < n_irgs; ++i) {
1120     current_ir_graph = get_irp_irg(i);
1121     assert(get_irg_phase_state(current_ir_graph) != phase_building);
1122     assert(get_irg_callee_info_state(current_ir_graph) == irg_callee_info_none);
1123
1124     irg_walk(get_irg_end(current_ir_graph), NULL, collect_calls2,
1125              get_irg_link(current_ir_graph));
1126     env = (inline_irg_env *)get_irg_link(current_ir_graph);
1127   }
1128
1129   /* and now inline.
1130      Inline leaves recursively -- we might construct new leaves. */
1131   //int itercnt = 1;
1132   while (did_inline) {
1133     //printf("iteration %d\n", itercnt++);
1134     did_inline = 0;
1135     for (i = 0; i < n_irgs; ++i) {
1136       ir_node *call;
1137       eset *walkset;
1138       int phiproj_computed = 0;
1139
1140       current_ir_graph = get_irp_irg(i);
1141       env = (inline_irg_env *)get_irg_link(current_ir_graph);
1142
1143       /* we can not walk and change a set, nor remove from it.
1144       So recompute.*/
1145       walkset = env->call_nodes;
1146       env->call_nodes = eset_create();
1147       for (call = eset_first(walkset); call; call = eset_next(walkset)) {
1148         inline_irg_env *callee_env;
1149         ir_graph *callee = get_call_called_irg(call);
1150
1151         if (env->n_nodes > maxsize) break;
1152         if (callee &&
1153             ((is_leave(callee) && is_smaller(callee, leavesize)) ||
1154              (get_irg_inline_property(callee) == irg_inline_forced))) {
1155           if (!phiproj_computed) {
1156             phiproj_computed = 1;
1157             collect_phiprojs(current_ir_graph);
1158           }
1159           callee_env = (inline_irg_env *)get_irg_link(callee);
1160 //        printf(" %s: Inlineing %s.\n", get_entity_name(get_irg_entity(current_ir_graph)),
1161 //            get_entity_name(get_irg_entity(callee)));
1162           inline_method(call, callee);
1163           did_inline = 1;
1164           env->n_call_nodes--;
1165           eset_insert_all(env->call_nodes, callee_env->call_nodes);
1166           env->n_call_nodes += callee_env->n_call_nodes;
1167           env->n_nodes += callee_env->n_nodes;
1168           callee_env->n_callers--;
1169         } else {
1170           eset_insert(env->call_nodes, call);
1171         }
1172       }
1173       eset_destroy(walkset);
1174     }
1175   }
1176
1177   //printf("Non leaves\n");
1178   /* inline other small functions. */
1179   for (i = 0; i < n_irgs; ++i) {
1180     ir_node *call;
1181     eset *walkset;
1182     int phiproj_computed = 0;
1183
1184     current_ir_graph = get_irp_irg(i);
1185     env = (inline_irg_env *)get_irg_link(current_ir_graph);
1186
1187     /* we can not walk and change a set, nor remove from it.
1188        So recompute.*/
1189     walkset = env->call_nodes;
1190     env->call_nodes = eset_create();
1191     for (call = eset_first(walkset); call; call = eset_next(walkset)) {
1192       inline_irg_env *callee_env;
1193       ir_graph *callee = get_call_called_irg(call);
1194
1195       if (env->n_nodes > maxsize) break;
1196       if (callee && is_smaller(callee, size)) {
1197         if (!phiproj_computed) {
1198                 phiproj_computed = 1;
1199                 collect_phiprojs(current_ir_graph);
1200         }
1201         callee_env = (inline_irg_env *)get_irg_link(callee);
1202 //      printf(" %s: Inlineing %s.\n", get_entity_name(get_irg_entity(current_ir_graph)),
1203 //      get_entity_name(get_irg_entity(callee)));
1204         inline_method(call, callee);
1205         did_inline = 1;
1206         env->n_call_nodes--;
1207         eset_insert_all(env->call_nodes, callee_env->call_nodes);
1208         env->n_call_nodes += callee_env->n_call_nodes;
1209         env->n_nodes += callee_env->n_nodes;
1210         callee_env->n_callers--;
1211       } else {
1212         eset_insert(env->call_nodes, call);
1213       }
1214     }
1215     eset_destroy(walkset);
1216   }
1217
1218   for (i = 0; i < n_irgs; ++i) {
1219     current_ir_graph = get_irp_irg(i);
1220 #if 0
1221     env = (inline_irg_env *)get_irg_link(current_ir_graph);
1222     if ((env->n_call_nodes_orig != env->n_call_nodes) ||
1223         (env->n_callers_orig != env->n_callers))
1224       printf("Nodes:%3d ->%3d, calls:%3d ->%3d, callers:%3d ->%3d, -- %s\n",
1225              env->n_nodes_orig, env->n_nodes, env->n_call_nodes_orig, env->n_call_nodes,
1226              env->n_callers_orig, env->n_callers,
1227              get_entity_name(get_irg_entity(current_ir_graph)));
1228 #endif
1229     free_inline_irg_env((inline_irg_env *)get_irg_link(current_ir_graph));
1230   }
1231
1232   current_ir_graph = rem;
1233 }
1234
1235 /*-----------------------------------------------------------------*/
1236 /*  Code Placement.  Pins all floating nodes to a block where they */
1237 /*  will be executed only if needed.                               */
1238 /*-----------------------------------------------------------------*/
1239
1240 /**
1241  * Find the earliest correct block for N.  --- Place N into the
1242  * same Block as its dominance-deepest Input.
1243  */
1244 static void
1245 place_floats_early(ir_node *n, pdeq *worklist)
1246 {
1247   int i, start, irn_arity;
1248
1249   /* we must not run into an infinite loop */
1250   assert (irn_not_visited(n));
1251   mark_irn_visited(n);
1252
1253   /* Place floating nodes. */
1254   if (get_op_pinned(get_irn_op(n)) == floats) {
1255     int depth = 0;
1256     ir_node *b = new_Bad();   /* The block to place this node in */
1257
1258     assert(get_irn_op(n) != op_Block);
1259
1260     if ((get_irn_op(n) == op_Const) ||
1261         (get_irn_op(n) == op_SymConst) ||
1262         (is_Bad(n)) ||
1263         (get_irn_op(n) == op_Unknown)) {
1264       /* These nodes will not be placed by the loop below. */
1265       b = get_irg_start_block(current_ir_graph);
1266       depth = 1;
1267     }
1268
1269     /* find the block for this node. */
1270     irn_arity = get_irn_arity(n);
1271     for (i = 0; i < irn_arity; i++) {
1272       ir_node *dep = get_irn_n(n, i);
1273       ir_node *dep_block;
1274       if ((irn_not_visited(dep)) &&
1275           (get_op_pinned(get_irn_op(dep)) == floats)) {
1276         place_floats_early(dep, worklist);
1277       }
1278       /* Because all loops contain at least one pinned node, now all
1279          our inputs are either pinned or place_early has already
1280          been finished on them.  We do not have any unfinished inputs!  */
1281       dep_block = get_nodes_Block(dep);
1282       if ((!is_Bad(dep_block)) &&
1283           (get_Block_dom_depth(dep_block) > depth)) {
1284         b = dep_block;
1285         depth = get_Block_dom_depth(dep_block);
1286       }
1287       /* Avoid that the node is placed in the Start block */
1288       if ((depth == 1) && (get_Block_dom_depth(get_nodes_Block(n)) > 1)) {
1289         b = get_Block_cfg_out(get_irg_start_block(current_ir_graph), 0);
1290         assert(b != get_irg_start_block(current_ir_graph));
1291         depth = 2;
1292       }
1293     }
1294     set_nodes_Block(n, b);
1295   }
1296
1297   /* Add predecessors of non floating nodes on worklist. */
1298   start = (get_irn_op(n) == op_Block) ? 0 : -1;
1299   irn_arity = get_irn_arity(n);
1300   for (i = start; i < irn_arity; i++) {
1301     ir_node *pred = get_irn_n(n, i);
1302     if (irn_not_visited(pred)) {
1303       pdeq_putr (worklist, pred);
1304     }
1305   }
1306 }
1307
1308 /**
1309  * Floating nodes form subgraphs that begin at nodes as Const, Load,
1310  * Start, Call and end at pinned nodes as Store, Call.  Place_early
1311  * places all floating nodes reachable from its argument through floating
1312  * nodes and adds all beginnings at pinned nodes to the worklist.
1313  */
1314 static INLINE void place_early(pdeq* worklist) {
1315   assert(worklist);
1316   inc_irg_visited(current_ir_graph);
1317
1318   /* this inits the worklist */
1319   place_floats_early(get_irg_end(current_ir_graph), worklist);
1320
1321   /* Work the content of the worklist. */
1322   while (!pdeq_empty (worklist)) {
1323     ir_node *n = pdeq_getl (worklist);
1324     if (irn_not_visited(n)) place_floats_early(n, worklist);
1325   }
1326
1327   set_irg_outs_inconsistent(current_ir_graph);
1328   current_ir_graph->pinned = pinned;
1329 }
1330
1331
1332 /** deepest common dominance ancestor of DCA and CONSUMER of PRODUCER. */
1333 static ir_node *
1334 consumer_dom_dca (ir_node *dca, ir_node *consumer, ir_node *producer)
1335 {
1336   ir_node *block = NULL;
1337
1338   /* Compute the latest block into which we can place a node so that it is
1339      before consumer. */
1340   if (get_irn_op(consumer) == op_Phi) {
1341     /* our consumer is a Phi-node, the effective use is in all those
1342        blocks through which the Phi-node reaches producer */
1343     int i, irn_arity;
1344     ir_node *phi_block = get_nodes_Block(consumer);
1345     irn_arity = get_irn_arity(consumer);
1346     for (i = 0;  i < irn_arity; i++) {
1347       if (get_irn_n(consumer, i) == producer) {
1348         block = get_nodes_Block(get_Block_cfgpred(phi_block, i));
1349       }
1350     }
1351   } else {
1352     assert(is_no_Block(consumer));
1353     block = get_nodes_Block(consumer);
1354   }
1355
1356   /* Compute the deepest common ancestor of block and dca. */
1357   assert(block);
1358   if (!dca) return block;
1359   while (get_Block_dom_depth(block) > get_Block_dom_depth(dca))
1360     block = get_Block_idom(block);
1361   while (get_Block_dom_depth(dca) > get_Block_dom_depth(block))
1362     dca = get_Block_idom(dca);
1363   while (block != dca)
1364     { block = get_Block_idom(block); dca = get_Block_idom(dca); }
1365
1366   return dca;
1367 }
1368
1369 static INLINE int get_irn_loop_depth(ir_node *n) {
1370   return get_loop_depth(get_irn_loop(n));
1371 }
1372
1373 /**
1374  * Move n to a block with less loop depth than it's current block. The
1375  * new block must be dominated by early.
1376  */
1377 static void
1378 move_out_of_loops (ir_node *n, ir_node *early)
1379 {
1380   ir_node *best, *dca;
1381   assert(n && early);
1382
1383
1384   /* Find the region deepest in the dominator tree dominating
1385      dca with the least loop nesting depth, but still dominated
1386      by our early placement. */
1387   dca = get_nodes_Block(n);
1388   best = dca;
1389   while (dca != early) {
1390     dca = get_Block_idom(dca);
1391     if (!dca) break; /* should we put assert(dca)? */
1392     if (get_irn_loop_depth(dca) < get_irn_loop_depth(best)) {
1393       best = dca;
1394     }
1395   }
1396   if (best != get_nodes_Block(n)) {
1397     /* debug output
1398     printf("Moving out of loop: "); DDMN(n);
1399     printf(" Outermost block: "); DDMN(early);
1400     printf(" Best block: "); DDMN(best);
1401     printf(" Innermost block: "); DDMN(get_nodes_Block(n));
1402     */
1403     set_nodes_Block(n, best);
1404   }
1405 }
1406
1407 /**
1408  * Find the latest legal block for N and place N into the
1409  * `optimal' Block between the latest and earliest legal block.
1410  * The `optimal' block is the dominance-deepest block of those
1411  * with the least loop-nesting-depth.  This places N out of as many
1412  * loops as possible and then makes it as control dependant as
1413  * possible.
1414  */
1415 static void
1416 place_floats_late(ir_node *n, pdeq *worklist)
1417 {
1418   int i;
1419   ir_node *early;
1420
1421   assert (irn_not_visited(n)); /* no multiple placement */
1422
1423   /* no need to place block nodes, control nodes are already placed. */
1424   if ((get_irn_op(n) != op_Block) &&
1425       (!is_cfop(n)) &&
1426       (get_irn_mode(n) != mode_X)) {
1427     /* Remember the early placement of this block to move it
1428        out of loop no further than the early placement. */
1429     early = get_nodes_Block(n);
1430     /* Assure that our users are all placed, except the Phi-nodes.
1431        --- Each data flow cycle contains at least one Phi-node.  We
1432        have to break the `user has to be placed before the
1433        producer' dependence cycle and the Phi-nodes are the
1434        place to do so, because we need to base our placement on the
1435        final region of our users, which is OK with Phi-nodes, as they
1436        are pinned, and they never have to be placed after a
1437        producer of one of their inputs in the same block anyway. */
1438     for (i = 0; i < get_irn_n_outs(n); i++) {
1439       ir_node *succ = get_irn_out(n, i);
1440       if (irn_not_visited(succ) && (get_irn_op(succ) != op_Phi))
1441         place_floats_late(succ, worklist);
1442     }
1443
1444     /* We have to determine the final block of this node... except for
1445        constants. */
1446     if ((get_op_pinned(get_irn_op(n)) == floats) &&
1447         (get_irn_op(n) != op_Const) &&
1448         (get_irn_op(n) != op_SymConst)) {
1449       ir_node *dca = NULL;      /* deepest common ancestor in the
1450                                    dominator tree of all nodes'
1451                                    blocks depending on us; our final
1452                                    placement has to dominate DCA. */
1453       for (i = 0; i < get_irn_n_outs(n); i++) {
1454         dca = consumer_dom_dca (dca, get_irn_out(n, i), n);
1455       }
1456       set_nodes_Block(n, dca);
1457
1458       move_out_of_loops (n, early);
1459     }
1460   }
1461
1462   mark_irn_visited(n);
1463
1464   /* Add predecessors of all non-floating nodes on list. (Those of floating
1465      nodes are placeded already and therefore are marked.)  */
1466   for (i = 0; i < get_irn_n_outs(n); i++) {
1467     if (irn_not_visited(get_irn_out(n, i))) {
1468       pdeq_putr (worklist, get_irn_out(n, i));
1469     }
1470   }
1471 }
1472
1473 static INLINE void place_late(pdeq* worklist) {
1474   assert(worklist);
1475   inc_irg_visited(current_ir_graph);
1476
1477   /* This fills the worklist initially. */
1478   place_floats_late(get_irg_start_block(current_ir_graph), worklist);
1479   /* And now empty the worklist again... */
1480   while (!pdeq_empty (worklist)) {
1481     ir_node *n = pdeq_getl (worklist);
1482     if (irn_not_visited(n)) place_floats_late(n, worklist);
1483   }
1484 }
1485
1486 void place_code(ir_graph *irg) {
1487   pdeq* worklist;
1488   ir_graph *rem = current_ir_graph;
1489
1490   current_ir_graph = irg;
1491
1492   if (!(get_opt_optimize() && get_opt_global_cse())) return;
1493
1494   /* Handle graph state */
1495   assert(get_irg_phase_state(irg) != phase_building);
1496   if (get_irg_dom_state(irg) != dom_consistent)
1497     compute_doms(irg);
1498
1499   construct_backedges(irg);
1500
1501   /* Place all floating nodes as early as possible. This guarantees
1502      a legal code placement. */
1503   worklist = new_pdeq();
1504   place_early(worklist);
1505
1506   /* place_early invalidates the outs, place_late needs them. */
1507   compute_outs(irg);
1508   /* Now move the nodes down in the dominator tree. This reduces the
1509      unnecessary executions of the node. */
1510   place_late(worklist);
1511
1512   set_irg_outs_inconsistent(current_ir_graph);
1513   del_pdeq(worklist);
1514   current_ir_graph = rem;
1515 }
1516
1517
1518
1519 /********************************************************************/
1520 /* Control flow optimization.                                       */
1521 /* Removes Bad control flow predecessors and empty blocks.  A block */
1522 /* is empty if it contains only a Jmp node.                         */
1523 /* Blocks can only be removed if they are not needed for the        */
1524 /* semantics of Phi nodes.                                          */
1525 /********************************************************************/
1526
1527 /**
1528  * Removes Tuples from Block control flow predecessors.
1529  * Optimizes blocks with equivalent_node().
1530  * Replaces n by Bad if n is unreachable control flow.
1531  */
1532 static void merge_blocks(ir_node *n, void *env) {
1533   int i;
1534   set_irn_link(n, NULL);
1535
1536   if (get_irn_op(n) == op_Block) {
1537     /* Remove Tuples */
1538     for (i = 0; i < get_Block_n_cfgpreds(n); i++)
1539       /* GL @@@ : is this possible? if (get_opt_normalize()) -- added, all tests go through.
1540          A different order of optimizations might cause problems. */
1541       if (get_opt_normalize())
1542         set_Block_cfgpred(n, i, skip_Tuple(get_Block_cfgpred(n, i)));
1543   } else if (get_opt_optimize() && (get_irn_mode(n) == mode_X)) {
1544     /* We will soon visit a block.  Optimize it before visiting! */
1545     ir_node *b = get_nodes_Block(n);
1546     ir_node *new_node = equivalent_node(b);
1547     while (irn_not_visited(b) && (!is_Bad(new_node)) && (new_node != b)) {
1548       /* We would have to run gigo if new is bad, so we
1549          promote it directly below. */
1550       assert(((b == new_node) ||
1551               get_opt_control_flow_straightening() ||
1552               get_opt_control_flow_weak_simplification()) &&
1553              ("strange flag setting"));
1554       exchange (b, new_node);
1555       b = new_node;
1556       new_node = equivalent_node(b);
1557     }
1558     /* GL @@@ get_opt_normalize hinzugefuegt, 5.5.2003 */
1559     if (is_Bad(new_node) && get_opt_normalize()) exchange(n, new_Bad());
1560   }
1561 }
1562
1563 /**
1564  * Collects all Phi nodes in link list of Block.
1565  * Marks all blocks "block_visited" if they contain a node other
1566  * than Jmp.
1567  */
1568 static void collect_nodes(ir_node *n, void *env) {
1569   if (is_no_Block(n)) {
1570     ir_node *b = get_nodes_Block(n);
1571
1572     if ((get_irn_op(n) == op_Phi)) {
1573       /* Collect Phi nodes to compact ins along with block's ins. */
1574       set_irn_link(n, get_irn_link(b));
1575       set_irn_link(b, n);
1576     } else if (get_irn_op(n) != op_Jmp) {  /* Check for non empty block. */
1577       mark_Block_block_visited(b);
1578     }
1579   }
1580 }
1581
1582 /** Returns true if pred is predecessor of block. */
1583 static int is_pred_of(ir_node *pred, ir_node *b) {
1584   int i;
1585   for (i = 0; i < get_Block_n_cfgpreds(b); i++) {
1586     ir_node *b_pred = get_nodes_Block(get_Block_cfgpred(b, i));
1587     if (b_pred == pred) return 1;
1588   }
1589   return 0;
1590 }
1591
1592 static int test_whether_dispensable(ir_node *b, int pos) {
1593   int i, j, n_preds = 1;
1594   int dispensable = 1;
1595   ir_node *cfop = get_Block_cfgpred(b, pos);
1596   ir_node *pred = get_nodes_Block(cfop);
1597
1598   if (get_Block_block_visited(pred) + 1
1599       < get_irg_block_visited(current_ir_graph)) {
1600     if (!get_opt_optimize() || !get_opt_control_flow_strong_simplification()) {
1601       /* Mark block so that is will not be removed. */
1602       set_Block_block_visited(pred, get_irg_block_visited(current_ir_graph)-1);
1603       return 1;
1604     }
1605     /* Seems to be empty. */
1606     if (!get_irn_link(b)) {
1607       /* There are no Phi nodes ==> dispensable. */
1608       n_preds = get_Block_n_cfgpreds(pred);
1609     } else {
1610       /* b's pred blocks and pred's pred blocks must be pairwise disjunct.
1611          Work preds < pos as if they were already removed. */
1612       for (i = 0; i < pos; i++) {
1613         ir_node *b_pred = get_nodes_Block(get_Block_cfgpred(b, i));
1614         if (get_Block_block_visited(b_pred) + 1
1615             < get_irg_block_visited(current_ir_graph)) {
1616           for (j = 0; j < get_Block_n_cfgpreds(b_pred); j++) {
1617             ir_node *b_pred_pred = get_nodes_Block(get_Block_cfgpred(b_pred, j));
1618             if (is_pred_of(b_pred_pred, pred)) dispensable = 0;
1619           }
1620         } else {
1621           if (is_pred_of(b_pred, pred)) dispensable = 0;
1622         }
1623       }
1624       for (i = pos +1; i < get_Block_n_cfgpreds(b); i++) {
1625         ir_node *b_pred = get_nodes_Block(get_Block_cfgpred(b, i));
1626         if (is_pred_of(b_pred, pred)) dispensable = 0;
1627       }
1628       if (!dispensable) {
1629         set_Block_block_visited(pred, get_irg_block_visited(current_ir_graph)-1);
1630         n_preds = 1;
1631       } else {
1632         n_preds = get_Block_n_cfgpreds(pred);
1633       }
1634     }
1635   }
1636
1637   return n_preds;
1638 }
1639
1640 static void optimize_blocks(ir_node *b, void *env) {
1641   int i, j, k, max_preds, n_preds;
1642   ir_node *pred, *phi;
1643   ir_node **in;
1644
1645   /* Count the number of predecessor if this block is merged with pred blocks
1646      that are empty. */
1647   max_preds = 0;
1648   for (i = 0; i < get_Block_n_cfgpreds(b); i++) {
1649     max_preds += test_whether_dispensable(b, i);
1650   }
1651   in = (ir_node **) malloc(max_preds * sizeof(ir_node *));
1652
1653 /*-
1654   printf(" working on "); DDMN(b);
1655   for (i = 0; i < get_Block_n_cfgpreds(b); i++) {
1656     pred = get_nodes_Block(get_Block_cfgpred(b, i));
1657     if (is_Bad(get_Block_cfgpred(b, i))) {
1658       printf("  removing Bad %i\n ", i);
1659     } else if (get_Block_block_visited(pred) +1
1660                < get_irg_block_visited(current_ir_graph)) {
1661       printf("  removing pred %i ", i); DDMN(pred);
1662     } else { printf("  Nothing to do for "); DDMN(pred); }
1663   }
1664   * end Debug output -*/
1665
1666   /*- Fix the Phi nodes -*/
1667   phi = get_irn_link(b);
1668   while (phi) {
1669     assert(get_irn_op(phi) == op_Phi);
1670     /* Find the new predecessors for the Phi */
1671     n_preds = 0;
1672     for (i = 0; i < get_Block_n_cfgpreds(b); i++) {
1673       pred = get_nodes_Block(get_Block_cfgpred(b, i));
1674       if (is_Bad(get_Block_cfgpred(b, i))) {
1675         /* Do nothing */
1676       } else if (get_Block_block_visited(pred) +1
1677                  < get_irg_block_visited(current_ir_graph)) {
1678         /* It's an empty block and not yet visited. */
1679         ir_node *phi_pred = get_Phi_pred(phi, i);
1680         for (j = 0; j < get_Block_n_cfgpreds(pred); j++) {
1681           if (get_nodes_Block(phi_pred) == pred) {
1682             assert(get_irn_op(phi_pred) == op_Phi);  /* Block is empty!! */
1683             in[n_preds] = get_Phi_pred(phi_pred, j);
1684           } else {
1685             in[n_preds] = phi_pred;
1686           }
1687           n_preds++;
1688         }
1689         /* The Phi_pred node is replaced now if it is a Phi.
1690            In Schleifen kann offenbar der entfernte Phi Knoten legal verwendet werden.
1691            Daher muss der Phiknoten durch den neuen ersetzt werden.
1692            Weiter muss der alte Phiknoten entfernt werden (durch ersetzen oder
1693            durch einen Bad) damit er aus den keep_alive verschwinden kann.
1694            Man sollte also, falls keine Schleife vorliegt, exchange mit new_Bad
1695            aufrufen.  */
1696         if (get_nodes_Block(phi_pred) == pred) {
1697           /* remove the Phi as it might be kept alive. Further there
1698              might be other users. */
1699           exchange(phi_pred, phi);  /* geht, ist aber doch semantisch falsch! Warum?? */
1700         }
1701       } else {
1702         in[n_preds] = get_Phi_pred(phi, i);
1703         n_preds ++;
1704       }
1705     }
1706     /* Fix the node */
1707     set_irn_in(phi, n_preds, in);
1708
1709     phi = get_irn_link(phi);
1710   }
1711
1712 /*-
1713       This happens only if merge between loop backedge and single loop entry. -*/
1714   for (k = 0; k < get_Block_n_cfgpreds(b); k++) {
1715     pred = get_nodes_Block(get_Block_cfgpred(b, k));
1716     if (get_Block_block_visited(pred) +1
1717         < get_irg_block_visited(current_ir_graph)) {
1718       phi = get_irn_link(pred);
1719       while (phi) {
1720         if (get_irn_op(phi) == op_Phi) {
1721           set_nodes_Block(phi, b);
1722
1723           n_preds = 0;
1724           for (i = 0; i < k; i++) {
1725             pred = get_nodes_Block(get_Block_cfgpred(b, i));
1726             if (is_Bad(get_Block_cfgpred(b, i))) {
1727               /* Do nothing */
1728             } else if (get_Block_block_visited(pred) +1
1729                        < get_irg_block_visited(current_ir_graph)) {
1730               /* It's an empty block and not yet visited. */
1731               for (j = 0; j < get_Block_n_cfgpreds(pred); j++) {
1732                 /* @@@ Hier brauche ich Schleifeninformation!!! Kontrollflusskante
1733                    muss Rueckwaertskante sein! (An allen vier in[n_preds] = phi
1734                    Anweisungen.) Trotzdem tuts bisher!! */
1735                 in[n_preds] = phi;
1736                 n_preds++;
1737               }
1738             } else {
1739               in[n_preds] = phi;
1740               n_preds++;
1741             }
1742           }
1743           for (i = 0; i < get_Phi_n_preds(phi); i++) {
1744             in[n_preds] = get_Phi_pred(phi, i);
1745             n_preds++;
1746           }
1747           for (i = k+1; i < get_Block_n_cfgpreds(b); i++) {
1748             pred = get_nodes_Block(get_Block_cfgpred(b, i));
1749             if (is_Bad(get_Block_cfgpred(b, i))) {
1750               /* Do nothing */
1751             } else if (get_Block_block_visited(pred) +1
1752                        < get_irg_block_visited(current_ir_graph)) {
1753               /* It's an empty block and not yet visited. */
1754               for (j = 0; j < get_Block_n_cfgpreds(pred); j++) {
1755                 in[n_preds] = phi;
1756                 n_preds++;
1757               }
1758             } else {
1759               in[n_preds] = phi;
1760               n_preds++;
1761             }
1762           }
1763           set_irn_in(phi, n_preds, in);
1764         }
1765         phi = get_irn_link(phi);
1766       }
1767     }
1768   }
1769
1770   /*- Fix the block -*/
1771   n_preds = 0;
1772   for (i = 0; i < get_Block_n_cfgpreds(b); i++) {
1773     pred = get_nodes_Block(get_Block_cfgpred(b, i));
1774     if (is_Bad(get_Block_cfgpred(b, i))) {
1775       /* Do nothing */
1776     } else if (get_Block_block_visited(pred) +1
1777                < get_irg_block_visited(current_ir_graph)) {
1778       /* It's an empty block and not yet visited. */
1779       assert(get_Block_n_cfgpreds(b) > 1);
1780                         /* Else it should be optimized by equivalent_node. */
1781       for (j = 0; j < get_Block_n_cfgpreds(pred); j++) {
1782         in[n_preds] = get_Block_cfgpred(pred, j);
1783         n_preds++;
1784       }
1785       /* Remove block as it might be kept alive. */
1786       exchange(pred, b/*new_Bad()*/);
1787     } else {
1788       in[n_preds] = get_Block_cfgpred(b, i);
1789       n_preds ++;
1790     }
1791   }
1792   set_irn_in(b, n_preds, in);
1793   free(in);
1794 }
1795
1796 void optimize_cf(ir_graph *irg) {
1797   int i;
1798   ir_node **in;
1799   ir_node *end = get_irg_end(irg);
1800   ir_graph *rem = current_ir_graph;
1801   current_ir_graph = irg;
1802
1803   /* Handle graph state */
1804   assert(get_irg_phase_state(irg) != phase_building);
1805   if (get_irg_outs_state(current_ir_graph) == outs_consistent)
1806     set_irg_outs_inconsistent(current_ir_graph);
1807   if (get_irg_dom_state(current_ir_graph) == dom_consistent)
1808     set_irg_dom_inconsistent(current_ir_graph);
1809
1810   /* Use block visited flag to mark non-empty blocks. */
1811   inc_irg_block_visited(irg);
1812   irg_walk(end, merge_blocks, collect_nodes, NULL);
1813
1814   /* Optimize the standard code. */
1815   irg_block_walk(get_irg_end_block(irg), optimize_blocks, NULL, NULL);
1816
1817   /* Walk all keep alives, optimize them if block, add to new in-array
1818      for end if useful. */
1819   in = NEW_ARR_F (ir_node *, 1);
1820   in[0] = get_nodes_Block(end);
1821   inc_irg_visited(current_ir_graph);
1822   for(i = 0; i < get_End_n_keepalives(end); i++) {
1823     ir_node *ka = get_End_keepalive(end, i);
1824     if (irn_not_visited(ka)) {
1825       if ((get_irn_op(ka) == op_Block) && Block_not_block_visited(ka)) {
1826         set_irg_block_visited(current_ir_graph,  /* Don't walk all the way to Start. */
1827                               get_irg_block_visited(current_ir_graph)-1);
1828         irg_block_walk(ka, optimize_blocks, NULL, NULL);
1829         mark_irn_visited(ka);
1830         ARR_APP1 (ir_node *, in, ka);
1831       } else if (get_irn_op(ka) == op_Phi) {
1832         mark_irn_visited(ka);
1833         ARR_APP1 (ir_node *, in, ka);
1834       }
1835     }
1836   }
1837   /* DEL_ARR_F(end->in);   GL @@@ tut nicht ! */
1838   end->in = in;
1839
1840   current_ir_graph = rem;
1841 }
1842
1843
1844 /**
1845  * Called by walker of remove_critical_cf_edges.
1846  *
1847  * Place an empty block to an edge between a blocks of multiple
1848  * predecessors and a block of multiple successors.
1849  *
1850  * @param n IR node
1851  * @param env Environment of walker. This field is unused and has
1852  *            the value NULL.
1853  */
1854 static void walk_critical_cf_edges(ir_node *n, void *env) {
1855   int arity, i;
1856   ir_node *pre, *block, **in, *jmp;
1857
1858   /* Block has multiple predecessors */
1859   if ((op_Block == get_irn_op(n)) &&
1860       (get_irn_arity(n) > 1)) {
1861     arity = get_irn_arity(n);
1862
1863     if (n == get_irg_end_block(current_ir_graph))
1864       return;  // No use to add a block here.
1865
1866     for (i=0; i<arity; i++) {
1867       pre = get_irn_n(n, i);
1868       /* Predecessor has multiple successors. Insert new flow edge */
1869       if ((NULL != pre) &&
1870           (op_Proj == get_irn_op(pre)) &&
1871           op_Raise != get_irn_op(skip_Proj(pre))) {
1872
1873         /* set predecessor array for new block */
1874         in = NEW_ARR_D (ir_node *, current_ir_graph->obst, 1);
1875         /* set predecessor of new block */
1876         in[0] = pre;
1877         block = new_Block(1, in);
1878         /* insert new jmp node to new block */
1879         switch_block(block);
1880         jmp = new_Jmp();
1881         switch_block(n);
1882         /* set successor of new block */
1883         set_irn_n(n, i, jmp);
1884
1885       } /* predecessor has multiple successors */
1886     } /* for all predecessors */
1887   } /* n is a block */
1888 }
1889
1890 void remove_critical_cf_edges(ir_graph *irg) {
1891   if (get_opt_critical_edges())
1892     irg_walk_graph(irg, NULL, walk_critical_cf_edges, NULL);
1893 }