used ircons_t.h now
[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_t.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       if (n_ret > 0)
891         phi = new_Phi(n_ret, cf_pred, get_irn_mode(cf_pred[0]));
892       else
893         phi = new_Bad();
894       res_pred[j] = phi;
895       /* Conserve Phi-list for further inlinings -- but might be optimized */
896       if (get_nodes_Block(phi) == post_bl) {
897         set_irn_link(phi, get_irn_link(post_bl));
898         set_irn_link(post_bl, phi);
899       }
900     }
901     set_Tuple_pred(call, pn_Call_T_result, new_Tuple(n_res, res_pred));
902   } else {
903     set_Tuple_pred(call, pn_Call_T_result, new_Bad());
904   }
905   /* Finally the exception control flow.
906      We have two (three) possible situations:
907      First if the Call branches to an exception handler: We need to add a Phi node to
908      collect the memory containing the exception objects.  Further we need
909      to add another block to get a correct representation of this Phi.  To
910      this block we add a Jmp that resolves into the X output of the Call
911      when the Call is turned into a tuple.
912      Second the Call branches to End, the exception is not handled.  Just
913      add all inlined exception branches to the End node.
914      Third: there is no Exception edge at all. Handle as case two. */
915   if (exc_handling == 0) {
916     n_exc = 0;
917     for (i = 0; i < arity; i++) {
918       ir_node *ret;
919       ret = get_irn_n(end_bl, i);
920       if (is_fragile_op(skip_Proj(ret)) || (get_irn_op(skip_Proj(ret)) == op_Raise)) {
921         cf_pred[n_exc] = ret;
922         n_exc++;
923       }
924     }
925     if (n_exc > 0) {
926       new_Block(n_exc, cf_pred);      /* watch it: current_block is changed! */
927       set_Tuple_pred(call, pn_Call_X_except, new_Jmp());
928       /* The Phi for the memories with the exception objects */
929       n_exc = 0;
930       for (i = 0; i < arity; i++) {
931         ir_node *ret;
932         ret = skip_Proj(get_irn_n(end_bl, i));
933         if (get_irn_op(ret) == op_Call) {
934           cf_pred[n_exc] = new_r_Proj(current_ir_graph, get_nodes_Block(ret), ret, mode_M, 3);
935           n_exc++;
936         } else if (is_fragile_op(ret)) {
937           /* We rely that all cfops have the memory output at the same position. */
938           cf_pred[n_exc] = new_r_Proj(current_ir_graph, get_nodes_Block(ret), ret, mode_M, 0);
939           n_exc++;
940         } else if (get_irn_op(ret) == op_Raise) {
941           cf_pred[n_exc] = new_r_Proj(current_ir_graph, get_nodes_Block(ret), ret, mode_M, 1);
942           n_exc++;
943         }
944       }
945       set_Tuple_pred(call, pn_Call_M_except, new_Phi(n_exc, cf_pred, mode_M));
946     } else {
947       set_Tuple_pred(call, pn_Call_X_except, new_Bad());
948       set_Tuple_pred(call, pn_Call_M_except, new_Bad());
949     }
950   } else {
951     ir_node *main_end_bl;
952     int main_end_bl_arity;
953     ir_node **end_preds;
954
955     /* assert(exc_handling == 1 || no exceptions. ) */
956     n_exc = 0;
957     for (i = 0; i < arity; i++) {
958       ir_node *ret = get_irn_n(end_bl, i);
959
960       if (is_fragile_op(skip_Proj(ret)) || (get_irn_op(skip_Proj(ret)) == op_Raise)) {
961         cf_pred[n_exc] = ret;
962         n_exc++;
963       }
964     }
965     main_end_bl = get_irg_end_block(current_ir_graph);
966     main_end_bl_arity = get_irn_arity(main_end_bl);
967     end_preds =  (ir_node **) malloc ((n_exc + main_end_bl_arity) * sizeof (ir_node *));
968
969     for (i = 0; i < main_end_bl_arity; ++i)
970       end_preds[i] = get_irn_n(main_end_bl, i);
971     for (i = 0; i < n_exc; ++i)
972       end_preds[main_end_bl_arity + i] = cf_pred[i];
973     set_irn_in(main_end_bl, n_exc + main_end_bl_arity, end_preds);
974     set_Tuple_pred(call, pn_Call_X_except, new_Bad());
975     set_Tuple_pred(call, pn_Call_M_except, new_Bad());
976     free(end_preds);
977   }
978   free(res_pred);
979   free(cf_pred);
980
981 #if 0  /* old. now better, correcter, faster implementation. */
982   if (n_exc > 0) {
983     /* -- If the exception control flow from the inlined Call directly
984        branched to the end block we now have the following control
985        flow predecessor pattern: ProjX -> Tuple -> Jmp.  We must
986        remove the Jmp along with it's empty block and add Jmp's
987        predecessors as predecessors of this end block.  No problem if
988        there is no exception, because then branches Bad to End which
989        is fine. --
990        @@@ can't we know this beforehand: by getting the Proj(1) from
991        the Call link list and checking whether it goes to Proj. */
992     /* find the problematic predecessor of the end block. */
993     end_bl = get_irg_end_block(current_ir_graph);
994     for (i = 0; i < get_Block_n_cfgpreds(end_bl); i++) {
995       cf_op = get_Block_cfgpred(end_bl, i);
996       if (get_irn_op(cf_op) == op_Proj) {
997         cf_op = get_Proj_pred(cf_op);
998         if ((get_irn_op(cf_op) == op_Tuple) && (cf_op == call)) {
999           /*  There are unoptimized tuples from inlineing before when no exc */
1000           assert(get_Proj_proj(get_Block_cfgpred(end_bl, i)) == pn_Call_X_except);
1001           cf_op = get_Tuple_pred(cf_op, pn_Call_X_except);
1002           assert(get_irn_op(cf_op) == op_Jmp);
1003           break;
1004         }
1005       }
1006     }
1007     /* repair */
1008     if (i < get_Block_n_cfgpreds(end_bl)) {
1009       bl = get_nodes_Block(cf_op);
1010       arity = get_Block_n_cfgpreds(end_bl) + get_Block_n_cfgpreds(bl) - 1;
1011       cf_pred = (ir_node **) malloc (arity * sizeof (ir_node *));
1012       for (j = 0; j < i; j++)
1013         cf_pred[j] = get_Block_cfgpred(end_bl, j);
1014       for (j = j; j < i + get_Block_n_cfgpreds(bl); j++)
1015         cf_pred[j] = get_Block_cfgpred(bl, j-i);
1016       for (j = j; j < arity; j++)
1017         cf_pred[j] = get_Block_cfgpred(end_bl, j-get_Block_n_cfgpreds(bl) +1);
1018       set_irn_in(end_bl, arity, cf_pred);
1019       free(cf_pred);
1020       /*  Remove the exception pred from post-call Tuple. */
1021       set_Tuple_pred(call, pn_Call_X_except, new_Bad());
1022     }
1023   }
1024 #endif
1025
1026   /* --  Turn cse back on. -- */
1027   set_optimize(rem_opt);
1028
1029   return 1;
1030 }
1031
1032 /********************************************************************/
1033 /* Apply inlineing to small methods.                                */
1034 /********************************************************************/
1035
1036 /* It makes no sense to inline too many calls in one procedure. Anyways,
1037    I didn't get a version with NEW_ARR_F to run. */
1038 #define MAX_INLINE 1024
1039
1040 /**
1041  * environment for inlining small irgs
1042  */
1043 typedef struct _inline_env_t {
1044   int pos;
1045   ir_node *calls[MAX_INLINE];
1046 } inline_env_t;
1047
1048 /**
1049  * Returns the irg called from a Call node. If the irg is not
1050  * known, NULL is returned.
1051  */
1052 static ir_graph *get_call_called_irg(ir_node *call) {
1053   ir_node *addr;
1054   tarval *tv;
1055   ir_graph *called_irg = NULL;
1056
1057   assert(get_irn_op(call) == op_Call);
1058
1059   addr = get_Call_ptr(call);
1060   if (get_irn_op(addr) == op_Const) {
1061     /* Check whether the constant is the pointer to a compiled entity. */
1062     tv = get_Const_tarval(addr);
1063     if (tarval_to_entity(tv))
1064       called_irg = get_entity_irg(tarval_to_entity(tv));
1065   }
1066   return called_irg;
1067 }
1068
1069 static void collect_calls(ir_node *call, void *env) {
1070   inline_env_t *ienv = env;
1071   ir_node *addr;
1072   tarval *tv;
1073   ir_graph *called_irg;
1074
1075   if (get_irn_op(call) != op_Call) return;
1076
1077   addr = get_Call_ptr(call);
1078   if (get_irn_op(addr) == op_Const) {
1079     /* Check whether the constant is the pointer to a compiled entity. */
1080     tv = get_Const_tarval(addr);
1081     if (tarval_to_entity(tv)) {
1082       called_irg = get_entity_irg(tarval_to_entity(tv));
1083       if (called_irg && ienv->pos < MAX_INLINE) {
1084         /* The Call node calls a locally defined method.  Remember to inline. */
1085         ienv->calls[ienv->pos++] = call;
1086       }
1087     }
1088   }
1089 }
1090
1091 /**
1092  * Inlines all small methods at call sites where the called address comes
1093  * from a Const node that references the entity representing the called
1094  * method.
1095  * The size argument is a rough measure for the code size of the method:
1096  * Methods where the obstack containing the firm graph is smaller than
1097  * size are inlined.
1098  */
1099 void inline_small_irgs(ir_graph *irg, int size) {
1100   int i;
1101   ir_graph *rem = current_ir_graph;
1102   inline_env_t env;
1103
1104   if (!(get_opt_optimize() && get_opt_inline())) return;
1105
1106   current_ir_graph = irg;
1107   /* Handle graph state */
1108   assert(get_irg_phase_state(current_ir_graph) != phase_building);
1109   free_callee_info(current_ir_graph);
1110
1111   /* Find Call nodes to inline.
1112      (We can not inline during a walk of the graph, as inlineing the same
1113      method several times changes the visited flag of the walked graph:
1114      after the first inlineing visited of the callee equals visited of
1115      the caller.  With the next inlineing both are increased.) */
1116   env.pos = 0;
1117   irg_walk(get_irg_end(irg), NULL, collect_calls, &env);
1118
1119   if ((env.pos > 0) && (env.pos < MAX_INLINE)) {
1120     /* There are calls to inline */
1121     collect_phiprojs(irg);
1122     for (i = 0; i < env.pos; i++) {
1123       tarval *tv;
1124       ir_graph *callee;
1125       tv = get_Const_tarval(get_Call_ptr(env.calls[i]));
1126       callee = get_entity_irg(tarval_to_entity(tv));
1127       if (((_obstack_memory_used(callee->obst) - obstack_room(callee->obst)) < size) ||
1128         (get_irg_inline_property(callee) == irg_inline_forced)) {
1129         inline_method(env.calls[i], callee);
1130       }
1131     }
1132   }
1133
1134   current_ir_graph = rem;
1135 }
1136
1137 /**
1138  * Environment for inlining irgs.
1139  */
1140 typedef struct {
1141   int n_nodes;       /**< Nodes in graph except Id, Tuple, Proj, Start, End */
1142   int n_nodes_orig;  /**< for statistics */
1143   eset *call_nodes;  /**< All call nodes in this graph */
1144   int n_call_nodes;
1145   int n_call_nodes_orig; /**< for statistics */
1146   int n_callers;   /**< Number of known graphs that call this graphs. */
1147   int n_callers_orig; /**< for statistics */
1148 } inline_irg_env;
1149
1150 static inline_irg_env *new_inline_irg_env(void) {
1151   inline_irg_env *env = malloc(sizeof(inline_irg_env));
1152   env->n_nodes = -2; /* uncount Start, End */
1153   env->n_nodes_orig = -2; /* uncount Start, End */
1154   env->call_nodes = eset_create();
1155   env->n_call_nodes = 0;
1156   env->n_call_nodes_orig = 0;
1157   env->n_callers = 0;
1158   env->n_callers_orig = 0;
1159   return env;
1160 }
1161
1162 static void free_inline_irg_env(inline_irg_env *env) {
1163   eset_destroy(env->call_nodes);
1164   free(env);
1165 }
1166
1167 static void collect_calls2(ir_node *call, void *env) {
1168   inline_irg_env *x = (inline_irg_env *)env;
1169   ir_op *op = get_irn_op(call);
1170   ir_graph *callee;
1171
1172   /* count nodes in irg */
1173   if (op != op_Proj && op != op_Tuple && op != op_Sync) {
1174     x->n_nodes++;
1175     x->n_nodes_orig++;
1176   }
1177
1178   if (op != op_Call) return;
1179
1180   /* collect all call nodes */
1181   eset_insert(x->call_nodes, (void *)call);
1182   x->n_call_nodes++;
1183   x->n_call_nodes_orig++;
1184
1185   /* count all static callers */
1186   callee = get_call_called_irg(call);
1187   if (callee) {
1188     ((inline_irg_env *)get_irg_link(callee))->n_callers++;
1189     ((inline_irg_env *)get_irg_link(callee))->n_callers_orig++;
1190   }
1191 }
1192
1193 INLINE static int is_leave(ir_graph *irg) {
1194   return (((inline_irg_env *)get_irg_link(irg))->n_call_nodes == 0);
1195 }
1196
1197 INLINE static int is_smaller(ir_graph *callee, int size) {
1198   return (((inline_irg_env *)get_irg_link(callee))->n_nodes < size);
1199 }
1200
1201
1202 /*
1203  * Inlines small leave methods at call sites where the called address comes
1204  * from a Const node that references the entity representing the called
1205  * method.
1206  * The size argument is a rough measure for the code size of the method:
1207  * Methods where the obstack containing the firm graph is smaller than
1208  * size are inlined.
1209  */
1210 void inline_leave_functions(int maxsize, int leavesize, int size) {
1211   inline_irg_env *env;
1212   int i, n_irgs = get_irp_n_irgs();
1213   ir_graph *rem = current_ir_graph;
1214   int did_inline = 1;
1215
1216   if (!(get_opt_optimize() && get_opt_inline())) return;
1217
1218   /* extend all irgs by a temporary data structure for inlineing. */
1219   for (i = 0; i < n_irgs; ++i)
1220     set_irg_link(get_irp_irg(i), new_inline_irg_env());
1221
1222   /* Precompute information in temporary data structure. */
1223   for (i = 0; i < n_irgs; ++i) {
1224     current_ir_graph = get_irp_irg(i);
1225     assert(get_irg_phase_state(current_ir_graph) != phase_building);
1226     free_callee_info(current_ir_graph);
1227
1228     irg_walk(get_irg_end(current_ir_graph), NULL, collect_calls2,
1229          get_irg_link(current_ir_graph));
1230   }
1231
1232   /* and now inline.
1233      Inline leaves recursively -- we might construct new leaves. */
1234   /* int itercnt = 1; */
1235   while (did_inline) {
1236     /* printf("iteration %d\n", itercnt++); */
1237     did_inline = 0;
1238     for (i = 0; i < n_irgs; ++i) {
1239       ir_node *call;
1240       eset *walkset;
1241       int phiproj_computed = 0;
1242
1243       current_ir_graph = get_irp_irg(i);
1244       env = (inline_irg_env *)get_irg_link(current_ir_graph);
1245
1246       /* we can not walk and change a set, nor remove from it.
1247       So recompute.*/
1248       walkset = env->call_nodes;
1249       env->call_nodes = eset_create();
1250       for (call = eset_first(walkset); call; call = eset_next(walkset)) {
1251         inline_irg_env *callee_env;
1252         ir_graph *callee = get_call_called_irg(call);
1253
1254         if (env->n_nodes > maxsize) break;
1255         if (callee &&
1256         ((is_leave(callee) && is_smaller(callee, leavesize)) ||
1257          (get_irg_inline_property(callee) == irg_inline_forced))) {
1258           if (!phiproj_computed) {
1259             phiproj_computed = 1;
1260             collect_phiprojs(current_ir_graph);
1261           }
1262           callee_env = (inline_irg_env *)get_irg_link(callee);
1263 /*         printf(" %s: Inlineing %s.\n", get_entity_name(get_irg_entity(current_ir_graph)), */
1264 /*         get_entity_name(get_irg_entity(callee))); */
1265           if (inline_method(call, callee)) {
1266             did_inline = 1;
1267         env->n_call_nodes--;
1268         eset_insert_all(env->call_nodes, callee_env->call_nodes);
1269         env->n_call_nodes += callee_env->n_call_nodes;
1270         env->n_nodes += callee_env->n_nodes;
1271         callee_env->n_callers--;
1272       }
1273         } else {
1274           eset_insert(env->call_nodes, call);
1275         }
1276       }
1277       eset_destroy(walkset);
1278     }
1279   }
1280
1281   /* printf("Non leaves\n"); */
1282   /* inline other small functions. */
1283   for (i = 0; i < n_irgs; ++i) {
1284     ir_node *call;
1285     eset *walkset;
1286     int phiproj_computed = 0;
1287
1288     current_ir_graph = get_irp_irg(i);
1289     env = (inline_irg_env *)get_irg_link(current_ir_graph);
1290
1291     /* we can not walk and change a set, nor remove from it.
1292        So recompute.*/
1293     walkset = env->call_nodes;
1294     env->call_nodes = eset_create();
1295     for (call = eset_first(walkset); call; call = eset_next(walkset)) {
1296       inline_irg_env *callee_env;
1297       ir_graph *callee = get_call_called_irg(call);
1298
1299       if (env->n_nodes > maxsize) break;
1300       if (callee && is_smaller(callee, size)) {
1301         if (!phiproj_computed) {
1302             phiproj_computed = 1;
1303             collect_phiprojs(current_ir_graph);
1304         }
1305         callee_env = (inline_irg_env *)get_irg_link(callee);
1306 /*       printf(" %s: Inlineing %s.\n", get_entity_name(get_irg_entity(current_ir_graph)), */
1307 /*       get_entity_name(get_irg_entity(callee))); */
1308         if (inline_method(call, callee)) {
1309       did_inline = 1;
1310       env->n_call_nodes--;
1311       eset_insert_all(env->call_nodes, callee_env->call_nodes);
1312       env->n_call_nodes += callee_env->n_call_nodes;
1313       env->n_nodes += callee_env->n_nodes;
1314       callee_env->n_callers--;
1315     }
1316       } else {
1317         eset_insert(env->call_nodes, call);
1318       }
1319     }
1320     eset_destroy(walkset);
1321   }
1322
1323   for (i = 0; i < n_irgs; ++i) {
1324     current_ir_graph = get_irp_irg(i);
1325 #if 0
1326     env = (inline_irg_env *)get_irg_link(current_ir_graph);
1327     if ((env->n_call_nodes_orig != env->n_call_nodes) ||
1328     (env->n_callers_orig != env->n_callers))
1329       printf("Nodes:%3d ->%3d, calls:%3d ->%3d, callers:%3d ->%3d, -- %s\n",
1330          env->n_nodes_orig, env->n_nodes, env->n_call_nodes_orig, env->n_call_nodes,
1331          env->n_callers_orig, env->n_callers,
1332          get_entity_name(get_irg_entity(current_ir_graph)));
1333 #endif
1334     free_inline_irg_env((inline_irg_env *)get_irg_link(current_ir_graph));
1335   }
1336
1337   current_ir_graph = rem;
1338 }
1339
1340 /*******************************************************************/
1341 /*  Code Placement.  Pins all floating nodes to a block where they */
1342 /*  will be executed only if needed.                               */
1343 /*******************************************************************/
1344
1345 /**
1346  * Find the earliest correct block for N.  --- Place N into the
1347  * same Block as its dominance-deepest Input.
1348  */
1349 static void
1350 place_floats_early(ir_node *n, pdeq *worklist)
1351 {
1352   int i, start, irn_arity;
1353
1354   /* we must not run into an infinite loop */
1355   assert (irn_not_visited(n));
1356   mark_irn_visited(n);
1357
1358   /* Place floating nodes. */
1359   if (get_op_pinned(get_irn_op(n)) == floats) {
1360     int depth         = 0;
1361     ir_node *b        = new_Bad();   /* The block to place this node in */
1362     int bad_recursion = is_Bad(get_nodes_block(n));
1363
1364     assert(get_irn_op(n) != op_Block);
1365
1366     if ((get_irn_op(n) == op_Const) ||
1367     (get_irn_op(n) == op_SymConst) ||
1368     (is_Bad(n)) ||
1369     (get_irn_op(n) == op_Unknown)) {
1370       /* These nodes will not be placed by the loop below. */
1371       b = get_irg_start_block(current_ir_graph);
1372       depth = 1;
1373     }
1374
1375     /* find the block for this node. */
1376     irn_arity = get_irn_arity(n);
1377     for (i = 0; i < irn_arity; i++) {
1378       ir_node *dep = get_irn_n(n, i);
1379       ir_node *dep_block;
1380
1381       if ((irn_not_visited(dep))
1382      && (get_op_pinned(get_irn_op(dep)) == floats)) {
1383     place_floats_early(dep, worklist);
1384       }
1385
1386       /*
1387        * A node in the Bad block must stay in the bad block,
1388        * so don't compute a new block for it.
1389        */
1390       if (bad_recursion)
1391         continue;
1392
1393       /* Because all loops contain at least one pinned node, now all
1394          our inputs are either pinned or place_early has already
1395          been finished on them.  We do not have any unfinished inputs!  */
1396       dep_block = get_nodes_Block(dep);
1397       if ((!is_Bad(dep_block)) &&
1398       (get_Block_dom_depth(dep_block) > depth)) {
1399     b = dep_block;
1400     depth = get_Block_dom_depth(dep_block);
1401       }
1402       /* Avoid that the node is placed in the Start block */
1403       if ((depth == 1) && (get_Block_dom_depth(get_nodes_Block(n)) > 1)) {
1404     b = get_Block_cfg_out(get_irg_start_block(current_ir_graph), 0);
1405     assert(b != get_irg_start_block(current_ir_graph));
1406     depth = 2;
1407       }
1408     }
1409     set_nodes_Block(n, b);
1410   }
1411
1412   /* Add predecessors of non floating nodes on worklist. */
1413   start = (get_irn_op(n) == op_Block) ? 0 : -1;
1414   irn_arity = get_irn_arity(n);
1415   for (i = start; i < irn_arity; i++) {
1416     ir_node *pred = get_irn_n(n, i);
1417     if (irn_not_visited(pred)) {
1418       pdeq_putr (worklist, pred);
1419     }
1420   }
1421 }
1422
1423 /**
1424  * Floating nodes form subgraphs that begin at nodes as Const, Load,
1425  * Start, Call and that end at pinned nodes as Store, Call.  Place_early
1426  * places all floating nodes reachable from its argument through floating
1427  * nodes and adds all beginnings at pinned nodes to the worklist.
1428  */
1429 static INLINE void place_early(pdeq* worklist) {
1430   assert(worklist);
1431   inc_irg_visited(current_ir_graph);
1432
1433   /* this inits the worklist */
1434   place_floats_early(get_irg_end(current_ir_graph), worklist);
1435
1436   /* Work the content of the worklist. */
1437   while (!pdeq_empty (worklist)) {
1438     ir_node *n = pdeq_getl (worklist);
1439     if (irn_not_visited(n)) place_floats_early(n, worklist);
1440   }
1441
1442   set_irg_outs_inconsistent(current_ir_graph);
1443   current_ir_graph->pinned = pinned;
1444 }
1445
1446
1447 /** deepest common dominance ancestor of DCA and CONSUMER of PRODUCER. */
1448 static ir_node *
1449 consumer_dom_dca (ir_node *dca, ir_node *consumer, ir_node *producer)
1450 {
1451   ir_node *block = NULL;
1452
1453   /* Compute the latest block into which we can place a node so that it is
1454      before consumer. */
1455   if (get_irn_op(consumer) == op_Phi) {
1456     /* our consumer is a Phi-node, the effective use is in all those
1457        blocks through which the Phi-node reaches producer */
1458     int i, irn_arity;
1459     ir_node *phi_block = get_nodes_Block(consumer);
1460     irn_arity = get_irn_arity(consumer);
1461     for (i = 0;  i < irn_arity; i++) {
1462       if (get_irn_n(consumer, i) == producer) {
1463     block = get_nodes_Block(get_Block_cfgpred(phi_block, i));
1464       }
1465     }
1466   } else {
1467     assert(is_no_Block(consumer));
1468     block = get_nodes_Block(consumer);
1469   }
1470
1471   /* Compute the deepest common ancestor of block and dca. */
1472   assert(block);
1473   if (!dca) return block;
1474   while (get_Block_dom_depth(block) > get_Block_dom_depth(dca))
1475     block = get_Block_idom(block);
1476   while (get_Block_dom_depth(dca) > get_Block_dom_depth(block))
1477     dca = get_Block_idom(dca);
1478   while (block != dca)
1479     { block = get_Block_idom(block); dca = get_Block_idom(dca); }
1480
1481   return dca;
1482 }
1483
1484 static INLINE int get_irn_loop_depth(ir_node *n) {
1485   return get_loop_depth(get_irn_loop(n));
1486 }
1487
1488 /**
1489  * Move n to a block with less loop depth than it's current block. The
1490  * new block must be dominated by early.
1491  */
1492 static void
1493 move_out_of_loops (ir_node *n, ir_node *early)
1494 {
1495   ir_node *best, *dca;
1496   assert(n && early);
1497
1498
1499   /* Find the region deepest in the dominator tree dominating
1500      dca with the least loop nesting depth, but still dominated
1501      by our early placement. */
1502   dca = get_nodes_Block(n);
1503   best = dca;
1504   while (dca != early) {
1505     dca = get_Block_idom(dca);
1506     if (!dca) break; /* should we put assert(dca)? */
1507     if (get_irn_loop_depth(dca) < get_irn_loop_depth(best)) {
1508       best = dca;
1509     }
1510   }
1511   if (best != get_nodes_Block(n)) {
1512     /* debug output
1513     printf("Moving out of loop: "); DDMN(n);
1514     printf(" Outermost block: "); DDMN(early);
1515     printf(" Best block: "); DDMN(best);
1516     printf(" Innermost block: "); DDMN(get_nodes_Block(n));
1517     */
1518     set_nodes_Block(n, best);
1519   }
1520 }
1521
1522 /**
1523  * Find the latest legal block for N and place N into the
1524  * `optimal' Block between the latest and earliest legal block.
1525  * The `optimal' block is the dominance-deepest block of those
1526  * with the least loop-nesting-depth.  This places N out of as many
1527  * loops as possible and then makes it as control dependant as
1528  * possible.
1529  */
1530 static void
1531 place_floats_late(ir_node *n, pdeq *worklist)
1532 {
1533   int i;
1534   ir_node *early;
1535
1536   assert (irn_not_visited(n)); /* no multiple placement */
1537
1538   /* no need to place block nodes, control nodes are already placed. */
1539   if ((get_irn_op(n) != op_Block) &&
1540       (!is_cfop(n)) &&
1541       (get_irn_mode(n) != mode_X)) {
1542     /* Remember the early placement of this block to move it
1543        out of loop no further than the early placement. */
1544     early = get_nodes_Block(n);
1545     /* Assure that our users are all placed, except the Phi-nodes.
1546        --- Each data flow cycle contains at least one Phi-node.  We
1547        have to break the `user has to be placed before the
1548        producer' dependence cycle and the Phi-nodes are the
1549        place to do so, because we need to base our placement on the
1550        final region of our users, which is OK with Phi-nodes, as they
1551        are pinned, and they never have to be placed after a
1552        producer of one of their inputs in the same block anyway. */
1553     for (i = 0; i < get_irn_n_outs(n); i++) {
1554       ir_node *succ = get_irn_out(n, i);
1555       if (irn_not_visited(succ) && (get_irn_op(succ) != op_Phi))
1556     place_floats_late(succ, worklist);
1557     }
1558
1559     /* We have to determine the final block of this node... except for
1560        constants. */
1561     if ((get_op_pinned(get_irn_op(n)) == floats) &&
1562     (get_irn_op(n) != op_Const) &&
1563     (get_irn_op(n) != op_SymConst)) {
1564       ir_node *dca = NULL;  /* deepest common ancestor in the
1565                    dominator tree of all nodes'
1566                    blocks depending on us; our final
1567                    placement has to dominate DCA. */
1568       for (i = 0; i < get_irn_n_outs(n); i++) {
1569     dca = consumer_dom_dca (dca, get_irn_out(n, i), n);
1570       }
1571       set_nodes_Block(n, dca);
1572
1573       move_out_of_loops (n, early);
1574     }
1575   }
1576
1577   mark_irn_visited(n);
1578
1579   /* Add predecessors of all non-floating nodes on list. (Those of floating
1580      nodes are placeded already and therefore are marked.)  */
1581   for (i = 0; i < get_irn_n_outs(n); i++) {
1582     if (irn_not_visited(get_irn_out(n, i))) {
1583       pdeq_putr (worklist, get_irn_out(n, i));
1584     }
1585   }
1586 }
1587
1588 static INLINE void place_late(pdeq* worklist) {
1589   assert(worklist);
1590   inc_irg_visited(current_ir_graph);
1591
1592   /* This fills the worklist initially. */
1593   place_floats_late(get_irg_start_block(current_ir_graph), worklist);
1594   /* And now empty the worklist again... */
1595   while (!pdeq_empty (worklist)) {
1596     ir_node *n = pdeq_getl (worklist);
1597     if (irn_not_visited(n)) place_floats_late(n, worklist);
1598   }
1599 }
1600
1601 void place_code(ir_graph *irg) {
1602   pdeq* worklist;
1603   ir_graph *rem = current_ir_graph;
1604
1605   current_ir_graph = irg;
1606
1607   if (!(get_opt_optimize() && get_opt_global_cse())) return;
1608
1609   /* Handle graph state */
1610   assert(get_irg_phase_state(irg) != phase_building);
1611   if (get_irg_dom_state(irg) != dom_consistent)
1612     compute_doms(irg);
1613
1614   if (1 || get_irg_loopinfo_state(irg) != loopinfo_consistent) {
1615     free_loop_information(irg);
1616     construct_backedges(irg);
1617   }
1618
1619   /* Place all floating nodes as early as possible. This guarantees
1620      a legal code placement. */
1621   worklist = new_pdeq();
1622   place_early(worklist);
1623
1624   /* place_early invalidates the outs, place_late needs them. */
1625   compute_outs(irg);
1626   /* Now move the nodes down in the dominator tree. This reduces the
1627      unnecessary executions of the node. */
1628   place_late(worklist);
1629
1630   set_irg_outs_inconsistent(current_ir_graph);
1631   set_irg_loopinfo_inconsistent(current_ir_graph);
1632   del_pdeq(worklist);
1633   current_ir_graph = rem;
1634 }
1635
1636
1637
1638 /********************************************************************/
1639 /* Control flow optimization.                                       */
1640 /* Removes Bad control flow predecessors and empty blocks.  A block */
1641 /* is empty if it contains only a Jmp node.                         */
1642 /* Blocks can only be removed if they are not needed for the        */
1643 /* semantics of Phi nodes.                                          */
1644 /********************************************************************/
1645
1646 /**
1647  * Removes Tuples from Block control flow predecessors.
1648  * Optimizes blocks with equivalent_node().
1649  * Replaces n by Bad if n is unreachable control flow.
1650  */
1651 static void merge_blocks(ir_node *n, void *env) {
1652   int i;
1653   set_irn_link(n, NULL);
1654
1655   if (get_irn_op(n) == op_Block) {
1656     /* Remove Tuples */
1657     for (i = 0; i < get_Block_n_cfgpreds(n); i++)
1658       /* GL @@@ : is this possible? if (get_opt_normalize()) -- added, all tests go through.
1659        A different order of optimizations might cause problems. */
1660       if (get_opt_normalize())
1661     set_Block_cfgpred(n, i, skip_Tuple(get_Block_cfgpred(n, i)));
1662   } else if (get_opt_optimize() && (get_irn_mode(n) == mode_X)) {
1663     /* We will soon visit a block.  Optimize it before visiting! */
1664     ir_node *b = get_nodes_Block(n);
1665     ir_node *new_node = equivalent_node(b);
1666     while (irn_not_visited(b) && (!is_Bad(new_node)) && (new_node != b)) {
1667       /* We would have to run gigo if new is bad, so we
1668      promote it directly below. */
1669       assert(((b == new_node) ||
1670           get_opt_control_flow_straightening() ||
1671           get_opt_control_flow_weak_simplification()) &&
1672          ("strange flag setting"));
1673       exchange (b, new_node);
1674       b = new_node;
1675       new_node = equivalent_node(b);
1676     }
1677     if (is_Bad(new_node) && get_opt_normalize()) exchange(n, new_Bad());
1678   }
1679 }
1680
1681 /**
1682  * Collects all Phi nodes in link list of Block.
1683  * Marks all blocks "block_visited" if they contain a node other
1684  * than Jmp.
1685  */
1686 static void collect_nodes(ir_node *n, void *env) {
1687   if (is_no_Block(n)) {
1688     ir_node *b = get_nodes_Block(n);
1689
1690     if ((get_irn_op(n) == op_Phi)) {
1691       /* Collect Phi nodes to compact ins along with block's ins. */
1692       set_irn_link(n, get_irn_link(b));
1693       set_irn_link(b, n);
1694     } else if ((get_irn_op(n) != op_Jmp) && !is_Bad(b)) {  /* Check for non empty block. */
1695       mark_Block_block_visited(b);
1696     }
1697   }
1698 }
1699
1700 /** Returns true if pred is predecessor of block. */
1701 static int is_pred_of(ir_node *pred, ir_node *b) {
1702   int i;
1703   for (i = 0; i < get_Block_n_cfgpreds(b); i++) {
1704     ir_node *b_pred = get_nodes_Block(get_Block_cfgpred(b, i));
1705     if (b_pred == pred) return 1;
1706   }
1707   return 0;
1708 }
1709
1710 static int test_whether_dispensable(ir_node *b, int pos) {
1711   int i, j, n_preds = 1;
1712   int dispensable = 1;
1713   ir_node *cfop = get_Block_cfgpred(b, pos);
1714   ir_node *pred = get_nodes_Block(cfop);
1715
1716   if (get_Block_block_visited(pred) + 1
1717       < get_irg_block_visited(current_ir_graph)) {
1718     if (!get_opt_optimize() || !get_opt_control_flow_strong_simplification()) {
1719       /* Mark block so that is will not be removed. */
1720       set_Block_block_visited(pred, get_irg_block_visited(current_ir_graph)-1);
1721       return 1;
1722     }
1723     /* Seems to be empty. */
1724     if (!get_irn_link(b)) {
1725       /* There are no Phi nodes ==> dispensable. */
1726       n_preds = get_Block_n_cfgpreds(pred);
1727     } else {
1728       /* b's pred blocks and pred's pred blocks must be pairwise disjunct.
1729      Work preds < pos as if they were already removed. */
1730       for (i = 0; i < pos; i++) {
1731     ir_node *b_pred = get_nodes_Block(get_Block_cfgpred(b, i));
1732     if (get_Block_block_visited(b_pred) + 1
1733         < get_irg_block_visited(current_ir_graph)) {
1734       for (j = 0; j < get_Block_n_cfgpreds(b_pred); j++) {
1735         ir_node *b_pred_pred = get_nodes_Block(get_Block_cfgpred(b_pred, j));
1736         if (is_pred_of(b_pred_pred, pred)) dispensable = 0;
1737       }
1738     } else {
1739       if (is_pred_of(b_pred, pred)) dispensable = 0;
1740     }
1741       }
1742       for (i = pos +1; i < get_Block_n_cfgpreds(b); i++) {
1743     ir_node *b_pred = get_nodes_Block(get_Block_cfgpred(b, i));
1744     if (is_pred_of(b_pred, pred)) dispensable = 0;
1745       }
1746       if (!dispensable) {
1747     set_Block_block_visited(pred, get_irg_block_visited(current_ir_graph)-1);
1748     n_preds = 1;
1749       } else {
1750         n_preds = get_Block_n_cfgpreds(pred);
1751       }
1752     }
1753   }
1754
1755   return n_preds;
1756 }
1757
1758 static void optimize_blocks(ir_node *b, void *env) {
1759   int i, j, k, max_preds, n_preds;
1760   ir_node *pred, *phi;
1761   ir_node **in;
1762
1763   /* Count the number of predecessor if this block is merged with pred blocks
1764      that are empty. */
1765   max_preds = 0;
1766   for (i = 0; i < get_Block_n_cfgpreds(b); i++) {
1767     max_preds += test_whether_dispensable(b, i);
1768   }
1769   in = (ir_node **) malloc(max_preds * sizeof(ir_node *));
1770
1771 /*-
1772   printf(" working on "); DDMN(b);
1773   for (i = 0; i < get_Block_n_cfgpreds(b); i++) {
1774     pred = get_nodes_Block(get_Block_cfgpred(b, i));
1775     if (is_Bad(get_Block_cfgpred(b, i))) {
1776       printf("  removing Bad %i\n ", i);
1777     } else if (get_Block_block_visited(pred) +1
1778            < get_irg_block_visited(current_ir_graph)) {
1779       printf("  removing pred %i ", i); DDMN(pred);
1780     } else { printf("  Nothing to do for "); DDMN(pred); }
1781   }
1782   * end Debug output -*/
1783
1784   /*- Fix the Phi nodes -*/
1785   phi = get_irn_link(b);
1786   while (phi) {
1787     assert(get_irn_op(phi) == op_Phi);
1788     /* Find the new predecessors for the Phi */
1789     n_preds = 0;
1790     for (i = 0; i < get_Block_n_cfgpreds(b); i++) {
1791       pred = get_nodes_Block(get_Block_cfgpred(b, i));
1792       if (is_Bad(get_Block_cfgpred(b, i))) {
1793     /* Do nothing */
1794       } else if (get_Block_block_visited(pred) +1
1795          < get_irg_block_visited(current_ir_graph)) {
1796     /* It's an empty block and not yet visited. */
1797     ir_node *phi_pred = get_Phi_pred(phi, i);
1798     for (j = 0; j < get_Block_n_cfgpreds(pred); j++) {
1799       if (get_nodes_Block(phi_pred) == pred) {
1800         assert(get_irn_op(phi_pred) == op_Phi);  /* Block is empty!! */
1801         in[n_preds] = get_Phi_pred(phi_pred, j);
1802       } else {
1803         in[n_preds] = phi_pred;
1804       }
1805       n_preds++;
1806     }
1807     /* The Phi_pred node is replaced now if it is a Phi.
1808        In Schleifen kann offenbar der entfernte Phi Knoten legal verwendet werden.
1809        Daher muss der Phiknoten durch den neuen ersetzt werden.
1810        Weiter muss der alte Phiknoten entfernt werden (durch ersetzen oder
1811        durch einen Bad) damit er aus den keep_alive verschwinden kann.
1812        Man sollte also, falls keine Schleife vorliegt, exchange mit new_Bad
1813        aufrufen.  */
1814     if (get_nodes_Block(phi_pred) == pred) {
1815       /* remove the Phi as it might be kept alive. Further there
1816          might be other users. */
1817       exchange(phi_pred, phi);  /* geht, ist aber doch semantisch falsch! Warum?? */
1818     }
1819       } else {
1820     in[n_preds] = get_Phi_pred(phi, i);
1821     n_preds ++;
1822       }
1823     }
1824     /* Fix the node */
1825     set_irn_in(phi, n_preds, in);
1826
1827     phi = get_irn_link(phi);
1828   }
1829
1830 /*-
1831       This happens only if merge between loop backedge and single loop entry. -*/
1832   for (k = 0; k < get_Block_n_cfgpreds(b); k++) {
1833     pred = get_nodes_Block(get_Block_cfgpred(b, k));
1834     if (get_Block_block_visited(pred)+1 < get_irg_block_visited(current_ir_graph)) {
1835       phi = get_irn_link(pred);
1836       while (phi) {
1837     if (get_irn_op(phi) == op_Phi) {
1838       set_nodes_Block(phi, b);
1839
1840       n_preds = 0;
1841       for (i = 0; i < k; i++) {
1842         pred = get_nodes_Block(get_Block_cfgpred(b, i));
1843         if (is_Bad(get_Block_cfgpred(b, i))) {
1844           /* Do nothing */
1845         } else if (get_Block_block_visited(pred) +1
1846            < get_irg_block_visited(current_ir_graph)) {
1847           /* It's an empty block and not yet visited. */
1848           for (j = 0; j < get_Block_n_cfgpreds(pred); j++) {
1849         /* @@@ Hier brauche ich Schleifeninformation!!! Kontrollflusskante
1850            muss Rueckwaertskante sein! (An allen vier in[n_preds] = phi
1851            Anweisungen.) Trotzdem tuts bisher!! */
1852         in[n_preds] = phi;
1853         n_preds++;
1854           }
1855         } else {
1856           in[n_preds] = phi;
1857           n_preds++;
1858         }
1859       }
1860       for (i = 0; i < get_Phi_n_preds(phi); i++) {
1861         in[n_preds] = get_Phi_pred(phi, i);
1862         n_preds++;
1863       }
1864       for (i = k+1; i < get_Block_n_cfgpreds(b); i++) {
1865         pred = get_nodes_Block(get_Block_cfgpred(b, i));
1866         if (is_Bad(get_Block_cfgpred(b, i))) {
1867           /* Do nothing */
1868         } else if (get_Block_block_visited(pred) +1
1869            < get_irg_block_visited(current_ir_graph)) {
1870           /* It's an empty block and not yet visited. */
1871           for (j = 0; j < get_Block_n_cfgpreds(pred); j++) {
1872         in[n_preds] = phi;
1873         n_preds++;
1874           }
1875         } else {
1876           in[n_preds] = phi;
1877           n_preds++;
1878         }
1879       }
1880       set_irn_in(phi, n_preds, in);
1881     }
1882     phi = get_irn_link(phi);
1883       }
1884     }
1885   }
1886
1887   /*- Fix the block -*/
1888   n_preds = 0;
1889   for (i = 0; i < get_Block_n_cfgpreds(b); i++) {
1890     pred = get_nodes_Block(get_Block_cfgpred(b, i));
1891     if (is_Bad(get_Block_cfgpred(b, i))) {
1892       /* Do nothing */
1893     } else if (get_Block_block_visited(pred) +1
1894            < get_irg_block_visited(current_ir_graph)) {
1895       /* It's an empty block and not yet visited. */
1896       assert(get_Block_n_cfgpreds(b) > 1);
1897                         /* Else it should be optimized by equivalent_node. */
1898       for (j = 0; j < get_Block_n_cfgpreds(pred); j++) {
1899     in[n_preds] = get_Block_cfgpred(pred, j);
1900     n_preds++;
1901       }
1902       /* Remove block as it might be kept alive. */
1903       exchange(pred, b/*new_Bad()*/);
1904     } else {
1905       in[n_preds] = get_Block_cfgpred(b, i);
1906       n_preds ++;
1907     }
1908   }
1909   set_irn_in(b, n_preds, in);
1910   free(in);
1911 }
1912
1913 void optimize_cf(ir_graph *irg) {
1914   int i;
1915   ir_node **in;
1916   ir_node *end = get_irg_end(irg);
1917   ir_graph *rem = current_ir_graph;
1918   current_ir_graph = irg;
1919
1920   /* Handle graph state */
1921   assert(get_irg_phase_state(irg) != phase_building);
1922   if (get_irg_outs_state(current_ir_graph) == outs_consistent)
1923     set_irg_outs_inconsistent(current_ir_graph);
1924   if (get_irg_dom_state(current_ir_graph) == dom_consistent)
1925     set_irg_dom_inconsistent(current_ir_graph);
1926
1927   /* Use block visited flag to mark non-empty blocks. */
1928   inc_irg_block_visited(irg);
1929   irg_walk(end, merge_blocks, collect_nodes, NULL);
1930
1931   /* Optimize the standard code. */
1932   irg_block_walk(get_irg_end_block(irg), optimize_blocks, NULL, NULL);
1933
1934   /* Walk all keep alives, optimize them if block, add to new in-array
1935      for end if useful. */
1936   in = NEW_ARR_F (ir_node *, 1);
1937   in[0] = get_nodes_Block(end);
1938   inc_irg_visited(current_ir_graph);
1939   for(i = 0; i < get_End_n_keepalives(end); i++) {
1940     ir_node *ka = get_End_keepalive(end, i);
1941     if (irn_not_visited(ka)) {
1942       if ((get_irn_op(ka) == op_Block) && Block_not_block_visited(ka)) {
1943     set_irg_block_visited(current_ir_graph,  /* Don't walk all the way to Start. */
1944               get_irg_block_visited(current_ir_graph)-1);
1945     irg_block_walk(ka, optimize_blocks, NULL, NULL);
1946     mark_irn_visited(ka);
1947     ARR_APP1 (ir_node *, in, ka);
1948       } else if (get_irn_op(ka) == op_Phi) {
1949     mark_irn_visited(ka);
1950     ARR_APP1 (ir_node *, in, ka);
1951       }
1952     }
1953   }
1954   /* DEL_ARR_F(end->in);   GL @@@ tut nicht ! */
1955   end->in = in;
1956
1957   current_ir_graph = rem;
1958 }
1959
1960
1961 /**
1962  * Called by walker of remove_critical_cf_edges().
1963  *
1964  * Place an empty block to an edge between a blocks of multiple
1965  * predecessors and a block of multiple successors.
1966  *
1967  * @param n IR node
1968  * @param env Environment of walker. This field is unused and has
1969  *            the value NULL.
1970  */
1971 static void walk_critical_cf_edges(ir_node *n, void *env) {
1972   int arity, i;
1973   ir_node *pre, *block, **in, *jmp;
1974
1975   /* Block has multiple predecessors */
1976   if ((op_Block == get_irn_op(n)) &&
1977       (get_irn_arity(n) > 1)) {
1978     arity = get_irn_arity(n);
1979
1980     if (n == get_irg_end_block(current_ir_graph))
1981       return;  /*  No use to add a block here.      */
1982
1983     for (i=0; i<arity; i++) {
1984       pre = get_irn_n(n, i);
1985       /* Predecessor has multiple successors. Insert new flow edge */
1986       if ((NULL != pre) &&
1987     (op_Proj == get_irn_op(pre)) &&
1988     op_Raise != get_irn_op(skip_Proj(pre))) {
1989
1990     /* set predecessor array for new block */
1991     in = NEW_ARR_D (ir_node *, current_ir_graph->obst, 1);
1992     /* set predecessor of new block */
1993     in[0] = pre;
1994     block = new_Block(1, in);
1995     /* insert new jmp node to new block */
1996     switch_block(block);
1997     jmp = new_Jmp();
1998     switch_block(n);
1999     /* set successor of new block */
2000     set_irn_n(n, i, jmp);
2001
2002       } /* predecessor has multiple successors */
2003     } /* for all predecessors */
2004   } /* n is a block */
2005 }
2006
2007 void remove_critical_cf_edges(ir_graph *irg) {
2008   if (get_opt_critical_edges())
2009     irg_walk_graph(irg, NULL, walk_critical_cf_edges, NULL);
2010 }