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