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