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