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