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