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