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