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