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