6b13921f474106a3320b3bcd0c97065169d6f23e
[libfirm] / ir / ir / irgopt.c
1 /*
2  * Project:     libFIRM
3  * File name:   ir/ir/irgopt.c
4  * Purpose:     Optimizations for a whole ir graph, i.e., a procedure.
5  * Author:      Christian Schaefer, Goetz Lindenmaier
6  * Modified by: Sebastian Felis
7  * Created:
8  * CVS-ID:      $Id$
9  * Copyright:   (c) 1998-2003 Universität Karlsruhe
10  * Licence:     This file protected by GPL -  GNU GENERAL PUBLIC LICENSE.
11  */
12
13
14 #ifdef HAVE_CONFIG_H
15 # include <config.h>
16 #endif
17
18 # include <assert.h>
19 # include <stdbool.h>
20
21 # include "irprog.h"
22 # include "irgopt.h"
23 # include "irnode_t.h"
24 # include "irgraph_t.h"
25 # include "iropt_t.h"
26 # include "irgwalk.h"
27 # include "ircons.h"
28 # include "irgmod.h"
29 # include "array.h"
30 # include "pset.h"
31 # include "eset.h"
32 # include "pdeq.h"       /* Fuer code placement */
33 # include "irouts.h"
34 # include "irloop.h"
35 # include "irbackedge_t.h"
36 # include "irflag_t.h"
37 # include "firmstat.h"
38
39 /* Defined in iropt.c */
40 pset *new_identities (void);
41 void  del_identities (pset *value_table);
42 void  add_identities   (pset *value_table, ir_node *node);
43
44 /*------------------------------------------------------------------*/
45 /* apply optimizations of iropt to all nodes.                       */
46 /*------------------------------------------------------------------*/
47
48 static void init_link (ir_node *n, void *env) {
49   set_irn_link(n, NULL);
50 }
51
52 #if 0   /* Old version. Avoids Ids.
53        This is not necessary:  we do a postwalk, and get_irn_n
54        removes ids anyways.  So it's much cheaper to call the
55        optimization less often and use the exchange() algorithm. */
56 static void
57 optimize_in_place_wrapper (ir_node *n, void *env) {
58   int i, irn_arity;
59   ir_node *optimized, *old;
60
61   irn_arity = get_irn_arity(n);
62   for (i = 0; i < irn_arity; i++) {
63     /* get_irn_n skips Id nodes, so comparison old != optimized does not
64        show all optimizations. Therefore always set new predecessor. */
65     old = get_irn_intra_n(n, i);
66     optimized = optimize_in_place_2(old);
67     set_irn_n(n, i, optimized);
68   }
69
70   if (get_irn_op(n) == op_Block) {
71     optimized = optimize_in_place_2(n);
72     if (optimized != n) exchange (n, optimized);
73   }
74 }
75 #else
76 static void
77 optimize_in_place_wrapper (ir_node *n, void *env) {
78   ir_node *optimized = optimize_in_place_2(n);
79   if (optimized != n) exchange (n, optimized);
80 }
81 #endif
82
83
84
85 void
86 local_optimize_graph (ir_graph *irg) {
87   ir_graph *rem = current_ir_graph;
88   current_ir_graph = irg;
89
90   /* Handle graph state */
91   assert(get_irg_phase_state(irg) != phase_building);
92   if (get_opt_global_cse())
93     set_irg_pinned(current_ir_graph, floats);
94   if (get_irg_outs_state(current_ir_graph) == outs_consistent)
95     set_irg_outs_inconsistent(current_ir_graph);
96   if (get_irg_dom_state(current_ir_graph) == dom_consistent)
97     set_irg_dom_inconsistent(current_ir_graph);
98   set_irg_loopinfo_inconsistent(current_ir_graph);
99
100
101   /* Clean the value_table in irg for the cse. */
102   del_identities(irg->value_table);
103   irg->value_table = new_identities();
104
105   /* walk over the graph */
106   irg_walk(irg->end, init_link, optimize_in_place_wrapper, NULL);
107
108   current_ir_graph = rem;
109 }
110
111 /*------------------------------------------------------------------*/
112 /* Routines for dead node elimination / copying garbage collection  */
113 /* of the obstack.                                                  */
114 /*------------------------------------------------------------------*/
115
116 /**
117  * Remember the new node in the old node by using a field all nodes have.
118  */
119 static INLINE void
120 set_new_node (ir_node *old, ir_node *new)
121 {
122   old->link = new;
123 }
124
125 /**
126  * Get this new node, before the old node is forgotton.
127  */
128 static INLINE ir_node *
129 get_new_node (ir_node * n)
130 {
131   return n->link;
132 }
133
134 /**
135  * We use the block_visited flag to mark that we have computed the
136  * number of useful predecessors for this block.
137  * Further we encode the new arity in this flag in the old blocks.
138  * Remembering the arity is useful, as it saves a lot of pointer
139  * accesses.  This function is called for all Phi and Block nodes
140  * in a Block.
141  */
142 static INLINE int
143 compute_new_arity(ir_node *b) {
144   int i, res, irn_arity;
145   int irg_v, block_v;
146
147   irg_v = get_irg_block_visited(current_ir_graph);
148   block_v = get_Block_block_visited(b);
149   if (block_v >= irg_v) {
150     /* we computed the number of preds for this block and saved it in the
151        block_v flag */
152     return block_v - irg_v;
153   } else {
154     /* compute the number of good predecessors */
155     res = irn_arity = get_irn_arity(b);
156     for (i = 0; i < irn_arity; i++)
157       if (get_irn_opcode(get_irn_n(b, i)) == iro_Bad) res--;
158     /* save it in the flag. */
159     set_Block_block_visited(b, irg_v + res);
160     return res;
161   }
162 }
163
164 /* TODO: add an ir_op operation */
165 static INLINE void new_backedge_info(ir_node *n) {
166   switch(get_irn_opcode(n)) {
167   case iro_Block:
168     n->attr.block.cg_backedge = NULL;
169     n->attr.block.backedge = new_backedge_arr(current_ir_graph->obst, get_irn_arity(n));
170     break;
171   case iro_Phi:
172     n->attr.phi_backedge = new_backedge_arr(current_ir_graph->obst, get_irn_arity(n));
173     break;
174   case iro_Filter:
175     n->attr.filter.backedge = new_backedge_arr(current_ir_graph->obst, get_irn_arity(n));
176     break;
177   default: ;
178   }
179 }
180
181 /**
182  * Copies the node to the new obstack. The Ins of the new node point to
183  * the predecessors on the old obstack.  For block/phi nodes not all
184  * predecessors might be copied.  n->link points to the new node.
185  * For Phi and Block nodes the function allocates in-arrays with an arity
186  * only for useful predecessors.  The arity is determined by counting
187  * the non-bad predecessors of the block.
188  */
189 static void
190 copy_node (ir_node *n, void *env) {
191   ir_node *nn, *block;
192   int new_arity;
193   opcode op = get_irn_opcode(n);
194   /* The end node looses it's flexible in array.  This doesn't matter,
195      as dead node elimination builds End by hand, inlineing doesn't use
196      the End node. */
197   /* assert(n->op == op_End ||  ((_ARR_DESCR(n->in))->cookie != ARR_F_MAGIC)); */
198
199   if (op == iro_Bad) {
200     /* node copied already */
201     return;
202   } else if (op == iro_Block) {
203     block = NULL;
204     new_arity = compute_new_arity(n);
205     n->attr.block.graph_arr = NULL;
206   } else {
207     block = get_nodes_Block(n);
208     if (get_irn_opcode(n) == iro_Phi) {
209       new_arity = compute_new_arity(block);
210     } else {
211       new_arity = get_irn_arity(n);
212     }
213   }
214   nn = new_ir_node(get_irn_dbg_info(n),
215            current_ir_graph,
216            block,
217            get_irn_op(n),
218            get_irn_mode(n),
219            new_arity,
220            get_irn_in(n));
221   /* Copy the attributes.  These might point to additional data.  If this
222      was allocated on the old obstack the pointers now are dangling.  This
223      frees e.g. the memory of the graph_arr allocated in new_immBlock. */
224   copy_attrs(n, nn);
225   new_backedge_info(nn);
226   set_new_node(n, nn);
227
228   /*  printf("\n old node: "); DDMSG2(n);
229       printf(" new node: "); DDMSG2(nn); */
230
231 }
232
233 /**
234  * Copies new predecessors of old node to new node remembered in link.
235  * Spare the Bad predecessors of Phi and Block nodes.
236  */
237 static void
238 copy_preds (ir_node *n, void *env) {
239   ir_node *nn, *block;
240   int i, j, irn_arity;
241
242   nn = get_new_node(n);
243
244   /* printf("\n old node: "); DDMSG2(n);
245      printf(" new node: "); DDMSG2(nn);
246      printf(" arities: old: %d, new: %d\n", get_irn_arity(n), get_irn_arity(nn)); */
247
248   if (get_irn_opcode(n) == iro_Block) {
249     /* Don't copy Bad nodes. */
250     j = 0;
251     irn_arity = get_irn_arity(n);
252     for (i = 0; i < irn_arity; i++)
253       if (get_irn_opcode(get_irn_n(n, i)) != iro_Bad) {
254     set_irn_n (nn, j, get_new_node(get_irn_n(n, i)));
255     /*if (is_backedge(n, i)) set_backedge(nn, j);*/
256     j++;
257       }
258     /* repair the block visited flag from above misuse. Repair it in both
259        graphs so that the old one can still be used. */
260     set_Block_block_visited(nn, 0);
261     set_Block_block_visited(n, 0);
262     /* Local optimization could not merge two subsequent blocks if
263        in array contained Bads.  Now it's possible.
264        We don't call optimize_in_place as it requires
265        that the fields in ir_graph are set properly. */
266     if ((get_opt_control_flow_straightening()) &&
267     (get_Block_n_cfgpreds(nn) == 1) &&
268     (get_irn_op(get_Block_cfgpred(nn, 0)) == op_Jmp)) {
269       ir_node *old = get_nodes_Block(get_Block_cfgpred(nn, 0));
270       if (nn == old) {
271     /* Jmp jumps into the block it is in -- deal self cycle. */
272     assert(is_Bad(get_new_node(get_irg_bad(current_ir_graph))));
273     exchange(nn, get_new_node(get_irg_bad(current_ir_graph)));
274       } else {
275     exchange(nn, old);
276       }
277     }
278   } else if (get_irn_opcode(n) == iro_Phi) {
279     /* Don't copy node if corresponding predecessor in block is Bad.
280        The Block itself should not be Bad. */
281     block = get_nodes_Block(n);
282     set_irn_n (nn, -1, get_new_node(block));
283     j = 0;
284     irn_arity = get_irn_arity(n);
285     for (i = 0; i < irn_arity; i++)
286       if (get_irn_opcode(get_irn_n(block, i)) != iro_Bad) {
287     set_irn_n (nn, j, get_new_node(get_irn_n(n, i)));
288     /*if (is_backedge(n, i)) set_backedge(nn, j);*/
289     j++;
290       }
291     /* If the pre walker reached this Phi after the post walker visited the
292        block block_visited is > 0. */
293     set_Block_block_visited(get_nodes_Block(n), 0);
294     /* Compacting the Phi's ins might generate Phis with only one
295        predecessor. */
296     if (get_irn_arity(n) == 1)
297       exchange(n, get_irn_n(n, 0));
298   } else {
299     irn_arity = get_irn_arity(n);
300     for (i = -1; i < irn_arity; i++)
301       set_irn_n (nn, i, get_new_node(get_irn_n(n, i)));
302   }
303   /* Now the new node is complete.  We can add it to the hash table for cse.
304      @@@ inlinening aborts if we identify End. Why? */
305   if(get_irn_op(nn) != op_End)
306     add_identities (current_ir_graph->value_table, nn);
307 }
308
309 /**
310  * Copies the graph recursively, compacts the keepalive of the end node.
311  */
312 static void
313 copy_graph (void) {
314   ir_node *oe, *ne, *ob, *nb; /* old end, new end, old bad, new bad */
315   ir_node *ka;      /* keep alive */
316   int i, irn_arity;
317
318   oe = get_irg_end(current_ir_graph);
319   /* copy the end node by hand, allocate dynamic in array! */
320   ne = new_ir_node(get_irn_dbg_info(oe),
321            current_ir_graph,
322            NULL,
323            op_End,
324            mode_X,
325            -1,
326            NULL);
327   /* Copy the attributes.  Well, there might be some in the future... */
328   copy_attrs(oe, ne);
329   set_new_node(oe, ne);
330
331   ob = get_irg_bad(current_ir_graph);
332   nb =  new_ir_node(get_irn_dbg_info(ob),
333            current_ir_graph,
334            NULL,
335            op_Bad,
336            mode_T,
337            0,
338            NULL);
339   set_new_node(ob, nb);
340
341   /* copy the live nodes */
342   irg_walk(get_nodes_Block(oe), copy_node, copy_preds, NULL);
343   /* copy_preds for the end node ... */
344   set_nodes_Block(ne, get_new_node(get_nodes_Block(oe)));
345   set_nodes_Block(nb, get_new_node(get_nodes_Block(ob)));
346
347   /*- ... and now the keep alives. -*/
348   /* First pick the not marked block nodes and walk them.  We must pick these
349      first as else we will oversee blocks reachable from Phis. */
350   irn_arity = get_irn_arity(oe);
351   for (i = 0; i < irn_arity; i++) {
352     ka = get_irn_intra_n(oe, i);
353     if ((get_irn_op(ka) == op_Block) &&
354     (get_irn_visited(ka) < get_irg_visited(current_ir_graph))) {
355       /* We must keep the block alive and copy everything reachable */
356       set_irg_visited(current_ir_graph, get_irg_visited(current_ir_graph)-1);
357       irg_walk(ka, copy_node, copy_preds, NULL);
358       add_End_keepalive(ne, get_new_node(ka));
359     }
360   }
361
362   /* Now pick the Phis.  Here we will keep all! */
363   irn_arity = get_irn_arity(oe);
364   for (i = 0; i < irn_arity; i++) {
365     ka = get_irn_intra_n(oe, i);
366     if ((get_irn_op(ka) == op_Phi)) {
367       if (get_irn_visited(ka) < get_irg_visited(current_ir_graph)) {
368     /* We didn't copy the Phi yet.  */
369     set_irg_visited(current_ir_graph, get_irg_visited(current_ir_graph)-1);
370     irg_walk(ka, copy_node, copy_preds, NULL);
371       }
372       add_End_keepalive(ne, get_new_node(ka));
373     }
374   }
375 }
376
377 /**
378  * Copies the graph reachable from current_ir_graph->end to the obstack
379  * in current_ir_graph and fixes the environment.
380  * Then fixes the fields in current_ir_graph containing nodes of the
381  * graph.
382  */
383 static void
384 copy_graph_env (void) {
385   ir_node *old_end;
386   /* Not all nodes remembered in current_ir_graph might be reachable
387      from the end node.  Assure their link is set to NULL, so that
388      we can test whether new nodes have been computed. */
389   set_irn_link(get_irg_frame  (current_ir_graph), NULL);
390   set_irn_link(get_irg_globals(current_ir_graph), NULL);
391   set_irn_link(get_irg_args   (current_ir_graph), NULL);
392
393   /* we use the block walk flag for removing Bads from Blocks ins. */
394   inc_irg_block_visited(current_ir_graph);
395
396   /* copy the graph */
397   copy_graph();
398
399   /* fix the fields in current_ir_graph */
400   old_end = get_irg_end(current_ir_graph);
401   set_irg_end        (current_ir_graph, get_new_node(old_end));
402   set_irg_end_except (current_ir_graph, get_irg_end(current_ir_graph));
403   set_irg_end_reg    (current_ir_graph, get_irg_end(current_ir_graph));
404   free_End(old_end);
405   set_irg_end_block  (current_ir_graph, get_new_node(get_irg_end_block(current_ir_graph)));
406   if (get_irn_link(get_irg_frame(current_ir_graph)) == NULL) {
407     copy_node (get_irg_frame(current_ir_graph), NULL);
408     copy_preds(get_irg_frame(current_ir_graph), NULL);
409   }
410   if (get_irn_link(get_irg_globals(current_ir_graph)) == NULL) {
411     copy_node (get_irg_globals(current_ir_graph), NULL);
412     copy_preds(get_irg_globals(current_ir_graph), NULL);
413   }
414   if (get_irn_link(get_irg_args(current_ir_graph)) == NULL) {
415     copy_node (get_irg_args(current_ir_graph), NULL);
416     copy_preds(get_irg_args(current_ir_graph), NULL);
417   }
418   set_irg_start  (current_ir_graph, get_new_node(get_irg_start(current_ir_graph)));
419
420   set_irg_start_block(current_ir_graph,
421               get_new_node(get_irg_start_block(current_ir_graph)));
422   set_irg_frame  (current_ir_graph, get_new_node(get_irg_frame(current_ir_graph)));
423   set_irg_globals(current_ir_graph, get_new_node(get_irg_globals(current_ir_graph)));
424   set_irg_args   (current_ir_graph, get_new_node(get_irg_args(current_ir_graph)));
425   if (get_irn_link(get_irg_bad(current_ir_graph)) == NULL) {
426     copy_node(get_irg_bad(current_ir_graph), NULL);
427     copy_preds(get_irg_bad(current_ir_graph), NULL);
428   }
429   set_irg_bad(current_ir_graph, get_new_node(get_irg_bad(current_ir_graph)));
430 }
431
432 /**
433  * Copies all reachable nodes to a new obstack.  Removes bad inputs
434  * from block nodes and the corresponding inputs from Phi nodes.
435  * Merges single exit blocks with single entry blocks and removes
436  * 1-input Phis.
437  * Adds all new nodes to a new hash table for cse.  Does not
438  * perform cse, so the hash table might contain common subexpressions.
439  */
440 void
441 dead_node_elimination(ir_graph *irg) {
442   ir_graph *rem;
443   int rem_ipview = interprocedural_view;
444   struct obstack *graveyard_obst = NULL;
445   struct obstack *rebirth_obst   = NULL;
446
447   stat_dead_node_elim_start(irg);
448
449   /* Remember external state of current_ir_graph. */
450   rem = current_ir_graph;
451   current_ir_graph = irg;
452   interprocedural_view = 0;
453
454   /* Handle graph state */
455   assert(get_irg_phase_state(current_ir_graph) != phase_building);
456   assert(get_irg_callee_info_state(current_ir_graph) == irg_callee_info_none);
457   free_outs(current_ir_graph);
458
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   assert(get_irg_callee_info_state(current_ir_graph) == irg_callee_info_none);
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     assert(get_irg_callee_info_state(current_ir_graph) == irg_callee_info_none);
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 }