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