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