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