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