inline_method():
[libfirm] / ir / opt / opt_inline.c
1 /*
2  * Copyright (C) 1995-2008 University of Karlsruhe.  All right reserved.
3  *
4  * This file is part of libFirm.
5  *
6  * This file may be distributed and/or modified under the terms of the
7  * GNU General Public License version 2 as published by the Free Software
8  * Foundation and appearing in the file LICENSE.GPL included in the
9  * packaging of this file.
10  *
11  * Licensees holding valid libFirm Professional Edition licenses may use
12  * this file in accordance with the libFirm Commercial License.
13  * Agreement provided with the Software.
14  *
15  * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
16  * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
17  * PURPOSE.
18  */
19
20 /**
21  * @file
22  * @brief    Dead node elimination and Procedure Inlining.
23  * @author   Michael Beck, Goetz Lindenmaier
24  * @version  $Id$
25  */
26 #ifdef HAVE_CONFIG_H
27 # include "config.h"
28 #endif
29
30 #include <limits.h>
31 #include <assert.h>
32
33 #include "irnode_t.h"
34 #include "irgraph_t.h"
35 #include "irprog_t.h"
36
37 #include "iroptimize.h"
38 #include "ircons_t.h"
39 #include "iropt_t.h"
40 #include "irgopt.h"
41 #include "irgmod.h"
42 #include "irgwalk.h"
43
44 #include "adt/array.h"
45 #include "adt/pset.h"
46 #include "adt/pmap.h"
47 #include "adt/pdeq.h"
48 #include "adt/xmalloc.h"
49
50 #include "irouts.h"
51 #include "irloop_t.h"
52 #include "irbackedge_t.h"
53 #include "opt_inline_t.h"
54 #include "cgana.h"
55 #include "trouts.h"
56 #include "error.h"
57
58 #include "analyze_irg_args.h"
59 #include "iredges_t.h"
60 #include "irflag_t.h"
61 #include "irhooks.h"
62 #include "irtools.h"
63
64 DEBUG_ONLY(static firm_dbg_module_t *dbg;)
65
66 /*------------------------------------------------------------------*/
67 /* Routines for dead node elimination / copying garbage collection  */
68 /* of the obstack.                                                  */
69 /*------------------------------------------------------------------*/
70
71 /**
72  * Remember the new node in the old node by using a field all nodes have.
73  */
74 #define set_new_node(oldn, newn)  set_irn_link(oldn, newn)
75
76 /**
77  * Get this new node, before the old node is forgotten.
78  */
79 #define get_new_node(oldn) get_irn_link(oldn)
80
81 /**
82  * Check if a new node was set.
83  */
84 #define has_new_node(n) (get_new_node(n) != NULL)
85
86 /**
87  * We use the block_visited flag to mark that we have computed the
88  * number of useful predecessors for this block.
89  * Further we encode the new arity in this flag in the old blocks.
90  * Remembering the arity is useful, as it saves a lot of pointer
91  * accesses.  This function is called for all Phi and Block nodes
92  * in a Block.
93  */
94 static INLINE int
95 compute_new_arity(ir_node *b) {
96         int i, res, irn_arity;
97         int irg_v, block_v;
98
99         irg_v = get_irg_block_visited(current_ir_graph);
100         block_v = get_Block_block_visited(b);
101         if (block_v >= irg_v) {
102                 /* we computed the number of preds for this block and saved it in the
103                    block_v flag */
104                 return block_v - irg_v;
105         } else {
106                 /* compute the number of good predecessors */
107                 res = irn_arity = get_irn_arity(b);
108                 for (i = 0; i < irn_arity; i++)
109                         if (is_Bad(get_irn_n(b, i))) res--;
110                         /* save it in the flag. */
111                         set_Block_block_visited(b, irg_v + res);
112                         return res;
113         }
114 }
115
116 /**
117  * Copies the node to the new obstack. The Ins of the new node point to
118  * the predecessors on the old obstack.  For block/phi nodes not all
119  * predecessors might be copied.  n->link points to the new node.
120  * For Phi and Block nodes the function allocates in-arrays with an arity
121  * only for useful predecessors.  The arity is determined by counting
122  * the non-bad predecessors of the block.
123  *
124  * @param n    The node to be copied
125  * @param env  if non-NULL, the node number attribute will be copied to the new node
126  *
127  * Note: Also used for loop unrolling.
128  */
129 static void copy_node(ir_node *n, void *env) {
130         ir_node *nn, *block;
131         int new_arity;
132         ir_op *op = get_irn_op(n);
133         (void) env;
134
135         if (op == op_Bad) {
136                 /* node copied already */
137                 return;
138         } else if (op == op_Block) {
139                 block = NULL;
140                 new_arity = compute_new_arity(n);
141                 n->attr.block.graph_arr = NULL;
142         } else {
143                 block = get_nodes_block(n);
144                 if (op == op_Phi) {
145                         new_arity = compute_new_arity(block);
146                 } else {
147                         new_arity = get_irn_arity(n);
148                 }
149         }
150         nn = new_ir_node(get_irn_dbg_info(n),
151                 current_ir_graph,
152                 block,
153                 op,
154                 get_irn_mode(n),
155                 new_arity,
156                 get_irn_in(n) + 1);
157         /* Copy the attributes.  These might point to additional data.  If this
158            was allocated on the old obstack the pointers now are dangling.  This
159            frees e.g. the memory of the graph_arr allocated in new_immBlock. */
160         if (op == op_Block) {
161                 /* we cannot allow blocks WITHOUT macroblock input */
162                 set_Block_MacroBlock(nn, get_Block_MacroBlock(n));
163         }
164         copy_node_attr(n, nn);
165
166 #ifdef DEBUG_libfirm
167         {
168                 int copy_node_nr = env != NULL;
169                 if (copy_node_nr) {
170                         /* for easier debugging, we want to copy the node numbers too */
171                         nn->node_nr = n->node_nr;
172                 }
173         }
174 #endif
175
176         set_new_node(n, nn);
177         hook_dead_node_elim_subst(current_ir_graph, n, nn);
178 }
179
180 /**
181  * Copies new predecessors of old node to new node remembered in link.
182  * Spare the Bad predecessors of Phi and Block nodes.
183  */
184 static void copy_preds(ir_node *n, void *env) {
185         ir_node *nn, *block;
186         int i, j, irn_arity;
187         (void) env;
188
189         nn = get_new_node(n);
190
191         if (is_Block(n)) {
192                 /* copy the macro block header */
193                 ir_node *mbh = get_Block_MacroBlock(n);
194
195                 if (mbh == n) {
196                         /* this block is a macroblock header */
197                         set_Block_MacroBlock(nn, nn);
198                 } else {
199                         /* get the macro block header */
200                         ir_node *nmbh = get_new_node(mbh);
201                         assert(nmbh != NULL);
202                         set_Block_MacroBlock(nn, nmbh);
203                 }
204
205                 /* Don't copy Bad nodes. */
206                 j = 0;
207                 irn_arity = get_irn_arity(n);
208                 for (i = 0; i < irn_arity; i++) {
209                         if (! is_Bad(get_irn_n(n, i))) {
210                                 ir_node *pred = get_irn_n(n, i);
211                                 set_irn_n(nn, j, get_new_node(pred));
212                                 j++;
213                         }
214                 }
215                 /* repair the block visited flag from above misuse. Repair it in both
216                    graphs so that the old one can still be used. */
217                 set_Block_block_visited(nn, 0);
218                 set_Block_block_visited(n, 0);
219                 /* Local optimization could not merge two subsequent blocks if
220                    in array contained Bads.  Now it's possible.
221                    We don't call optimize_in_place as it requires
222                    that the fields in ir_graph are set properly. */
223                 if ((get_opt_control_flow_straightening()) &&
224                         (get_Block_n_cfgpreds(nn) == 1) &&
225                         is_Jmp(get_Block_cfgpred(nn, 0))) {
226                         ir_node *old = get_nodes_block(get_Block_cfgpred(nn, 0));
227                         if (nn == old) {
228                                 /* Jmp jumps into the block it is in -- deal self cycle. */
229                                 assert(is_Bad(get_new_node(get_irg_bad(current_ir_graph))));
230                                 exchange(nn, get_new_node(get_irg_bad(current_ir_graph)));
231                         } else {
232                                 exchange(nn, old);
233                         }
234                 }
235         } else if (is_Phi(n) && get_irn_arity(n) > 0) {
236                 /* Don't copy node if corresponding predecessor in block is Bad.
237                    The Block itself should not be Bad. */
238                 block = get_nodes_block(n);
239                 set_nodes_block(nn, get_new_node(block));
240                 j = 0;
241                 irn_arity = get_irn_arity(n);
242                 for (i = 0; i < irn_arity; i++) {
243                         if (! is_Bad(get_irn_n(block, i))) {
244                                 ir_node *pred = get_irn_n(n, i);
245                                 set_irn_n(nn, j, get_new_node(pred));
246                                 /*if (is_backedge(n, i)) set_backedge(nn, j);*/
247                                 j++;
248                         }
249                 }
250                 /* If the pre walker reached this Phi after the post walker visited the
251                    block block_visited is > 0. */
252                 set_Block_block_visited(get_nodes_block(n), 0);
253                 /* Compacting the Phi's ins might generate Phis with only one
254                    predecessor. */
255                 if (get_irn_arity(nn) == 1)
256                         exchange(nn, get_irn_n(nn, 0));
257         } else {
258                 irn_arity = get_irn_arity(n);
259                 for (i = -1; i < irn_arity; i++)
260                         set_irn_n(nn, i, get_new_node(get_irn_n(n, i)));
261         }
262         /* Now the new node is complete.  We can add it to the hash table for CSE.
263            @@@ inlining aborts if we identify End. Why? */
264         if (!is_End(nn))
265                 add_identities(current_ir_graph->value_table, nn);
266 }
267
268 /**
269  * Copies the graph recursively, compacts the keep-alives of the end node.
270  *
271  * @param irg           the graph to be copied
272  * @param copy_node_nr  If non-zero, the node number will be copied
273  */
274 static void copy_graph(ir_graph *irg, int copy_node_nr) {
275         ir_node *oe, *ne, *ob, *nb, *om, *nm; /* old end, new end, old bad, new bad, old NoMem, new NoMem */
276         ir_node *ka;      /* keep alive */
277         int i, irn_arity;
278         unsigned long vfl;
279
280         /* Some nodes must be copied by hand, sigh */
281         vfl = get_irg_visited(irg);
282         set_irg_visited(irg, vfl + 1);
283
284         oe = get_irg_end(irg);
285         mark_irn_visited(oe);
286         /* copy the end node by hand, allocate dynamic in array! */
287         ne = new_ir_node(get_irn_dbg_info(oe),
288                 irg,
289                 NULL,
290                 op_End,
291                 mode_X,
292                 -1,
293                 NULL);
294         /* Copy the attributes.  Well, there might be some in the future... */
295         copy_node_attr(oe, ne);
296         set_new_node(oe, ne);
297
298         /* copy the Bad node */
299         ob = get_irg_bad(irg);
300         mark_irn_visited(ob);
301         nb = new_ir_node(get_irn_dbg_info(ob),
302                 irg,
303                 NULL,
304                 op_Bad,
305                 mode_T,
306                 0,
307                 NULL);
308         copy_node_attr(ob, nb);
309         set_new_node(ob, nb);
310
311         /* copy the NoMem node */
312         om = get_irg_no_mem(irg);
313         mark_irn_visited(om);
314         nm = new_ir_node(get_irn_dbg_info(om),
315                 irg,
316                 NULL,
317                 op_NoMem,
318                 mode_M,
319                 0,
320                 NULL);
321         copy_node_attr(om, nm);
322         set_new_node(om, nm);
323
324         /* copy the live nodes */
325         set_irg_visited(irg, vfl);
326         irg_walk(get_nodes_block(oe), copy_node, copy_preds, INT_TO_PTR(copy_node_nr));
327
328         /* Note: from yet, the visited flag of the graph is equal to vfl + 1 */
329
330         /* visit the anchors as well */
331         for (i = get_irg_n_anchors(irg) - 1; i >= 0; --i) {
332                 ir_node *n = get_irg_anchor(irg, i);
333
334                 if (n && (get_irn_visited(n) <= vfl)) {
335                         set_irg_visited(irg, vfl);
336                         irg_walk(n, copy_node, copy_preds, INT_TO_PTR(copy_node_nr));
337                 }
338         }
339
340         /* copy_preds for the end node ... */
341         set_nodes_block(ne, get_new_node(get_nodes_block(oe)));
342
343         /*- ... and now the keep alives. -*/
344         /* First pick the not marked block nodes and walk them.  We must pick these
345            first as else we will oversee blocks reachable from Phis. */
346         irn_arity = get_End_n_keepalives(oe);
347         for (i = 0; i < irn_arity; i++) {
348                 ka = get_End_keepalive(oe, i);
349                 if (is_Block(ka)) {
350                         if (get_irn_visited(ka) <= vfl) {
351                                 /* We must keep the block alive and copy everything reachable */
352                                 set_irg_visited(irg, vfl);
353                                 irg_walk(ka, copy_node, copy_preds, INT_TO_PTR(copy_node_nr));
354                         }
355                         add_End_keepalive(ne, get_new_node(ka));
356                 }
357         }
358
359         /* Now pick other nodes.  Here we will keep all! */
360         irn_arity = get_End_n_keepalives(oe);
361         for (i = 0; i < irn_arity; i++) {
362                 ka = get_End_keepalive(oe, i);
363                 if (!is_Block(ka)) {
364                         if (get_irn_visited(ka) <= vfl) {
365                                 /* We didn't copy the node yet.  */
366                                 set_irg_visited(irg, vfl);
367                                 irg_walk(ka, copy_node, copy_preds, INT_TO_PTR(copy_node_nr));
368                         }
369                         add_End_keepalive(ne, get_new_node(ka));
370                 }
371         }
372
373         /* start block sometimes only reached after keep alives */
374         set_nodes_block(nb, get_new_node(get_nodes_block(ob)));
375         set_nodes_block(nm, get_new_node(get_nodes_block(om)));
376 }
377
378 /**
379  * Copies the graph reachable from current_ir_graph->end to the obstack
380  * in current_ir_graph and fixes the environment.
381  * Then fixes the fields in current_ir_graph containing nodes of the
382  * graph.
383  *
384  * @param copy_node_nr  If non-zero, the node number will be copied
385  */
386 static void
387 copy_graph_env(int copy_node_nr) {
388         ir_graph *irg = current_ir_graph;
389         ir_node *old_end, *new_anchor;
390         int i;
391
392         /* remove end_except and end_reg nodes */
393         old_end = get_irg_end(irg);
394         set_irg_end_except (irg, old_end);
395         set_irg_end_reg    (irg, old_end);
396
397         /* Not all nodes remembered in irg might be reachable
398            from the end node.  Assure their link is set to NULL, so that
399            we can test whether new nodes have been computed. */
400         for (i = get_irg_n_anchors(irg) - 1; i >= 0; --i) {
401                 ir_node *n = get_irg_anchor(irg, i);
402                 if (n != NULL)
403                         set_new_node(n, NULL);
404         }
405         /* we use the block walk flag for removing Bads from Blocks ins. */
406         inc_irg_block_visited(irg);
407
408         /* copy the graph */
409         copy_graph(irg, copy_node_nr);
410
411         /* fix the anchor */
412         old_end    = get_irg_end(irg);
413         new_anchor = new_Anchor(irg);
414
415         for (i = get_irg_n_anchors(irg) - 1; i >= 0; --i) {
416                 ir_node *n = get_irg_anchor(irg, i);
417                 if (n)
418                         set_irn_n(new_anchor, i, get_new_node(n));
419         }
420         free_End(old_end);
421         irg->anchor = new_anchor;
422
423         /* ensure the new anchor is placed in the endblock */
424         set_nodes_block(new_anchor, get_irg_end_block(irg));
425 }
426
427 /**
428  * Copies all reachable nodes to a new obstack.  Removes bad inputs
429  * from block nodes and the corresponding inputs from Phi nodes.
430  * Merges single exit blocks with single entry blocks and removes
431  * 1-input Phis.
432  * Adds all new nodes to a new hash table for CSE.  Does not
433  * perform CSE, so the hash table might contain common subexpressions.
434  */
435 void dead_node_elimination(ir_graph *irg) {
436         ir_graph *rem;
437 #ifdef INTERPROCEDURAL_VIEW
438         int rem_ipview = get_interprocedural_view();
439 #endif
440         struct obstack *graveyard_obst = NULL;
441         struct obstack *rebirth_obst   = NULL;
442         assert(! edges_activated(irg) && "dead node elimination requires disabled edges");
443
444         /* inform statistics that we started a dead-node elimination run */
445         hook_dead_node_elim(irg, 1);
446
447         /* Remember external state of current_ir_graph. */
448         rem = current_ir_graph;
449         current_ir_graph = irg;
450 #ifdef INTERPROCEDURAL_VIEW
451         set_interprocedural_view(0);
452 #endif
453
454         assert(get_irg_phase_state(irg) != phase_building);
455
456         /* Handle graph state */
457         free_callee_info(irg);
458         free_irg_outs(irg);
459         free_trouts();
460
461         /* @@@ so far we loose loops when copying */
462         free_loop_information(irg);
463
464         set_irg_doms_inconsistent(irg);
465
466         /* A quiet place, where the old obstack can rest in peace,
467            until it will be cremated. */
468         graveyard_obst = irg->obst;
469
470         /* A new obstack, where the reachable nodes will be copied to. */
471         rebirth_obst = xmalloc(sizeof(*rebirth_obst));
472         irg->obst = rebirth_obst;
473         obstack_init(irg->obst);
474         irg->last_node_idx = 0;
475
476         /* We also need a new value table for CSE */
477         del_identities(irg->value_table);
478         irg->value_table = new_identities();
479
480         /* Copy the graph from the old to the new obstack */
481         copy_graph_env(/*copy_node_nr=*/1);
482
483         /* Free memory from old unoptimized obstack */
484         obstack_free(graveyard_obst, 0);  /* First empty the obstack ... */
485         xfree(graveyard_obst);            /* ... then free it.           */
486
487         /* inform statistics that the run is over */
488         hook_dead_node_elim(irg, 0);
489
490         current_ir_graph = rem;
491 #ifdef INTERPROCEDURAL_VIEW
492         set_interprocedural_view(rem_ipview);
493 #endif
494 }
495
496 /**
497  * Relink bad predecessors of a block and store the old in array to the
498  * link field. This function is called by relink_bad_predecessors().
499  * The array of link field starts with the block operand at position 0.
500  * If block has bad predecessors, create a new in array without bad preds.
501  * Otherwise let in array untouched.
502  */
503 static void relink_bad_block_predecessors(ir_node *n, void *env) {
504         ir_node **new_in, *irn;
505         int i, new_irn_n, old_irn_arity, new_irn_arity = 0;
506         (void) env;
507
508         /* if link field of block is NULL, look for bad predecessors otherwise
509            this is already done */
510         if (is_Block(n) && get_irn_link(n) == NULL) {
511                 /* save old predecessors in link field (position 0 is the block operand)*/
512                 set_irn_link(n, get_irn_in(n));
513
514                 /* count predecessors without bad nodes */
515                 old_irn_arity = get_irn_arity(n);
516                 for (i = 0; i < old_irn_arity; i++)
517                         if (!is_Bad(get_irn_n(n, i)))
518                                 ++new_irn_arity;
519
520                 /* arity changing: set new predecessors without bad nodes */
521                 if (new_irn_arity < old_irn_arity) {
522                         /* Get new predecessor array. We do not resize the array, as we must
523                            keep the old one to update Phis. */
524                         new_in = NEW_ARR_D(ir_node *, current_ir_graph->obst, (new_irn_arity+1));
525
526                         /* set new predecessors in array */
527                         new_in[0] = NULL;
528                         new_irn_n = 1;
529                         for (i = 0; i < old_irn_arity; i++) {
530                                 irn = get_irn_n(n, i);
531                                 if (!is_Bad(irn)) {
532                                         new_in[new_irn_n] = irn;
533                                         is_backedge(n, i) ? set_backedge(n, new_irn_n-1) : set_not_backedge(n, new_irn_n-1);
534                                         ++new_irn_n;
535                                 }
536                         }
537                         /* ARR_SETLEN(int, n->attr.block.backedge, new_irn_arity); */
538                         ARR_SHRINKLEN(n->attr.block.backedge, new_irn_arity);
539                         n->in = new_in;
540                 } /* ir node has bad predecessors */
541         } /* Block is not relinked */
542 }
543
544 /**
545  * Relinks Bad predecessors from Blocks and Phis called by walker
546  * remove_bad_predecesors(). If n is a Block, call
547  * relink_bad_block_redecessors(). If n is a Phi-node, call also the relinking
548  * function of Phi's Block. If this block has bad predecessors, relink preds
549  * of the Phi-node.
550  */
551 static void relink_bad_predecessors(ir_node *n, void *env) {
552         ir_node *block, **old_in;
553         int i, old_irn_arity, new_irn_arity;
554
555         /* relink bad predecessors of a block */
556         if (is_Block(n))
557                 relink_bad_block_predecessors(n, env);
558
559         /* If Phi node relink its block and its predecessors */
560         if (is_Phi(n)) {
561                 /* Relink predecessors of phi's block */
562                 block = get_nodes_block(n);
563                 if (get_irn_link(block) == NULL)
564                         relink_bad_block_predecessors(block, env);
565
566                 old_in = (ir_node **)get_irn_link(block); /* Of Phi's Block */
567                 old_irn_arity = ARR_LEN(old_in);
568
569                 /* Relink Phi predecessors if count of predecessors changed */
570                 if (old_irn_arity != ARR_LEN(get_irn_in(block))) {
571                         /* set new predecessors in array
572                            n->in[0] remains the same block */
573                         new_irn_arity = 1;
574                         for(i = 1; i < old_irn_arity; i++)
575                                 if (!is_Bad(old_in[i])) {
576                                         n->in[new_irn_arity] = n->in[i];
577                                         is_backedge(n, i) ? set_backedge(n, new_irn_arity) : set_not_backedge(n, new_irn_arity);
578                                         ++new_irn_arity;
579                                 }
580
581                                 ARR_SETLEN(ir_node *, n->in, new_irn_arity);
582                                 ARR_SETLEN(int, n->attr.phi.u.backedge, new_irn_arity);
583                 }
584         } /* n is a Phi node */
585 }
586
587 /*
588  * Removes Bad Bad predecessors from Blocks and the corresponding
589  * inputs to Phi nodes as in dead_node_elimination but without
590  * copying the graph.
591  * On walking up set the link field to NULL, on walking down call
592  * relink_bad_predecessors() (This function stores the old in array
593  * to the link field and sets a new in array if arity of predecessors
594  * changes).
595  */
596 void remove_bad_predecessors(ir_graph *irg) {
597         panic("Fix backedge handling first");
598         irg_walk_graph(irg, firm_clear_link, relink_bad_predecessors, NULL);
599 }
600
601
602 /*
603    __                      _  __ __
604   (_     __    o     _    | \/  |_
605   __)|_| | \_/ | \_/(/_   |_/\__|__
606
607   The following stuff implements a facility that automatically patches
608   registered ir_node pointers to the new node when a dead node elimination occurs.
609 */
610
611 struct _survive_dce_t {
612         struct obstack obst;
613         pmap *places;
614         pmap *new_places;
615         hook_entry_t dead_node_elim;
616         hook_entry_t dead_node_elim_subst;
617 };
618
619 typedef struct _survive_dce_list_t {
620         struct _survive_dce_list_t *next;
621         ir_node **place;
622 } survive_dce_list_t;
623
624 static void dead_node_hook(void *context, ir_graph *irg, int start) {
625         survive_dce_t *sd = context;
626         (void) irg;
627
628         /* Create a new map before the dead node elimination is performed. */
629         if (start) {
630                 sd->new_places = pmap_create_ex(pmap_count(sd->places));
631         } else {
632                 /* Patch back all nodes if dead node elimination is over and something is to be done. */
633                 pmap_destroy(sd->places);
634                 sd->places     = sd->new_places;
635                 sd->new_places = NULL;
636         }
637 }
638
639 /**
640  * Hook called when dead node elimination replaces old by nw.
641  */
642 static void dead_node_subst_hook(void *context, ir_graph *irg, ir_node *old, ir_node *nw) {
643         survive_dce_t *sd = context;
644         survive_dce_list_t *list = pmap_get(sd->places, old);
645         (void) irg;
646
647         /* If the node is to be patched back, write the new address to all registered locations. */
648         if (list) {
649                 survive_dce_list_t *p;
650
651                 for (p = list; p; p = p->next)
652                         *(p->place) = nw;
653
654                 pmap_insert(sd->new_places, nw, list);
655         }
656 }
657
658 /**
659  * Make a new Survive DCE environment.
660  */
661 survive_dce_t *new_survive_dce(void) {
662         survive_dce_t *res = xmalloc(sizeof(res[0]));
663         obstack_init(&res->obst);
664         res->places     = pmap_create();
665         res->new_places = NULL;
666
667         res->dead_node_elim.hook._hook_dead_node_elim = dead_node_hook;
668         res->dead_node_elim.context                   = res;
669         res->dead_node_elim.next                      = NULL;
670
671         res->dead_node_elim_subst.hook._hook_dead_node_elim_subst = dead_node_subst_hook;
672         res->dead_node_elim_subst.context = res;
673         res->dead_node_elim_subst.next    = NULL;
674
675 #ifndef FIRM_ENABLE_HOOKS
676         assert(0 && "need hooks enabled");
677 #endif
678
679         register_hook(hook_dead_node_elim, &res->dead_node_elim);
680         register_hook(hook_dead_node_elim_subst, &res->dead_node_elim_subst);
681         return res;
682 }
683
684 /**
685  * Free a Survive DCE environment.
686  */
687 void free_survive_dce(survive_dce_t *sd) {
688         obstack_free(&sd->obst, NULL);
689         pmap_destroy(sd->places);
690         unregister_hook(hook_dead_node_elim, &sd->dead_node_elim);
691         unregister_hook(hook_dead_node_elim_subst, &sd->dead_node_elim_subst);
692         xfree(sd);
693 }
694
695 /**
696  * Register a node pointer to be patched upon DCE.
697  * When DCE occurs, the node pointer specified by @p place will be
698  * patched to the new address of the node it is pointing to.
699  *
700  * @param sd    The Survive DCE environment.
701  * @param place The address of the node pointer.
702  */
703 void survive_dce_register_irn(survive_dce_t *sd, ir_node **place) {
704         if (*place != NULL) {
705                 ir_node *irn      = *place;
706                 survive_dce_list_t *curr = pmap_get(sd->places, irn);
707                 survive_dce_list_t *nw   = obstack_alloc(&sd->obst, sizeof(nw[0]));
708
709                 nw->next  = curr;
710                 nw->place = place;
711
712                 pmap_insert(sd->places, irn, nw);
713         }
714 }
715
716 /*--------------------------------------------------------------------*/
717 /*  Functionality for inlining                                         */
718 /*--------------------------------------------------------------------*/
719
720 /**
721  * Copy node for inlineing.  Updates attributes that change when
722  * inlineing but not for dead node elimination.
723  *
724  * Copies the node by calling copy_node() and then updates the entity if
725  * it's a local one.  env must be a pointer of the frame type of the
726  * inlined procedure. The new entities must be in the link field of
727  * the entities.
728  */
729 static INLINE void
730 copy_node_inline(ir_node *n, void *env) {
731         ir_node *nn;
732         ir_type *frame_tp = (ir_type *)env;
733
734         copy_node(n, NULL);
735         if (is_Sel(n)) {
736                 nn = get_new_node (n);
737                 assert(is_Sel(nn));
738                 if (get_entity_owner(get_Sel_entity(n)) == frame_tp) {
739                         set_Sel_entity(nn, get_entity_link(get_Sel_entity(n)));
740                 }
741         } else if (is_Block(n)) {
742                 nn = get_new_node (n);
743                 nn->attr.block.irg = current_ir_graph;
744         }
745 }
746
747 /**
748  * Walker: checks if P_value_arg_base is used.
749  */
750 static void find_addr(ir_node *node, void *env) {
751         int *allow_inline = env;
752         if (is_Proj(node) &&
753                         is_Start(get_Proj_pred(node)) &&
754                         get_Proj_proj(node) == pn_Start_P_value_arg_base) {
755                 *allow_inline = 0;
756         } else if (is_Alloc(node) && get_Alloc_where(node) == stack_alloc) {
757                 /* From GCC:
758                  * Refuse to inline alloca call unless user explicitly forced so as this
759                  * may change program's memory overhead drastically when the function
760                  * using alloca is called in loop.  In GCC present in SPEC2000 inlining
761                  * into schedule_block cause it to require 2GB of ram instead of 256MB.
762                  *
763                  * Sorryly this is true with our implementation also.
764                  * Moreover, we cannot differentiate between alloca() and VLA yet, so this
765                  * disables inlining of functions using VLA (with are completely save).
766                  *
767                  * 2 Solutions:
768                  * - add a flag to the Alloc node for "real" alloca() calls
769                  * - add a new Stack-Restore node at the end of a function using alloca()
770                  */
771                 *allow_inline = 0;
772         }
773 }
774
775 /**
776  * Check if we can inline a given call.
777  * Currently, we cannot inline two cases:
778  * - call with compound arguments
779  * - graphs that take the address of a parameter
780  *
781  * check these conditions here
782  */
783 static int can_inline(ir_node *call, ir_graph *called_graph) {
784         ir_type *call_type = get_Call_type(call);
785         int params, ress, i, res;
786         assert(is_Method_type(call_type));
787
788         params = get_method_n_params(call_type);
789         ress   = get_method_n_ress(call_type);
790
791         /* check parameters for compound arguments */
792         for (i = 0; i < params; ++i) {
793                 ir_type *p_type = get_method_param_type(call_type, i);
794
795                 if (is_compound_type(p_type))
796                         return 0;
797         }
798
799         /* check results for compound arguments */
800         for (i = 0; i < ress; ++i) {
801                 ir_type *r_type = get_method_res_type(call_type, i);
802
803                 if (is_compound_type(r_type))
804                         return 0;
805         }
806
807         res = 1;
808         irg_walk_graph(called_graph, find_addr, NULL, &res);
809
810         return res;
811 }
812
813 enum exc_mode {
814         exc_handler    = 0, /**< There is a handler. */
815         exc_to_end     = 1, /**< Branches to End. */
816         exc_no_handler = 2  /**< Exception handling not represented. */
817 };
818
819 /* Inlines a method at the given call site. */
820 int inline_method(ir_node *call, ir_graph *called_graph) {
821         ir_node             *pre_call;
822         ir_node             *post_call, *post_bl;
823         ir_node             *in[pn_Start_max];
824         ir_node             *end, *end_bl, *block;
825         ir_node             **res_pred;
826         ir_node             **cf_pred;
827         ir_node             **args_in;
828         ir_node             *ret, *phi;
829         int                 arity, n_ret, n_exc, n_res, i, n, j, rem_opt, irn_arity, n_params;
830         enum exc_mode       exc_handling;
831         ir_type             *called_frame, *curr_frame, *mtp, *ctp;
832         ir_entity           *ent;
833         ir_graph            *rem, *irg;
834         irg_inline_property prop = get_irg_inline_property(called_graph);
835
836         if (prop == irg_inline_forbidden)
837                 return 0;
838
839         ent = get_irg_entity(called_graph);
840
841         mtp = get_entity_type(ent);
842         ctp = get_Call_type(call);
843         if (get_method_n_params(mtp) > get_method_n_params(ctp)) {
844                 /* this is a bad feature of C: without a prototype, we can can call a function with less
845                 parameters than needed. Currently we don't support this, although it would be
846                 to use Unknown than. */
847                 return 0;
848         }
849
850         /* Argh, compiling C has some bad consequences:
851            the call type AND the method type might be different.
852            It is implementation defendant what happens in that case.
853            We support inlining, if the bitsize of the types matches AND
854            the same arithmetic is used. */
855         n_params = get_method_n_params(mtp);
856         for (i = n_params - 1; i >= 0; --i) {
857                 ir_type *param_tp = get_method_param_type(mtp, i);
858                 ir_type *arg_tp   = get_method_param_type(ctp, i);
859
860                 if (param_tp != arg_tp) {
861                         ir_mode *pmode = get_type_mode(param_tp);
862                         ir_mode *amode = get_type_mode(arg_tp);
863
864                         if (pmode == NULL || amode == NULL)
865                                 return 0;
866                         if (get_mode_size_bits(pmode) != get_mode_size_bits(amode))
867                                 return 0;
868                         if (get_mode_arithmetic(pmode) != get_mode_arithmetic(amode))
869                                 return 0;
870                         /* otherwise we can simply "reinterpret" the bits */
871                 }
872         }
873
874         irg = get_irn_irg(call);
875
876         /*
877          * We cannot inline a recursive call. The graph must be copied before
878          * the call the inline_method() using create_irg_copy().
879          */
880         if (called_graph == irg)
881                 return 0;
882
883         /*
884          * currently, we cannot inline two cases:
885          * - call with compound arguments
886          * - graphs that take the address of a parameter
887          */
888         if (! can_inline(call, called_graph))
889                 return 0;
890
891         rem = current_ir_graph;
892         current_ir_graph = irg;
893
894         DB((dbg, LEVEL_1, "Inlining %+F(%+F) into %+F\n", call, called_graph, irg));
895
896         /* --  Turn off optimizations, this can cause problems when allocating new nodes. -- */
897         rem_opt = get_opt_optimize();
898         set_optimize(0);
899
900         /* Handle graph state */
901         assert(get_irg_phase_state(irg) != phase_building);
902         assert(get_irg_pinned(irg) == op_pin_state_pinned);
903         assert(get_irg_pinned(called_graph) == op_pin_state_pinned);
904         set_irg_outs_inconsistent(irg);
905         set_irg_extblk_inconsistent(irg);
906         set_irg_doms_inconsistent(irg);
907         set_irg_loopinfo_inconsistent(irg);
908         set_irg_callee_info_state(irg, irg_callee_info_inconsistent);
909
910         /* -- Check preconditions -- */
911         assert(is_Call(call));
912
913         /* here we know we WILL inline, so inform the statistics */
914         hook_inline(call, called_graph);
915
916         /* -- Decide how to handle exception control flow: Is there a handler
917            for the Call node, or do we branch directly to End on an exception?
918            exc_handling:
919            0 There is a handler.
920            1 Branches to End.
921            2 Exception handling not represented in Firm. -- */
922         {
923                 ir_node *proj, *Mproj = NULL, *Xproj = NULL;
924                 for (proj = get_irn_link(call); proj; proj = get_irn_link(proj)) {
925                         long proj_nr = get_Proj_proj(proj);
926                         if (proj_nr == pn_Call_X_except) Xproj = proj;
927                         if (proj_nr == pn_Call_M_except) Mproj = proj;
928                 }
929                 if      (Mproj) { assert(Xproj); exc_handling = exc_handler; } /*  Mproj           */
930                 else if (Xproj) {                exc_handling = exc_to_end; } /* !Mproj &&  Xproj   */
931                 else            {                exc_handling = exc_no_handler; } /* !Mproj && !Xproj   */
932         }
933
934         /* create the argument tuple */
935         NEW_ARR_A(ir_type *, args_in, n_params);
936
937         block = get_nodes_block(call);
938         for (i = n_params - 1; i >= 0; --i) {
939                 ir_node *arg      = get_Call_param(call, i);
940                 ir_type *param_tp = get_method_param_type(mtp, i);
941                 ir_mode *mode     = get_type_mode(param_tp);
942
943                 if (mode != get_irn_mode(arg)) {
944                         arg = new_r_Conv(irg, block, arg, mode);
945                 }
946                 args_in[i] = arg;
947         }
948
949         /* --
950            the procedure and later replaces the Start node of the called graph.
951            Post_call is the old Call node and collects the results of the called
952            graph. Both will end up being a tuple.  -- */
953         post_bl = get_nodes_block(call);
954         set_irg_current_block(irg, post_bl);
955         /* XxMxPxPxPxT of Start + parameter of Call */
956         in[pn_Start_X_initial_exec]   = new_Jmp();
957         in[pn_Start_M]                = get_Call_mem(call);
958         in[pn_Start_P_frame_base]     = get_irg_frame(irg);
959         in[pn_Start_P_tls]            = get_irg_tls(irg);
960         in[pn_Start_T_args]           = new_Tuple(n_params, args_in);
961         /* in[pn_Start_P_value_arg_base] = ??? */
962         assert(pn_Start_P_value_arg_base == pn_Start_max - 1 && "pn_Start_P_value_arg_base not supported, fix");
963         pre_call = new_Tuple(pn_Start_max - 1, in);
964         post_call = call;
965
966         /* --
967            The new block gets the ins of the old block, pre_call and all its
968            predecessors and all Phi nodes. -- */
969         part_block(pre_call);
970
971         /* -- Prepare state for dead node elimination -- */
972         /* Visited flags in calling irg must be >= flag in called irg.
973            Else walker and arity computation will not work. */
974         if (get_irg_visited(irg) <= get_irg_visited(called_graph))
975                 set_irg_visited(irg, get_irg_visited(called_graph) + 1);
976         if (get_irg_block_visited(irg) < get_irg_block_visited(called_graph))
977                 set_irg_block_visited(irg, get_irg_block_visited(called_graph));
978         /* Set pre_call as new Start node in link field of the start node of
979            calling graph and pre_calls block as new block for the start block
980            of calling graph.
981            Further mark these nodes so that they are not visited by the
982            copying. */
983         set_irn_link(get_irg_start(called_graph), pre_call);
984         set_irn_visited(get_irg_start(called_graph), get_irg_visited(irg));
985         set_irn_link(get_irg_start_block(called_graph), get_nodes_block(pre_call));
986         set_irn_visited(get_irg_start_block(called_graph), get_irg_visited(irg));
987         set_irn_link(get_irg_bad(called_graph), get_irg_bad(irg));
988         set_irn_visited(get_irg_bad(called_graph), get_irg_visited(irg));
989
990         /* Initialize for compaction of in arrays */
991         inc_irg_block_visited(irg);
992
993         /* -- Replicate local entities of the called_graph -- */
994         /* copy the entities. */
995         called_frame = get_irg_frame_type(called_graph);
996         curr_frame   = get_irg_frame_type(irg);
997         for (i = 0, n = get_class_n_members(called_frame); i < n; ++i) {
998                 ir_entity *new_ent, *old_ent;
999                 old_ent = get_class_member(called_frame, i);
1000                 new_ent = copy_entity_own(old_ent, curr_frame);
1001                 set_entity_link(old_ent, new_ent);
1002         }
1003
1004         /* visited is > than that of called graph.  With this trick visited will
1005            remain unchanged so that an outer walker, e.g., searching the call nodes
1006             to inline, calling this inline will not visit the inlined nodes. */
1007         set_irg_visited(irg, get_irg_visited(irg)-1);
1008
1009         /* -- Performing dead node elimination inlines the graph -- */
1010         /* Copies the nodes to the obstack of current_ir_graph. Updates links to new
1011            entities. */
1012         irg_walk(get_irg_end(called_graph), copy_node_inline, copy_preds,
1013                  get_irg_frame_type(called_graph));
1014
1015         /* Repair called_graph */
1016         set_irg_visited(called_graph, get_irg_visited(irg));
1017         set_irg_block_visited(called_graph, get_irg_block_visited(irg));
1018         set_Block_block_visited(get_irg_start_block(called_graph), 0);
1019
1020         /* -- Merge the end of the inlined procedure with the call site -- */
1021         /* We will turn the old Call node into a Tuple with the following
1022            predecessors:
1023            -1:  Block of Tuple.
1024            0: Phi of all Memories of Return statements.
1025            1: Jmp from new Block that merges the control flow from all exception
1026            predecessors of the old end block.
1027            2: Tuple of all arguments.
1028            3: Phi of Exception memories.
1029            In case the old Call directly branches to End on an exception we don't
1030            need the block merging all exceptions nor the Phi of the exception
1031            memories.
1032         */
1033
1034         /* -- Precompute some values -- */
1035         end_bl = get_new_node(get_irg_end_block(called_graph));
1036         end = get_new_node(get_irg_end(called_graph));
1037         arity = get_irn_arity(end_bl);    /* arity = n_exc + n_ret  */
1038         n_res = get_method_n_ress(get_Call_type(call));
1039
1040         res_pred = xmalloc(n_res * sizeof(*res_pred));
1041         cf_pred  = xmalloc(arity * sizeof(*res_pred));
1042
1043         set_irg_current_block(irg, post_bl); /* just to make sure */
1044
1045         /* -- archive keepalives -- */
1046         irn_arity = get_irn_arity(end);
1047         for (i = 0; i < irn_arity; i++) {
1048                 ir_node *ka = get_End_keepalive(end, i);
1049                 if (! is_Bad(ka))
1050                         add_End_keepalive(get_irg_end(irg), ka);
1051         }
1052
1053         /* The new end node will die.  We need not free as the in array is on the obstack:
1054            copy_node() only generated 'D' arrays. */
1055
1056         /* -- Replace Return nodes by Jump nodes. -- */
1057         n_ret = 0;
1058         for (i = 0; i < arity; i++) {
1059                 ir_node *ret;
1060                 ret = get_irn_n(end_bl, i);
1061                 if (is_Return(ret)) {
1062                         cf_pred[n_ret] = new_r_Jmp(irg, get_nodes_block(ret));
1063                         n_ret++;
1064                 }
1065         }
1066         set_irn_in(post_bl, n_ret, cf_pred);
1067
1068         /* -- Build a Tuple for all results of the method.
1069            Add Phi node if there was more than one Return.  -- */
1070         turn_into_tuple(post_call, pn_Call_max);
1071         /* First the Memory-Phi */
1072         n_ret = 0;
1073         for (i = 0; i < arity; i++) {
1074                 ret = get_irn_n(end_bl, i);
1075                 if (is_Return(ret)) {
1076                         cf_pred[n_ret] = get_Return_mem(ret);
1077                         n_ret++;
1078                 }
1079         }
1080         phi = new_Phi(n_ret, cf_pred, mode_M);
1081         set_Tuple_pred(call, pn_Call_M_regular, phi);
1082         /* Conserve Phi-list for further inlinings -- but might be optimized */
1083         if (get_nodes_block(phi) == post_bl) {
1084                 set_irn_link(phi, get_irn_link(post_bl));
1085                 set_irn_link(post_bl, phi);
1086         }
1087         /* Now the real results */
1088         if (n_res > 0) {
1089                 for (j = 0; j < n_res; j++) {
1090                         n_ret = 0;
1091                         for (i = 0; i < arity; i++) {
1092                                 ret = get_irn_n(end_bl, i);
1093                                 if (is_Return(ret)) {
1094                                         cf_pred[n_ret] = get_Return_res(ret, j);
1095                                         n_ret++;
1096                                 }
1097                         }
1098                         if (n_ret > 0)
1099                                 phi = new_Phi(n_ret, cf_pred, get_irn_mode(cf_pred[0]));
1100                         else
1101                                 phi = new_Bad();
1102                         res_pred[j] = phi;
1103                         /* Conserve Phi-list for further inlinings -- but might be optimized */
1104                         if (get_nodes_block(phi) == post_bl) {
1105                                 set_Phi_next(phi, get_Block_phis(post_bl));
1106                                 set_Block_phis(post_bl, phi);
1107                         }
1108                 }
1109                 set_Tuple_pred(call, pn_Call_T_result, new_Tuple(n_res, res_pred));
1110         } else {
1111                 set_Tuple_pred(call, pn_Call_T_result, new_Bad());
1112         }
1113         /* handle the regular call */
1114         set_Tuple_pred(call, pn_Call_X_regular, new_Jmp());
1115
1116         /* For now, we cannot inline calls with value_base */
1117         set_Tuple_pred(call, pn_Call_P_value_res_base, new_Bad());
1118
1119         /* Finally the exception control flow.
1120            We have two (three) possible situations:
1121            First if the Call branches to an exception handler: We need to add a Phi node to
1122            collect the memory containing the exception objects.  Further we need
1123            to add another block to get a correct representation of this Phi.  To
1124            this block we add a Jmp that resolves into the X output of the Call
1125            when the Call is turned into a tuple.
1126            Second the Call branches to End, the exception is not handled.  Just
1127            add all inlined exception branches to the End node.
1128            Third: there is no Exception edge at all. Handle as case two. */
1129         if (exc_handling == exc_handler) {
1130                 n_exc = 0;
1131                 for (i = 0; i < arity; i++) {
1132                         ir_node *ret, *irn;
1133                         ret = get_irn_n(end_bl, i);
1134                         irn = skip_Proj(ret);
1135                         if (is_fragile_op(irn) || is_Raise(irn)) {
1136                                 cf_pred[n_exc] = ret;
1137                                 ++n_exc;
1138                         }
1139                 }
1140                 if (n_exc > 0) {
1141                         new_Block(n_exc, cf_pred);      /* watch it: current_block is changed! */
1142                         set_Tuple_pred(call, pn_Call_X_except, new_Jmp());
1143                         /* The Phi for the memories with the exception objects */
1144                         n_exc = 0;
1145                         for (i = 0; i < arity; i++) {
1146                                 ir_node *ret;
1147                                 ret = skip_Proj(get_irn_n(end_bl, i));
1148                                 if (is_Call(ret)) {
1149                                         cf_pred[n_exc] = new_r_Proj(irg, get_nodes_block(ret), ret, mode_M, 3);
1150                                         n_exc++;
1151                                 } else if (is_fragile_op(ret)) {
1152                                         /* We rely that all cfops have the memory output at the same position. */
1153                                         cf_pred[n_exc] = new_r_Proj(irg, get_nodes_block(ret), ret, mode_M, 0);
1154                                         n_exc++;
1155                                 } else if (is_Raise(ret)) {
1156                                         cf_pred[n_exc] = new_r_Proj(irg, get_nodes_block(ret), ret, mode_M, 1);
1157                                         n_exc++;
1158                                 }
1159                         }
1160                         set_Tuple_pred(call, pn_Call_M_except, new_Phi(n_exc, cf_pred, mode_M));
1161                 } else {
1162                         set_Tuple_pred(call, pn_Call_X_except, new_Bad());
1163                         set_Tuple_pred(call, pn_Call_M_except, new_Bad());
1164                 }
1165         } else {
1166                 ir_node *main_end_bl;
1167                 int main_end_bl_arity;
1168                 ir_node **end_preds;
1169
1170                 /* assert(exc_handling == 1 || no exceptions. ) */
1171                 n_exc = 0;
1172                 for (i = 0; i < arity; i++) {
1173                         ir_node *ret = get_irn_n(end_bl, i);
1174                         ir_node *irn = skip_Proj(ret);
1175
1176                         if (is_fragile_op(irn) || is_Raise(irn)) {
1177                                 cf_pred[n_exc] = ret;
1178                                 n_exc++;
1179                         }
1180                 }
1181                 main_end_bl = get_irg_end_block(irg);
1182                 main_end_bl_arity = get_irn_arity(main_end_bl);
1183                 end_preds =  xmalloc((n_exc + main_end_bl_arity) * sizeof(*end_preds));
1184
1185                 for (i = 0; i < main_end_bl_arity; ++i)
1186                         end_preds[i] = get_irn_n(main_end_bl, i);
1187                 for (i = 0; i < n_exc; ++i)
1188                         end_preds[main_end_bl_arity + i] = cf_pred[i];
1189                 set_irn_in(main_end_bl, n_exc + main_end_bl_arity, end_preds);
1190                 set_Tuple_pred(call, pn_Call_X_except,  new_Bad());
1191                 set_Tuple_pred(call, pn_Call_M_except,  new_Bad());
1192                 free(end_preds);
1193         }
1194         free(res_pred);
1195         free(cf_pred);
1196
1197         /* --  Turn CSE back on. -- */
1198         set_optimize(rem_opt);
1199         current_ir_graph = rem;
1200
1201         return 1;
1202 }
1203
1204 /********************************************************************/
1205 /* Apply inlineing to small methods.                                */
1206 /********************************************************************/
1207
1208 static struct obstack  temp_obst;
1209
1210 /** Represents a possible inlinable call in a graph. */
1211 typedef struct _call_entry call_entry;
1212 struct _call_entry {
1213         ir_node    *call;      /**< the Call node */
1214         ir_graph   *callee;    /**< the callee IR-graph called here */
1215         call_entry *next;      /**< for linking the next one */
1216         int        loop_depth; /**< the loop depth of this call */
1217 };
1218
1219 /**
1220  * environment for inlining small irgs
1221  */
1222 typedef struct _inline_env_t {
1223         struct obstack obst;  /**< an obstack where call_entries are allocated on. */
1224         call_entry *head;     /**< the head of the call entry list */
1225         call_entry *tail;     /**< the tail of the call entry list */
1226 } inline_env_t;
1227
1228 /**
1229  * Returns the irg called from a Call node. If the irg is not
1230  * known, NULL is returned.
1231  *
1232  * @param call  the call node
1233  */
1234 static ir_graph *get_call_called_irg(ir_node *call) {
1235         ir_node *addr;
1236
1237         addr = get_Call_ptr(call);
1238         if (is_Global(addr)) {
1239                 ir_entity *ent = get_Global_entity(addr);
1240                 return get_entity_irg(ent);
1241         }
1242
1243         return NULL;
1244 }
1245
1246 /**
1247  * Walker: Collect all calls to known graphs inside a graph.
1248  */
1249 static void collect_calls(ir_node *call, void *env) {
1250         if (is_Call(call)) {
1251                 ir_graph *called_irg = get_call_called_irg(call);
1252
1253                 if (called_irg != NULL) {
1254                         /* The Call node calls a locally defined method.  Remember to inline. */
1255                         inline_env_t *ienv  = env;
1256                         call_entry   *entry = obstack_alloc(&ienv->obst, sizeof(*entry));
1257                         entry->call       = call;
1258                         entry->callee     = called_irg;
1259                         entry->next       = NULL;
1260                         entry->loop_depth = 0;
1261
1262                         if (ienv->tail == NULL)
1263                                 ienv->head = entry;
1264                         else
1265                                 ienv->tail->next = entry;
1266                         ienv->tail = entry;
1267                 }
1268         }
1269 }
1270
1271 /**
1272  * Inlines all small 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_small_irgs(ir_graph *irg, int size) {
1280         ir_graph *rem = current_ir_graph;
1281         inline_env_t env;
1282         call_entry *entry;
1283
1284         current_ir_graph = irg;
1285         /* Handle graph state */
1286         assert(get_irg_phase_state(irg) != phase_building);
1287         free_callee_info(irg);
1288
1289         /* Find Call nodes to inline.
1290            (We can not inline during a walk of the graph, as inlineing the same
1291            method several times changes the visited flag of the walked graph:
1292            after the first inlineing visited of the callee equals visited of
1293            the caller.  With the next inlineing both are increased.) */
1294         obstack_init(&env.obst);
1295         env.head = env.tail = NULL;
1296         irg_walk_graph(irg, NULL, collect_calls, &env);
1297
1298         if (env.head != NULL) {
1299                 /* There are calls to inline */
1300                 collect_phiprojs(irg);
1301                 for (entry = env.head; entry != NULL; entry = entry->next) {
1302                         ir_graph *callee = entry->callee;
1303                         if (((_obstack_memory_used(callee->obst) - (int)obstack_room(callee->obst)) < size) ||
1304                             (get_irg_inline_property(callee) >= irg_inline_forced)) {
1305                                 inline_method(entry->call, callee);
1306                         }
1307                 }
1308         }
1309         obstack_free(&env.obst, NULL);
1310         current_ir_graph = rem;
1311 }
1312
1313 /**
1314  * Environment for inlining irgs.
1315  */
1316 typedef struct {
1317         int n_nodes;             /**< Number of nodes in graph except Id, Tuple, Proj, Start, End. */
1318         int n_blocks;            /**< Number of Blocks in graph without Start and End block. */
1319         int n_nodes_orig;        /**< for statistics */
1320         int n_call_nodes;        /**< Number of Call nodes in the graph. */
1321         int n_call_nodes_orig;   /**< for statistics */
1322         int n_callers;           /**< Number of known graphs that call this graphs. */
1323         int n_callers_orig;      /**< for statistics */
1324         unsigned got_inline:1;   /**< Set, if at least one call inside this graph was inlined. */
1325         unsigned local_vars:1;   /**< Set, if a inlined function gets the address of an inlined variable. */
1326         unsigned recursive:1;    /**< Set, if this function is self recursive. */
1327         call_entry *call_head;   /**< The head of the list of all call nodes in this graph. */
1328         call_entry *call_tail;   /**< The tail of the list of all call nodes in this graph .*/
1329         unsigned *local_weights; /**< Once allocated, the beneficial weight for transmitting local addresses. */
1330 } inline_irg_env;
1331
1332 /**
1333  * Allocate a new environment for inlining.
1334  */
1335 static inline_irg_env *alloc_inline_irg_env(void) {
1336         inline_irg_env *env    = obstack_alloc(&temp_obst, sizeof(*env));
1337         env->n_nodes           = -2; /* do not count count Start, End */
1338         env->n_blocks          = -2; /* do not count count Start, End Block */
1339         env->n_nodes_orig      = -2; /* do not count Start, End */
1340         env->call_head         = NULL;
1341         env->call_tail         = NULL;
1342         env->n_call_nodes      = 0;
1343         env->n_call_nodes_orig = 0;
1344         env->n_callers         = 0;
1345         env->n_callers_orig    = 0;
1346         env->got_inline        = 0;
1347         env->local_vars        = 0;
1348         env->recursive         = 0;
1349         env->local_weights     = NULL;
1350         return env;
1351 }
1352
1353 typedef struct walker_env {
1354         inline_irg_env *x;     /**< the inline environment */
1355         call_entry *last_call; /**< points to the last inserted call */
1356         char ignore_runtime;   /**< the ignore runtime flag */
1357         char ignore_callers;   /**< if set, do change callers data */
1358 } wenv_t;
1359
1360 /**
1361  * post-walker: collect all calls in the inline-environment
1362  * of a graph and sum some statistics.
1363  */
1364 static void collect_calls2(ir_node *call, void *ctx) {
1365         wenv_t         *env = ctx;
1366         inline_irg_env *x = env->x;
1367         ir_opcode      code = get_irn_opcode(call);
1368         ir_graph       *callee;
1369         call_entry     *entry;
1370
1371         /* count meaningful nodes in irg */
1372         if (code != iro_Proj && code != iro_Tuple && code != iro_Sync) {
1373                 if (code != iro_Block) {
1374                         ++x->n_nodes;
1375                         ++x->n_nodes_orig;
1376                 } else {
1377                         ++x->n_blocks;
1378                 }
1379         }
1380
1381         if (code != iro_Call) return;
1382
1383         /* check, if it's a runtime call */
1384         if (env->ignore_runtime) {
1385                 ir_node *symc = get_Call_ptr(call);
1386
1387                 if (is_Global(symc)) {
1388                         ir_entity *ent = get_Global_entity(symc);
1389
1390                         if (get_entity_additional_properties(ent) & mtp_property_runtime)
1391                                 return;
1392                 }
1393         }
1394
1395         /* collect all call nodes */
1396         ++x->n_call_nodes;
1397         ++x->n_call_nodes_orig;
1398
1399         callee = get_call_called_irg(call);
1400         if (callee != NULL) {
1401                 if (! env->ignore_callers) {
1402                         inline_irg_env *callee_env = get_irg_link(callee);
1403                         /* count all static callers */
1404                         ++callee_env->n_callers;
1405                         ++callee_env->n_callers_orig;
1406                 }
1407                 if (callee == current_ir_graph)
1408                         x->recursive = 1;
1409
1410                 /* link it in the list of possible inlinable entries */
1411                 entry = obstack_alloc(&temp_obst, sizeof(*entry));
1412                 entry->call       = call;
1413                 entry->callee     = callee;
1414                 entry->next       = NULL;
1415                 entry->loop_depth = get_irn_loop(get_nodes_block(call))->depth;
1416
1417                 /* note: we use call_tail here as a pointer to the last inserted */
1418                 if (x->call_head == NULL) {
1419                         x->call_head = entry;
1420                 } else {
1421                         if (entry->loop_depth == env->last_call->loop_depth) {
1422                                 /* same depth as the last one, enqueue after it */
1423                                 entry->next          = env->last_call->next;
1424                                 env->last_call->next = entry;
1425                         } else if (entry->loop_depth > x->call_head->loop_depth) {
1426                                 /* put first */
1427                                 entry->next  = x->call_head;
1428                                 x->call_head = entry;
1429                         } else {
1430                                 /* search the insertion point */
1431                                 call_entry *p;
1432
1433                                 for (p = x->call_head; p->next != NULL; p = p->next)
1434                                         if (entry->loop_depth > p->next->loop_depth)
1435                                                 break;
1436                                 entry->next = p->next;
1437                                 p->next     = entry;
1438                         }
1439                 }
1440                 env->last_call = entry;
1441                 if (entry->next == NULL) {
1442                         /* keep tail up to date */
1443                         x->call_tail = entry;
1444                 }
1445         }
1446 }
1447
1448 /**
1449  * Returns TRUE if the number of callers is 0 in the irg's environment,
1450  * hence this irg is a leave.
1451  */
1452 INLINE static int is_leave(ir_graph *irg) {
1453         inline_irg_env *env = get_irg_link(irg);
1454         return env->n_call_nodes == 0;
1455 }
1456
1457 /**
1458  * Returns TRUE if the number of nodes in the callee is
1459  * smaller then size in the irg's environment.
1460  */
1461 INLINE static int is_smaller(ir_graph *callee, int size) {
1462         inline_irg_env *env = get_irg_link(callee);
1463         return env->n_nodes < size;
1464 }
1465
1466 /**
1467  * Append the nodes of the list src to the nodes of the list in environment dst.
1468  */
1469 static void append_call_list(inline_irg_env *dst, call_entry *src) {
1470         call_entry *entry, *nentry;
1471
1472         /* Note that the src list points to Call nodes in the inlined graph, but
1473            we need Call nodes in our graph. Luckily the inliner leaves this information
1474            in the link field. */
1475         for (entry = src; entry != NULL; entry = entry->next) {
1476                 nentry = obstack_alloc(&temp_obst, sizeof(*nentry));
1477                 nentry->call         = get_irn_link(entry->call);
1478                 nentry->callee       = entry->callee;
1479                 nentry->next         = NULL;
1480                 nentry->loop_depth   = entry->loop_depth;
1481                 dst->call_tail->next = nentry;
1482                 dst->call_tail       = nentry;
1483         }
1484 }
1485
1486 /**
1487  * Add the nodes of the list src in front to the nodes of the list dst.
1488  */
1489 static call_entry *replace_entry_by_call_list(call_entry *dst, call_entry *src) {
1490         call_entry *entry, *nentry, *head, *tail;
1491
1492         /* Note that the src list points to Call nodes in the inlined graph, but
1493            we need Call nodes in our graph. Luckily the inliner leaves this information
1494            in the link field. */
1495         head = tail = NULL;
1496         for (entry = src; entry != NULL; entry = entry->next) {
1497                 nentry = obstack_alloc(&temp_obst, sizeof(*nentry));
1498                 nentry->call         = get_irn_link(entry->call);
1499                 nentry->callee       = entry->callee;
1500                 nentry->next         = NULL;
1501                 nentry->loop_depth   = entry->loop_depth + dst->loop_depth;
1502                 if (head == NULL)
1503                         head = nentry;
1504                 else
1505                         tail->next = nentry;
1506                 tail = nentry;
1507         }
1508         /* skip the head of dst */
1509         if (head != NULL) {
1510                 tail->next = dst->next;
1511         } else {
1512                 head = dst->next;
1513         }
1514         return head;
1515 }
1516
1517 /*
1518  * Inlines small leave methods at call sites where the called address comes
1519  * from a Const node that references the entity representing the called
1520  * method.
1521  * The size argument is a rough measure for the code size of the method:
1522  * Methods where the obstack containing the firm graph is smaller than
1523  * size are inlined.
1524  */
1525 void inline_leave_functions(int maxsize, int leavesize, int size, int ignore_runtime) {
1526         inline_irg_env   *env;
1527         ir_graph         *irg;
1528         int              i, n_irgs;
1529         ir_graph         *rem;
1530         int              did_inline;
1531         wenv_t           wenv;
1532         call_entry       *entry, *tail;
1533         const call_entry *centry;
1534         pmap             *copied_graphs;
1535         pmap_entry       *pm_entry;
1536
1537         rem = current_ir_graph;
1538         obstack_init(&temp_obst);
1539
1540         /* a map for the copied graphs, used to inline recursive calls */
1541         copied_graphs = pmap_create();
1542
1543         /* extend all irgs by a temporary data structure for inlining. */
1544         n_irgs = get_irp_n_irgs();
1545         for (i = 0; i < n_irgs; ++i)
1546                 set_irg_link(get_irp_irg(i), alloc_inline_irg_env());
1547
1548         /* Precompute information in temporary data structure. */
1549         wenv.ignore_runtime = ignore_runtime;
1550         wenv.ignore_callers = 0;
1551         for (i = 0; i < n_irgs; ++i) {
1552                 ir_graph *irg = get_irp_irg(i);
1553
1554                 assert(get_irg_phase_state(irg) != phase_building);
1555                 free_callee_info(irg);
1556
1557                 assure_cf_loop(irg);
1558                 wenv.x = get_irg_link(irg);
1559                 irg_walk_graph(irg, NULL, collect_calls2, &wenv);
1560         }
1561
1562         /* -- and now inline. -- */
1563
1564         /* Inline leaves recursively -- we might construct new leaves. */
1565         do {
1566                 did_inline = 0;
1567
1568                 for (i = 0; i < n_irgs; ++i) {
1569                         ir_node *call;
1570                         int phiproj_computed = 0;
1571
1572                         current_ir_graph = get_irp_irg(i);
1573                         env = (inline_irg_env *)get_irg_link(current_ir_graph);
1574
1575                         tail = NULL;
1576                         for (entry = env->call_head; entry != NULL; entry = entry->next) {
1577                                 ir_graph *callee;
1578
1579                                 if (env->n_nodes > maxsize) break;
1580
1581                                 call   = entry->call;
1582                                 callee = entry->callee;
1583
1584                                 if (is_leave(callee) && (
1585                                     is_smaller(callee, leavesize) || (get_irg_inline_property(callee) >= irg_inline_forced))) {
1586                                         if (!phiproj_computed) {
1587                                                 phiproj_computed = 1;
1588                                                 collect_phiprojs(current_ir_graph);
1589                                         }
1590                                         did_inline = inline_method(call, callee);
1591
1592                                         if (did_inline) {
1593                                                 inline_irg_env *callee_env = (inline_irg_env *)get_irg_link(callee);
1594
1595                                                 /* was inlined, must be recomputed */
1596                                                 phiproj_computed = 0;
1597
1598                                                 /* Do some statistics */
1599                                                 env->got_inline = 1;
1600                                                 --env->n_call_nodes;
1601                                                 env->n_nodes += callee_env->n_nodes;
1602                                                 --callee_env->n_callers;
1603
1604                                                 /* remove this call from the list */
1605                                                 if (tail != NULL)
1606                                                         tail->next = entry->next;
1607                                                 else
1608                                                         env->call_head = entry->next;
1609                                                 continue;
1610                                         }
1611                                 }
1612                                 tail = entry;
1613                         }
1614                         env->call_tail = tail;
1615                 }
1616         } while (did_inline);
1617
1618         /* inline other small functions. */
1619         for (i = 0; i < n_irgs; ++i) {
1620                 ir_node *call;
1621                 int phiproj_computed = 0;
1622
1623                 current_ir_graph = get_irp_irg(i);
1624                 env = (inline_irg_env *)get_irg_link(current_ir_graph);
1625
1626                 /* note that the list of possible calls is updated during the process */
1627                 tail = NULL;
1628                 for (entry = env->call_head; entry != NULL; entry = entry->next) {
1629                         ir_graph   *callee;
1630                         pmap_entry *e;
1631
1632                         call   = entry->call;
1633                         callee = entry->callee;
1634
1635                         e = pmap_find(copied_graphs, callee);
1636                         if (e != NULL) {
1637                                 /*
1638                                  * Remap callee if we have a copy.
1639                                  * FIXME: Should we do this only for recursive Calls ?
1640                                  */
1641                                 callee = e->value;
1642                         }
1643
1644                         if (((is_smaller(callee, size) && (env->n_nodes < maxsize)) ||    /* small function */
1645                                 (get_irg_inline_property(callee) >= irg_inline_forced))) {
1646                                 if (current_ir_graph == callee) {
1647                                         /*
1648                                          * Recursive call: we cannot directly inline because we cannot walk
1649                                          * the graph and change it. So we have to make a copy of the graph
1650                                          * first.
1651                                          */
1652
1653                                         inline_irg_env *callee_env;
1654                                         ir_graph       *copy;
1655
1656                                         /*
1657                                          * No copy yet, create one.
1658                                          * Note that recursive methods are never leaves, so it is sufficient
1659                                          * to test this condition here.
1660                                          */
1661                                         copy = create_irg_copy(callee);
1662
1663                                         /* create_irg_copy() destroys the Proj links, recompute them */
1664                                         phiproj_computed = 0;
1665
1666                                         /* allocate new environment */
1667                                         callee_env = alloc_inline_irg_env();
1668                                         set_irg_link(copy, callee_env);
1669
1670                                         assure_cf_loop(copy);
1671                                         wenv.x              = callee_env;
1672                                         wenv.ignore_callers = 1;
1673                                         irg_walk_graph(copy, NULL, collect_calls2, &wenv);
1674
1675                                         /*
1676                                          * Enter the entity of the original graph. This is needed
1677                                          * for inline_method(). However, note that ent->irg still points
1678                                          * to callee, NOT to copy.
1679                                          */
1680                                         set_irg_entity(copy, get_irg_entity(callee));
1681
1682                                         pmap_insert(copied_graphs, callee, copy);
1683                                         callee = copy;
1684
1685                                         /* we have only one caller: the original graph */
1686                                         callee_env->n_callers      = 1;
1687                                         callee_env->n_callers_orig = 1;
1688                                 }
1689                                 if (! phiproj_computed) {
1690                                         phiproj_computed = 1;
1691                                         collect_phiprojs(current_ir_graph);
1692                                 }
1693                                 did_inline = inline_method(call, callee);
1694                                 if (did_inline) {
1695                                         inline_irg_env *callee_env = (inline_irg_env *)get_irg_link(callee);
1696
1697                                         /* was inlined, must be recomputed */
1698                                         phiproj_computed = 0;
1699
1700                                         /* callee was inline. Append it's call list. */
1701                                         env->got_inline = 1;
1702                                         --env->n_call_nodes;
1703                                         append_call_list(env, callee_env->call_head);
1704                                         env->n_call_nodes += callee_env->n_call_nodes;
1705                                         env->n_nodes += callee_env->n_nodes;
1706                                         --callee_env->n_callers;
1707
1708                                         /* after we have inlined callee, all called methods inside callee
1709                                            are now called once more */
1710                                         for (centry = callee_env->call_head; centry != NULL; centry = centry->next) {
1711                                                 inline_irg_env *penv = get_irg_link(centry->callee);
1712                                                 ++penv->n_callers;
1713                                         }
1714
1715                                         /* remove this call from the list */
1716                                         if (tail != NULL)
1717                                                 tail->next = entry->next;
1718                                         else
1719                                                 env->call_head = entry->next;
1720                                         continue;
1721                                 }
1722                         }
1723                         tail = entry;
1724                 }
1725                 env->call_tail = tail;
1726         }
1727
1728         for (i = 0; i < n_irgs; ++i) {
1729                 irg = get_irp_irg(i);
1730                 env = (inline_irg_env *)get_irg_link(irg);
1731
1732                 if (env->got_inline) {
1733                         optimize_graph_df(irg);
1734                         optimize_cf(irg);
1735                 }
1736                 if (env->got_inline || (env->n_callers_orig != env->n_callers)) {
1737                         DB((dbg, LEVEL_1, "Nodes:%3d ->%3d, calls:%3d ->%3d, callers:%3d ->%3d, -- %s\n",
1738                         env->n_nodes_orig, env->n_nodes, env->n_call_nodes_orig, env->n_call_nodes,
1739                         env->n_callers_orig, env->n_callers,
1740                         get_entity_name(get_irg_entity(irg))));
1741                 }
1742         }
1743
1744         /* kill the copied graphs: we don't need them anymore */
1745         foreach_pmap(copied_graphs, pm_entry) {
1746                 ir_graph *copy = pm_entry->value;
1747
1748                 /* reset the entity, otherwise it will be deleted in the next step ... */
1749                 set_irg_entity(copy, NULL);
1750                 free_ir_graph(copy);
1751         }
1752         pmap_destroy(copied_graphs);
1753
1754         obstack_free(&temp_obst, NULL);
1755         current_ir_graph = rem;
1756 }
1757
1758 /**
1759  * Calculate the parameter weights for transmitting the address of a local variable.
1760  */
1761 static unsigned calc_method_local_weight(ir_node *arg) {
1762         int      i, j, k;
1763         unsigned v, weight = 0;
1764
1765         for (i = get_irn_n_outs(arg) - 1; i >= 0; --i) {
1766                 ir_node *succ = get_irn_out(arg, i);
1767
1768                 switch (get_irn_opcode(succ)) {
1769                 case iro_Load:
1770                 case iro_Store:
1771                         /* Loads and Store can be removed */
1772                         weight += 3;
1773                         break;
1774                 case iro_Sel:
1775                         /* check if all args are constant */
1776                         for (j = get_Sel_n_indexs(succ) - 1; j >= 0; --j) {
1777                                 ir_node *idx = get_Sel_index(succ, j);
1778                                 if (! is_Const(idx))
1779                                         return 0;
1780                         }
1781                         /* Check users on this Sel. Note: if a 0 is returned here, there was
1782                            some unsupported node. */
1783                         v = calc_method_local_weight(succ);
1784                         if (v == 0)
1785                                 return 0;
1786                         /* we can kill one Sel with constant indexes, this is cheap */
1787                         weight += v + 1;
1788                         break;
1789                 case iro_Id:
1790                         /* when looking backward we might find Id nodes */
1791                         weight += calc_method_local_weight(succ);
1792                         break;
1793                 case iro_Tuple:
1794                         /* unoptimized tuple */
1795                         for (j = get_Tuple_n_preds(succ) - 1; j >= 0; --j) {
1796                                 ir_node *pred = get_Tuple_pred(succ, j);
1797                                 if (pred == arg) {
1798                                         /* look for Proj(j) */
1799                                         for (k = get_irn_n_outs(succ) - 1; k >= 0; --k) {
1800                                                 ir_node *succ_succ = get_irn_out(succ, k);
1801                                                 if (is_Proj(succ_succ)) {
1802                                                         if (get_Proj_proj(succ_succ) == j) {
1803                                                                 /* found */
1804                                                                 weight += calc_method_local_weight(succ_succ);
1805                                                         }
1806                                                 } else {
1807                                                         /* this should NOT happen */
1808                                                         return 0;
1809                                                 }
1810                                         }
1811                                 }
1812                         }
1813                         break;
1814                 default:
1815                         /* any other node: unsupported yet or bad. */
1816                         return 0;
1817                 }
1818         }
1819         return weight;
1820 }
1821
1822 /**
1823  * Calculate the parameter weights for transmitting the address of a local variable.
1824  */
1825 static void analyze_irg_local_weights(inline_irg_env *env, ir_graph *irg) {
1826         ir_entity *ent = get_irg_entity(irg);
1827         ir_type  *mtp;
1828         int      nparams, i, proj_nr;
1829         ir_node  *irg_args, *arg;
1830
1831         mtp      = get_entity_type(ent);
1832         nparams  = get_method_n_params(mtp);
1833
1834         /* allocate a new array. currently used as 'analysed' flag */
1835         env->local_weights = NEW_ARR_D(unsigned, &temp_obst, nparams);
1836
1837         /* If the method haven't parameters we have nothing to do. */
1838         if (nparams <= 0)
1839                 return;
1840
1841         assure_irg_outs(irg);
1842         irg_args = get_irg_args(irg);
1843         for (i = get_irn_n_outs(irg_args) - 1; i >= 0; --i) {
1844                 arg     = get_irn_out(irg_args, i);
1845                 proj_nr = get_Proj_proj(arg);
1846                 env->local_weights[proj_nr] = calc_method_local_weight(arg);
1847         }
1848 }
1849
1850 /**
1851  * Calculate the benefice for transmitting an local variable address.
1852  * After inlining, the local variable might be transformed into a
1853  * SSA variable by scalar_replacement().
1854  */
1855 static unsigned get_method_local_adress_weight(ir_graph *callee, int pos) {
1856         inline_irg_env *env = get_irg_link(callee);
1857
1858         if (env->local_weights != NULL) {
1859                 if (pos < ARR_LEN(env->local_weights))
1860                         return env->local_weights[pos];
1861                 return 0;
1862         }
1863
1864         analyze_irg_local_weights(env, callee);
1865
1866         if (pos < ARR_LEN(env->local_weights))
1867                 return env->local_weights[pos];
1868         return 0;
1869 }
1870
1871 /**
1872  * calculate a benefice value for inlining the given call.
1873  */
1874 static int calc_inline_benefice(ir_node *call, ir_graph *callee, unsigned *local_adr) {
1875         ir_entity *ent = get_irg_entity(callee);
1876         ir_node   *frame_ptr;
1877         ir_type   *mtp;
1878         int       weight = 0;
1879         int       i, n_params, all_const;
1880         unsigned  cc, v;
1881
1882         inline_irg_env *curr_env, *callee_env;
1883
1884         if (get_entity_additional_properties(ent) & mtp_property_noreturn) {
1885                 /* do NOT inline noreturn calls */
1886                 return INT_MIN;
1887         }
1888
1889         /* costs for every passed parameter */
1890         n_params = get_Call_n_params(call);
1891         mtp      = get_entity_type(ent);
1892         cc       = get_method_calling_convention(mtp);
1893         if (cc & cc_reg_param) {
1894                 /* register parameter, smaller costs for register parameters */
1895                 int max_regs = cc & ~cc_bits;
1896
1897                 if (max_regs < n_params)
1898                         weight += max_regs * 2 + (n_params - max_regs) * 5;
1899                 else
1900                         weight += n_params * 2;
1901         } else {
1902                 /* parameters are passed an stack */
1903                 weight += 5 * n_params;
1904         }
1905
1906         /* constant parameters improve the benefice */
1907         frame_ptr = get_irg_frame(current_ir_graph);
1908         all_const = 1;
1909         for (i = 0; i < n_params; ++i) {
1910                 ir_node *param = get_Call_param(call, i);
1911
1912                 if (is_Const(param))
1913                         weight += get_method_param_weight(ent, i);
1914                 else {
1915                         all_const = 0;
1916                         if (is_SymConst(param))
1917                                 weight += get_method_param_weight(ent, i);
1918                         else if (is_Sel(param) && get_Sel_ptr(param) == frame_ptr) {
1919                                 /*
1920                                  * An address of a local variable is transmitted. After inlining,
1921                                  * scalar_replacement might be able to remove the local variable,
1922                                  * so honor this.
1923                                  */
1924                                 v = get_method_local_adress_weight(callee, i);
1925                                 weight += v;
1926                                 if (v > 0)
1927                                         *local_adr = 1;
1928                         }
1929                 }
1930         }
1931
1932         callee_env = get_irg_link(callee);
1933         if (get_entity_visibility(ent) == visibility_local &&
1934             callee_env->n_callers_orig == 1 &&
1935             callee != current_ir_graph) {
1936                 /* we are the only caller, give big bonus */
1937                 weight += 5000;
1938         }
1939
1940         /* do not inline big functions */
1941         weight -= callee_env->n_nodes;
1942
1943         /* reduce the benefice if the current function is already big */
1944         curr_env = get_irg_link(current_ir_graph);
1945         weight -= curr_env->n_nodes / 50;
1946
1947         /* give a bonus for functions with one block */
1948         if (callee_env->n_blocks == 1)
1949                 weight = weight * 3 / 2;
1950
1951         /* and one for small non-recursive functions: we want them to be inlined in mostly every case */
1952         else if (callee_env->n_nodes < 20 && !callee_env->recursive)
1953                 weight += 5000;
1954
1955         /* and finally for leaves: they do not increase the register pressure
1956            because of callee safe registers */
1957         else if (callee_env->n_call_nodes == 0)
1958                 weight += 25;
1959
1960         /*
1961          * Reduce the weight for recursive function IFF not all arguments are const.
1962          * inlining recursive functions is rarely good.
1963          */
1964         if (callee_env->recursive && !all_const)
1965                 weight -= 500;
1966
1967         /*
1968          * All arguments constant is probably a good sign, give an extra bonus
1969          */
1970         if (all_const)
1971                 weight += 100;
1972
1973         return weight;
1974 }
1975
1976 /**
1977  * Heuristic inliner. Calculates a benefice value for every call and inlines
1978  * those calls with a value higher than the threshold.
1979  */
1980 void inline_functions(int maxsize, int inline_threshold) {
1981         inline_irg_env   *env;
1982         int              i, n_irgs;
1983         ir_graph         *rem;
1984         int              did_inline;
1985         wenv_t           wenv;
1986         call_entry       *curr_call, **last_call;
1987         const call_entry *centry;
1988         pmap             *copied_graphs;
1989         pmap_entry       *pm_entry;
1990
1991         rem = current_ir_graph;
1992         obstack_init(&temp_obst);
1993
1994         /* a map for the copied graphs, used to inline recursive calls */
1995         copied_graphs = pmap_create();
1996
1997         /* extend all irgs by a temporary data structure for inlining. */
1998         n_irgs = get_irp_n_irgs();
1999         for (i = 0; i < n_irgs; ++i)
2000                 set_irg_link(get_irp_irg(i), alloc_inline_irg_env());
2001
2002         /* Precompute information in temporary data structure. */
2003         wenv.ignore_runtime = 0;
2004         wenv.ignore_callers = 0;
2005         for (i = 0; i < n_irgs; ++i) {
2006                 ir_graph *irg = get_irp_irg(i);
2007
2008                 assert(get_irg_phase_state(irg) != phase_building);
2009                 free_callee_info(irg);
2010
2011                 wenv.x         = get_irg_link(irg);
2012                 wenv.last_call = NULL;
2013                 assure_cf_loop(irg);
2014                 irg_walk_graph(irg, NULL, collect_calls2, &wenv);
2015         }
2016
2017         /* -- and now inline. -- */
2018         for (i = 0; i < n_irgs; ++i) {
2019                 int      phiproj_computed = 0;
2020                 ir_node  *call;
2021                 ir_graph *irg = get_irp_irg(i);
2022
2023                 current_ir_graph = irg;
2024                 env = get_irg_link(irg);
2025
2026                 /* note that the list of possible calls is updated during the process */
2027                 last_call = &env->call_head;
2028                 for (curr_call = env->call_head; curr_call != NULL;) {
2029                         ir_graph   *callee;
2030                         pmap_entry *e;
2031                         int        benefice;
2032                         unsigned   local_adr;
2033
2034                         if (env->n_nodes > maxsize) break;
2035
2036                         call   = curr_call->call;
2037                         callee = curr_call->callee;
2038
2039                         e = pmap_find(copied_graphs, callee);
2040                         if (e != NULL) {
2041                                 /*
2042                                 * Remap callee if we have a copy.
2043                                 * FIXME: Should we do this only for recursive Calls ?
2044                                 */
2045                                 callee = e->value;
2046                         }
2047
2048                         /* calculate the benefice on the original call to prevent excessive inlining */
2049                         local_adr = 0;
2050                         benefice = calc_inline_benefice(call, callee, &local_adr);
2051                         DB((dbg, LEVEL_2, "In %+F Call %+F has benefice %d\n", irg, callee, benefice));
2052
2053                         if (benefice > -inline_threshold ||
2054                                 (get_irg_inline_property(callee) >= irg_inline_forced)) {
2055                                 if (current_ir_graph == callee) {
2056                                         /*
2057                                          * Recursive call: we cannot directly inline because we cannot walk
2058                                          * the graph and change it. So we have to make a copy of the graph
2059                                          * first.
2060                                          */
2061
2062                                         inline_irg_env *callee_env;
2063                                         ir_graph       *copy;
2064
2065                                         /*
2066                                          * No copy yet, create one.
2067                                          * Note that recursive methods are never leaves, so it is sufficient
2068                                          * to test this condition here.
2069                                          */
2070                                         copy = create_irg_copy(callee);
2071
2072                                         /* create_irg_copy() destroys the Proj links, recompute them */
2073                                         phiproj_computed = 0;
2074
2075                                         /* allocate new environment */
2076                                         callee_env = alloc_inline_irg_env();
2077                                         set_irg_link(copy, callee_env);
2078
2079                                         assure_cf_loop(copy);
2080                                         wenv.x              = callee_env;
2081                                         wenv.ignore_callers = 1;
2082                                         irg_walk_graph(copy, NULL, collect_calls2, &wenv);
2083
2084                                         /*
2085                                          * Enter the entity of the original graph. This is needed
2086                                          * for inline_method(). However, note that ent->irg still points
2087                                          * to callee, NOT to copy.
2088                                          */
2089                                         set_irg_entity(copy, get_irg_entity(callee));
2090
2091                                         pmap_insert(copied_graphs, callee, copy);
2092                                         callee = copy;
2093
2094                                         /* we have only one caller: the original graph */
2095                                         callee_env->n_callers      = 1;
2096                                         callee_env->n_callers_orig = 1;
2097                                 }
2098                                 if (! phiproj_computed) {
2099                                         phiproj_computed = 1;
2100                                         collect_phiprojs(current_ir_graph);
2101                                 }
2102                                 did_inline = inline_method(call, callee);
2103                                 if (did_inline) {
2104                                         inline_irg_env *callee_env = (inline_irg_env *)get_irg_link(callee);
2105
2106                                         /* was inlined, must be recomputed */
2107                                         phiproj_computed = 0;
2108
2109                                         /* after we have inlined callee, all called methods inside callee
2110                                         are now called once more */
2111                                         for (centry = callee_env->call_head; centry != NULL; centry = centry->next) {
2112                                                 inline_irg_env *penv = get_irg_link(centry->callee);
2113                                                 ++penv->n_callers;
2114                                         }
2115
2116                                         /* callee was inline. Append it's call list. */
2117                                         env->got_inline = 1;
2118                                         if (local_adr)
2119                                                 env->local_vars = 1;
2120                                         --env->n_call_nodes;
2121                                         curr_call = replace_entry_by_call_list(curr_call, callee_env->call_head);
2122                                         env->n_call_nodes += callee_env->n_call_nodes;
2123                                         env->n_nodes += callee_env->n_nodes;
2124                                         --callee_env->n_callers;
2125
2126                                         /* remove the current call entry from the list */
2127                                         *last_call = curr_call;
2128                                         continue;
2129                                 }
2130                         }
2131                         last_call = &curr_call->next;
2132                         curr_call = curr_call->next;
2133                 }
2134
2135                 if (env->got_inline) {
2136                         /* this irg got calls inlined: optimize it */
2137
2138                         /* scalar replacement does not work well with Tuple nodes, so optimize them away */
2139                         optimize_graph_df(irg);
2140
2141                         if (env->local_vars) {
2142                                 if (scalar_replacement_opt(irg)) {
2143                                         optimize_graph_df(irg);
2144                                 }
2145                         }
2146                         optimize_cf(irg);
2147                 }
2148                 if (env->got_inline || (env->n_callers_orig != env->n_callers)) {
2149                         DB((dbg, LEVEL_1, "Nodes:%3d ->%3d, calls:%3d ->%3d, callers:%3d ->%3d, -- %s\n",
2150                         env->n_nodes_orig, env->n_nodes, env->n_call_nodes_orig, env->n_call_nodes,
2151                         env->n_callers_orig, env->n_callers,
2152                         get_entity_name(get_irg_entity(irg))));
2153                 }
2154         }
2155
2156         /* kill the copied graphs: we don't need them anymore */
2157         foreach_pmap(copied_graphs, pm_entry) {
2158                 ir_graph *copy = pm_entry->value;
2159
2160                 /* reset the entity, otherwise it will be deleted in the next step ... */
2161                 set_irg_entity(copy, NULL);
2162                 free_ir_graph(copy);
2163         }
2164         pmap_destroy(copied_graphs);
2165
2166         obstack_free(&temp_obst, NULL);
2167         current_ir_graph = rem;
2168 }
2169
2170 void firm_init_inline(void) {
2171         FIRM_DBG_REGISTER(dbg, "firm.opt.inline");
2172 }