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