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