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