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