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