0f20d7a6ce7ddadfbe6d63549c9e7e887417b546
[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) return;
559
560
561 /* --
562       the procedure and later replaces the Start node of the called graph.
563       Post_call is the old Call node and collects the results of the called
564       graph. Both will end up being a tuple.  -- */
565   post_bl = get_nodes_Block(call);
566   set_irg_current_block(current_ir_graph, post_bl);
567   /* XxMxPxP of Start + parameter of Call */
568   in[0] = new_Jmp();
569   in[1] = get_Call_mem(call);
570   in[2] = get_irg_frame(current_ir_graph);
571   in[3] = get_irg_globals(current_ir_graph);
572   in[4] = new_Tuple (get_Call_n_params(call), get_Call_param_arr(call));
573   pre_call = new_Tuple(5, in);
574   post_call = call;
575
576 /* --
577       The new block gets the ins of the old block, pre_call and all its
578       predecessors and all Phi nodes. -- */
579   part_block(pre_call);
580
581   /* -- Prepare state for dead node elimination -- */
582   /* Visited flags in calling irg must be >= flag in called irg.
583      Else walker and arity computation will not work. */
584   if (get_irg_visited(current_ir_graph) <= get_irg_visited(called_graph))
585     set_irg_visited(current_ir_graph, get_irg_visited(called_graph)+1);
586   if (get_irg_block_visited(current_ir_graph)< get_irg_block_visited(called_graph))
587     set_irg_block_visited(current_ir_graph, get_irg_block_visited(called_graph));
588   /* Set pre_call as new Start node in link field of the start node of
589      calling graph and pre_calls block as new block for the start block
590      of calling graph.
591      Further mark these nodes so that they are not visited by the
592      copying. */
593   set_irn_link(get_irg_start(called_graph), pre_call);
594   set_irn_visited(get_irg_start(called_graph),
595                   get_irg_visited(current_ir_graph));
596   set_irn_link(get_irg_start_block(called_graph),
597                get_nodes_Block(pre_call));
598   set_irn_visited(get_irg_start_block(called_graph),
599                   get_irg_visited(current_ir_graph));
600
601   /* Initialize for compaction of in arrays */
602   inc_irg_block_visited(current_ir_graph);
603
604   /* -- Replicate local entities of the called_graph -- */
605   /* copy the entities. */
606   called_frame = get_irg_frame_type(called_graph);
607   for (i = 0; i < get_class_n_members(called_frame); i++) {
608     entity *new_ent, *old_ent;
609     old_ent = get_class_member(called_frame, i);
610     new_ent = copy_entity_own(old_ent, get_cur_frame_type());
611     set_entity_link(old_ent, new_ent);
612   }
613
614   /* visited is > than that of called graph.  With this trick visited will
615      remain unchanged so that an outer walker, e.g., searching the call nodes
616      to inline, calling this inline will not visit the inlined nodes. */
617   set_irg_visited(current_ir_graph, get_irg_visited(current_ir_graph)-1);
618
619   /* -- Performing dead node elimination inlines the graph -- */
620   /* Copies the nodes to the obstack of current_ir_graph. Updates links to new
621      entities. */
622   /* @@@ endless loops are not copied!! -- they should be, I think... */
623   irg_walk(get_irg_end(called_graph), copy_node_inline, copy_preds,
624            get_irg_frame_type(called_graph));
625
626   /* Repair called_graph */
627   set_irg_visited(called_graph, get_irg_visited(current_ir_graph));
628   set_irg_block_visited(called_graph, get_irg_block_visited(current_ir_graph));
629   set_Block_block_visited(get_irg_start_block(called_graph), 0);
630
631   /* -- Merge the end of the inlined procedure with the call site -- */
632   /* We will turn the old Call node into a Tuple with the following
633      predecessors:
634      -1:  Block of Tuple.
635      0: Phi of all Memories of Return statements.
636      1: Jmp from new Block that merges the control flow from all exception
637          predecessors of the old end block.
638      2: Tuple of all arguments.
639      3: Phi of Exception memories.
640   */
641
642   /* -- Precompute some values -- */
643   end_bl = get_new_node(get_irg_end_block(called_graph));
644   end = get_new_node(get_irg_end(called_graph));
645   arity = get_irn_arity(end_bl);    /* arity = n_exc + n_ret  */
646   n_res = get_method_n_ress(get_Call_type(call));
647
648   res_pred = (ir_node **) malloc (n_res * sizeof (ir_node *));
649   cf_pred = (ir_node **) malloc (arity * sizeof (ir_node *));
650
651   set_irg_current_block(current_ir_graph, post_bl); /* just to make sure */
652
653   /* -- archive keepalives -- */
654   for (i = 0; i < get_irn_arity(end); i++)
655     add_End_keepalive(get_irg_end(current_ir_graph), get_irn_n(end, i));
656   /* The new end node will die, but the in array is not on the obstack ... */
657   free_End(end);
658
659 /* --
660       Return nodes by Jump nodes. -- */
661   n_ret = 0;
662   for (i = 0; i < arity; i++) {
663     ir_node *ret;
664     ret = get_irn_n(end_bl, i);
665     if (get_irn_op(ret) == op_Return) {
666       cf_pred[n_ret] = new_r_Jmp(current_ir_graph, get_nodes_Block(ret));
667       n_ret++;
668     }
669   }
670   set_irn_in(post_bl, n_ret, cf_pred);
671
672 /* --
673       turned into a tuple.  -- */
674   turn_into_tuple(post_call, 4);
675   /* First the Memory-Phi */
676   n_ret = 0;
677   for (i = 0; i < arity; i++) {
678     ret = get_irn_n(end_bl, i);
679     if (get_irn_op(ret) == op_Return) {
680       cf_pred[n_ret] = get_Return_mem(ret);
681       n_ret++;
682     }
683   }
684   phi = new_Phi(n_ret, cf_pred, mode_M);
685   set_Tuple_pred(call, 0, phi);
686   /* Conserve Phi-list for further inlinings -- but might be optimized */
687   if (get_nodes_Block(phi) == post_bl) {
688     set_irn_link(phi, get_irn_link(post_bl));
689     set_irn_link(post_bl, phi);
690   }
691   /* Now the real results */
692   if (n_res > 0) {
693     for (j = 0; j < n_res; j++) {
694       n_ret = 0;
695       for (i = 0; i < arity; i++) {
696         ret = get_irn_n(end_bl, i);
697         if (get_irn_op(ret) == op_Return) {
698           cf_pred[n_ret] = get_Return_res(ret, j);
699           n_ret++;
700         }
701       }
702       phi = new_Phi(n_ret, cf_pred, get_irn_mode(cf_pred[0]));
703       res_pred[j] = phi;
704       /* Conserve Phi-list for further inlinings -- but might be optimized */
705       if (get_nodes_Block(phi) == post_bl) {
706         set_irn_link(phi, get_irn_link(post_bl));
707         set_irn_link(post_bl, phi);
708       }
709     }
710     set_Tuple_pred(call, 2, new_Tuple(n_res, res_pred));
711   } else {
712     set_Tuple_pred(call, 2, new_Bad());
713   }
714   /* Finally the exception control flow.  We need to add a Phi node to
715      collect the memory containing the exception objects.  Further we need
716      to add another block to get a correct representation of this Phi.  To
717      this block we add a Jmp that resolves into the X output of the Call
718      when the Call is turned into a tuple. */
719   n_exc = 0;
720   for (i = 0; i < arity; i++) {
721     ir_node *ret;
722     ret = get_irn_n(end_bl, i);
723     if (is_fragile_op(skip_Proj(ret)) || (get_irn_op(skip_Proj(ret)) == op_Raise)) {
724       cf_pred[n_exc] = ret;
725       n_exc++;
726     }
727   }
728   if (n_exc > 0) {
729     new_Block(n_exc, cf_pred);      /* watch it: current_block is changed! */
730     set_Tuple_pred(call, 1, new_Jmp());
731     /* The Phi for the memories with the exception objects */
732     n_exc = 0;
733     for (i = 0; i < arity; i++) {
734       ir_node *ret;
735       ret = skip_Proj(get_irn_n(end_bl, i));
736       if (get_irn_op(ret) == op_Call) {
737         cf_pred[n_exc] = new_r_Proj(current_ir_graph, get_nodes_Block(ret), ret, mode_M, 3);
738         n_exc++;
739       } else if (is_fragile_op(ret)) {
740         /* We rely that all cfops have the memory output at the same position. */
741         cf_pred[n_exc] = new_r_Proj(current_ir_graph, get_nodes_Block(ret), ret, mode_M, 0);
742         n_exc++;
743       } else if (get_irn_op(ret) == op_Raise) {
744         cf_pred[n_exc] = new_r_Proj(current_ir_graph, get_nodes_Block(ret), ret, mode_M, 1);
745         n_exc++;
746       }
747     }
748     set_Tuple_pred(call, 3, new_Phi(n_exc, cf_pred, mode_M));
749   } else {
750     set_Tuple_pred(call, 1, new_Bad());
751     set_Tuple_pred(call, 3, new_Bad());
752   }
753   free(res_pred);
754   free(cf_pred);
755
756 /* --
757        If the exception control flow from the Call directly branched to the
758        end block we now have the following control flow predecessor pattern:
759        ProjX -> Tuple -> Jmp.
760        We must remove the Jmp along with it's empty block and add Jmp's
761        predecessors as predecessors of this end block. -- */
762   /* find the problematic predecessor of the end block. */
763   end_bl = get_irg_end_block(current_ir_graph);
764   for (i = 0; i < get_Block_n_cfgpreds(end_bl); i++) {
765     cf_op = get_Block_cfgpred(end_bl, i);
766     if (get_irn_op(cf_op) == op_Proj) {
767       cf_op = get_Proj_pred(cf_op);
768       if (get_irn_op(cf_op) == op_Tuple) {
769         cf_op = get_Tuple_pred(cf_op, 1);
770         assert(get_irn_op(cf_op) == op_Jmp);
771         break;
772       }
773     }
774   }
775   /* repair */
776   if (i < get_Block_n_cfgpreds(end_bl)) {
777     bl = get_nodes_Block(cf_op);
778     arity = get_Block_n_cfgpreds(end_bl) + get_Block_n_cfgpreds(bl) - 1;
779     cf_pred = (ir_node **) malloc (arity * sizeof (ir_node *));
780     for (j = 0; j < i; j++)
781       cf_pred[j] = get_Block_cfgpred(end_bl, j);
782     for (j = j; j < i + get_Block_n_cfgpreds(bl); j++)
783       cf_pred[j] = get_Block_cfgpred(bl, j-i);
784     for (j = j; j < arity; j++)
785       cf_pred[j] = get_Block_cfgpred(end_bl, j-get_Block_n_cfgpreds(bl) +1);
786     set_irn_in(end_bl, arity, cf_pred);
787     free(cf_pred);
788   }
789
790   /* --  Turn cse back on. -- */
791   set_optimize(rem_opt);
792 }
793
794 /********************************************************************/
795 /* Apply inlineing to small methods.                                */
796 /********************************************************************/
797
798 static int pos;
799
800 /* It makes no sense to inline too many calls in one procedure. Anyways,
801    I didn't get a version with NEW_ARR_F to run. */
802 #define MAX_INLINE 1024
803
804 static void collect_calls(ir_node *call, void *env) {
805   ir_node **calls = (ir_node **)env;
806   ir_node *addr;
807   tarval *tv;
808   ir_graph *called_irg;
809
810   if (get_irn_op(call) != op_Call) return;
811
812   addr = get_Call_ptr(call);
813   if (get_irn_op(addr) == op_Const) {
814     /* Check whether the constant is the pointer to a compiled entity. */
815     tv = get_Const_tarval(addr);
816     if (tv->u.P.ent) {
817       called_irg = get_entity_irg(tv->u.P.ent);
818       if (called_irg && pos < MAX_INLINE) {
819         /* The Call node calls a locally defined method.  Remember to inline. */
820         calls[pos] = call;
821         pos++;
822       }
823     }
824   }
825 }
826
827 /* Inlines all small methods at call sites where the called address comes
828    from a Const node that references the entity representing the called
829    method.
830    The size argument is a rough measure for the code size of the method:
831    Methods where the obstack containing the firm graph is smaller than
832    size are inlined. */
833 void inline_small_irgs(ir_graph *irg, int size) {
834   int i;
835   ir_node *calls[MAX_INLINE];
836   ir_graph *rem = current_ir_graph;
837
838   if (!(get_optimize() && get_opt_inline())) return;
839
840   current_ir_graph = irg;
841   /* Handle graph state */
842   assert(get_irg_phase_state(current_ir_graph) != phase_building);
843
844   /* Find Call nodes to inline.
845      (We can not inline during a walk of the graph, as inlineing the same
846      method several times changes the visited flag of the walked graph:
847      after the first inlineing visited of the callee equals visited of
848      the caller.  With the next inlineing both are increased.) */
849   pos = 0;
850   irg_walk(get_irg_end(irg), NULL, collect_calls, (void *) calls);
851
852   if ((pos > 0) && (pos < MAX_INLINE)) {
853     /* There are calls to inline */
854     collect_phiprojs(irg);
855     for (i = 0; i < pos; i++) {
856       tarval *tv;
857       ir_graph *callee;
858       tv = get_Const_tarval(get_Call_ptr(calls[i]));
859       callee = get_entity_irg(tv->u.P.ent);
860       if ((_obstack_memory_used(callee->obst) - obstack_room(callee->obst)) < size) {
861         inline_method(calls[i], callee);
862       }
863     }
864   }
865
866   current_ir_graph = rem;
867 }
868
869
870 /********************************************************************/
871 /*  Code Placement.  Pinns all floating nodes to a block where they */
872 /*  will be executed only if needed.                                */
873 /********************************************************************/
874
875 static pdeq *worklist;          /* worklist of ir_node*s */
876
877 /* Find the earliest correct block for N.  --- Place N into the
878    same Block as its dominance-deepest Input.  */
879 static void
880 place_floats_early (ir_node *n)
881 {
882   int i, start;
883
884   /* we must not run into an infinite loop */
885   assert (irn_not_visited(n));
886   mark_irn_visited(n);
887
888   /* Place floating nodes. */
889   if (get_op_pinned(get_irn_op(n)) == floats) {
890     int depth = 0;
891     ir_node *b = new_Bad();   /* The block to place this node in */
892
893     assert(get_irn_op(n) != op_Block);
894
895     if ((get_irn_op(n) == op_Const) ||
896         (get_irn_op(n) == op_SymConst) ||
897         (is_Bad(n))) {
898       /* These nodes will not be placed by the loop below. */
899       b = get_irg_start_block(current_ir_graph);
900       depth = 1;
901     }
902
903     /* find the block for this node. */
904     for (i = 0; i < get_irn_arity(n); i++) {
905       ir_node *dep = get_irn_n(n, i);
906       ir_node *dep_block;
907       if ((irn_not_visited(dep)) &&
908           (get_op_pinned(get_irn_op(dep)) == floats)) {
909         place_floats_early (dep);
910       }
911       /* Because all loops contain at least one pinned node, now all
912          our inputs are either pinned or place_early has already
913          been finished on them.  We do not have any unfinished inputs!  */
914       dep_block = get_nodes_Block(dep);
915       if ((!is_Bad(dep_block)) &&
916           (get_Block_dom_depth(dep_block) > depth)) {
917         b = dep_block;
918         depth = get_Block_dom_depth(dep_block);
919       }
920       /* Avoid that the node is placed in the Start block */
921       if ((depth == 1) && (get_Block_dom_depth(get_nodes_Block(n)) > 1)) {
922         b = get_Block_cfg_out(get_irg_start_block(current_ir_graph), 0);
923         assert(b != get_irg_start_block(current_ir_graph));
924         depth = 2;
925       }
926     }
927     set_nodes_Block(n, b);
928   }
929
930   /* Add predecessors of non floating nodes on worklist. */
931   start = (get_irn_op(n) == op_Block) ? 0 : -1;
932   for (i = start; i < get_irn_arity(n); i++) {
933     ir_node *pred = get_irn_n(n, i);
934     if (irn_not_visited(pred)) {
935       pdeq_putr (worklist, pred);
936     }
937   }
938 }
939
940 /* Floating nodes form subgraphs that begin at nodes as Const, Load,
941    Start, Call and end at pinned nodes as Store, Call.  Place_early
942    places all floating nodes reachable from its argument through floating
943    nodes and adds all beginnings at pinned nodes to the worklist. */
944 static INLINE void place_early (void) {
945   assert(worklist);
946   inc_irg_visited(current_ir_graph);
947
948   /* this inits the worklist */
949   place_floats_early (get_irg_end(current_ir_graph));
950
951   /* Work the content of the worklist. */
952   while (!pdeq_empty (worklist)) {
953     ir_node *n = pdeq_getl (worklist);
954     if (irn_not_visited(n)) place_floats_early (n);
955   }
956
957   set_irg_outs_inconsistent(current_ir_graph);
958   current_ir_graph->pinned = pinned;
959 }
960
961
962 /* deepest common dominance ancestor of DCA and CONSUMER of PRODUCER */
963 static ir_node *
964 consumer_dom_dca (ir_node *dca, ir_node *consumer, ir_node *producer)
965 {
966   ir_node *block = NULL;
967
968   /* Compute the latest block into which we can place a node so that it is
969      before consumer. */
970   if (get_irn_op(consumer) == op_Phi) {
971     /* our comsumer is a Phi-node, the effective use is in all those
972        blocks through which the Phi-node reaches producer */
973     int i;
974     ir_node *phi_block = get_nodes_Block(consumer);
975     for (i = 0;  i < get_irn_arity(consumer); i++) {
976       if (get_irn_n(consumer, i) == producer) {
977         block = get_nodes_Block(get_Block_cfgpred(phi_block, i));
978       }
979     }
980   } else {
981     assert(is_no_Block(consumer));
982     block = get_nodes_Block(consumer);
983   }
984
985   /* Compute the deepest common ancestor of block and dca. */
986   assert(block);
987   if (!dca) return block;
988   while (get_Block_dom_depth(block) > get_Block_dom_depth(dca))
989     block = get_Block_idom(block);
990   while (get_Block_dom_depth(dca) > get_Block_dom_depth(block))
991     dca = get_Block_idom(dca);
992   while (block != dca)
993     { block = get_Block_idom(block); dca = get_Block_idom(dca); }
994
995   return dca;
996 }
997
998 static INLINE int get_irn_loop_depth(ir_node *n) {
999   return get_loop_depth(get_irn_loop(n));
1000 }
1001
1002 /* Move n to a block with less loop depth than it's current block. The
1003    new block must be dominated by early. */
1004 static void
1005 move_out_of_loops (ir_node *n, ir_node *early)
1006 {
1007   ir_node *best, *dca;
1008   assert(n && early);
1009
1010
1011   /* Find the region deepest in the dominator tree dominating
1012      dca with the least loop nesting depth, but still dominated
1013      by our early placement. */
1014   dca = get_nodes_Block(n);
1015   best = dca;
1016   while (dca != early) {
1017     dca = get_Block_idom(dca);
1018     if (!dca) break; /* should we put assert(dca)? */
1019     if (get_irn_loop_depth(dca) < get_irn_loop_depth(best)) {
1020       best = dca;
1021     }
1022   }
1023   if (best != get_nodes_Block(n)) {
1024     /* debug output
1025     printf("Moving out of loop: "); DDMN(n);
1026     printf(" Outermost block: "); DDMN(early);
1027     printf(" Best block: "); DDMN(best);
1028     printf(" Innermost block: "); DDMN(get_nodes_Block(n));
1029     */
1030     set_nodes_Block(n, best);
1031   }
1032 }
1033
1034 /* Find the latest legal block for N and place N into the
1035    `optimal' Block between the latest and earliest legal block.
1036    The `optimal' block is the dominance-deepest block of those
1037    with the least loop-nesting-depth.  This places N out of as many
1038    loops as possible and then makes it as controldependant as
1039    possible. */
1040 static void
1041 place_floats_late (ir_node *n)
1042 {
1043   int i;
1044   ir_node *early;
1045
1046   assert (irn_not_visited(n)); /* no multiple placement */
1047
1048   /* no need to place block nodes, control nodes are already placed. */
1049   if ((get_irn_op(n) != op_Block) &&
1050       (!is_cfop(n)) &&
1051       (get_irn_mode(n) != mode_X)) {
1052     /* Remember the early palacement of this block to move it
1053        out of loop no further than the early placement. */
1054     early = get_nodes_Block(n);
1055     /* Assure that our users are all placed, except the Phi-nodes.
1056        --- Each dataflow cycle contains at least one Phi-node.  We
1057        have to break the `user has to be placed before the
1058        producer' dependance cycle and the Phi-nodes are the
1059        place to do so, because we need to base our placement on the
1060        final region of our users, which is OK with Phi-nodes, as they
1061        are pinned, and they never have to be placed after a
1062        producer of one of their inputs in the same block anyway. */
1063     for (i = 0; i < get_irn_n_outs(n); i++) {
1064       ir_node *succ = get_irn_out(n, i);
1065       if (irn_not_visited(succ) && (get_irn_op(succ) != op_Phi))
1066         place_floats_late (succ);
1067     }
1068
1069     /* We have to determine the final block of this node... except for
1070        constants. */
1071     if ((get_op_pinned(get_irn_op(n)) == floats) &&
1072         (get_irn_op(n) != op_Const) &&
1073         (get_irn_op(n) != op_SymConst)) {
1074       ir_node *dca = NULL;      /* deepest common ancestor in the
1075                                    dominator tree of all nodes'
1076                                    blocks depending on us; our final
1077                                    placement has to dominate DCA. */
1078       for (i = 0; i < get_irn_n_outs(n); i++) {
1079         dca = consumer_dom_dca (dca, get_irn_out(n, i), n);
1080       }
1081       set_nodes_Block(n, dca);
1082
1083       move_out_of_loops (n, early);
1084     }
1085   }
1086
1087   mark_irn_visited(n);
1088
1089   /* Add predecessors of all non-floating nodes on list. (Those of floating
1090      nodes are placeded already and therefore are marked.)  */
1091   for (i = 0; i < get_irn_n_outs(n); i++) {
1092     if (irn_not_visited(get_irn_out(n, i))) {
1093       pdeq_putr (worklist, get_irn_out(n, i));
1094     }
1095   }
1096 }
1097
1098 static INLINE void place_late(void) {
1099   assert(worklist);
1100   inc_irg_visited(current_ir_graph);
1101
1102   /* This fills the worklist initially. */
1103   place_floats_late(get_irg_start_block(current_ir_graph));
1104   /* And now empty the worklist again... */
1105   while (!pdeq_empty (worklist)) {
1106     ir_node *n = pdeq_getl (worklist);
1107     if (irn_not_visited(n)) place_floats_late(n);
1108   }
1109 }
1110
1111 void place_code(ir_graph *irg) {
1112   ir_graph *rem = current_ir_graph;
1113   current_ir_graph = irg;
1114
1115   if (!(get_optimize() && get_opt_global_cse())) return;
1116
1117   /* Handle graph state */
1118   assert(get_irg_phase_state(irg) != phase_building);
1119   if (get_irg_dom_state(irg) != dom_consistent)
1120     compute_doms(irg);
1121
1122   construct_backedges(irg);
1123
1124   /* Place all floating nodes as early as possible. This guarantees
1125      a legal code placement. */
1126   worklist = new_pdeq ();
1127   place_early();
1128
1129   /* place_early invalidates the outs, place_late needs them. */
1130   compute_outs(irg);
1131   /* Now move the nodes down in the dominator tree. This reduces the
1132      unnecessary executions of the node. */
1133   place_late();
1134
1135   set_irg_outs_inconsistent(current_ir_graph);
1136   del_pdeq (worklist);
1137   current_ir_graph = rem;
1138 }
1139
1140
1141
1142 /********************************************************************/
1143 /* Control flow optimization.                                       */
1144 /* Removes Bad control flow predecessors and empty blocks.  A block */
1145 /* is empty if it contains only a Jmp node.                         */
1146 /* Blocks can only be removed if they are not needed for the        */
1147 /* semantics of Phi nodes.                                          */
1148 /********************************************************************/
1149
1150 /* Removes Tuples from Block control flow predecessors.
1151    Optimizes blocks with equivalent_node().                         */
1152 static void merge_blocks(ir_node *n, void *env) {
1153   int i;
1154   set_irn_link(n, NULL);
1155
1156   if (get_irn_op(n) == op_Block) {
1157     /* Remove Tuples */
1158     for (i = 0; i < get_Block_n_cfgpreds(n); i++)
1159       set_Block_cfgpred(n, i, skip_Tuple(get_Block_cfgpred(n, i)));
1160   } else if (get_irn_mode(n) == mode_X) {
1161     /* We will soon visit a block.  Optimize it before visiting! */
1162     ir_node *b = get_nodes_Block(n);
1163     ir_node *new = equivalent_node(b);
1164     while (irn_not_visited(b) && (!is_Bad(new)) && (new != b)) {
1165       /* We would have to run gigo if new is bad. */
1166       if (!get_optimize() || (!get_opt_control_flow_straightening()
1167                               && !get_opt_control_flow_weak_simplification()))
1168         /* how could something be optimized if flags are not set? */
1169         assert(0 && "strange ?? !!");
1170       exchange (b, new);
1171       b = new;
1172       new = equivalent_node(b);
1173     }
1174     if (is_Bad(new)) exchange (n, new_Bad());
1175   }
1176 }
1177
1178 /* Collects all Phi nodes in link list of Block.
1179    Marks all blocks "block_visited" if they contain a node other
1180    than Jmp. */
1181 static void collect_nodes(ir_node *n, void *env) {
1182   if (is_no_Block(n)) {
1183     ir_node *b = get_nodes_Block(n);
1184
1185     if ((get_irn_op(n) == op_Phi)) {
1186       /* Collect Phi nodes to compact ins along with block's ins. */
1187       set_irn_link(n, get_irn_link(b));
1188       set_irn_link(b, n);
1189     } else if (get_irn_op(n) != op_Jmp) {  /* Check for non empty block. */
1190       mark_Block_block_visited(b);
1191     }
1192   }
1193 }
1194
1195 /* Returns true if pred is pred of block */
1196 static int is_pred_of(ir_node *pred, ir_node *b) {
1197   int i;
1198   for (i = 0; i < get_Block_n_cfgpreds(b); i++) {
1199     ir_node *b_pred = get_nodes_Block(get_Block_cfgpred(b, i));
1200     if (b_pred == pred) return 1;
1201   }
1202   return 0;
1203 }
1204
1205 static int test_whether_dispensable(ir_node *b, int pos) {
1206   int i, j, n_preds = 1;
1207   int dispensable = 1;
1208   ir_node *cfop = get_Block_cfgpred(b, pos);
1209   ir_node *pred = get_nodes_Block(cfop);
1210
1211   if (get_Block_block_visited(pred) + 1
1212       < get_irg_block_visited(current_ir_graph)) {
1213     if (!get_optimize() || !get_opt_control_flow_strong_simplification()) {
1214       /* Mark block so that is will not be removed. */
1215       set_Block_block_visited(pred, get_irg_block_visited(current_ir_graph)-1);
1216       return 1;
1217     }
1218     /* Seems to be empty. */
1219     if (!get_irn_link(b)) {
1220       /* There are no Phi nodes ==> dispensable. */
1221       n_preds = get_Block_n_cfgpreds(pred);
1222     } else {
1223       /* b's pred blocks and pred's pred blocks must be pairwise disjunct.
1224          Work preds < pos as if they were already removed. */
1225       for (i = 0; i < pos; i++) {
1226         ir_node *b_pred = get_nodes_Block(get_Block_cfgpred(b, i));
1227         if (get_Block_block_visited(b_pred) + 1
1228             < get_irg_block_visited(current_ir_graph)) {
1229           for (j = 0; j < get_Block_n_cfgpreds(b_pred); j++) {
1230             ir_node *b_pred_pred = get_nodes_Block(get_Block_cfgpred(b_pred, j));
1231             if (is_pred_of(b_pred_pred, pred)) dispensable = 0;
1232           }
1233         } else {
1234           if (is_pred_of(b_pred, pred)) dispensable = 0;
1235         }
1236       }
1237       for (i = pos +1; i < get_Block_n_cfgpreds(b); i++) {
1238         ir_node *b_pred = get_nodes_Block(get_Block_cfgpred(b, i));
1239         if (is_pred_of(b_pred, pred)) dispensable = 0;
1240       }
1241       if (!dispensable) {
1242         set_Block_block_visited(pred, get_irg_block_visited(current_ir_graph)-1);
1243         n_preds = 1;
1244       } else {
1245         n_preds = get_Block_n_cfgpreds(pred);
1246       }
1247     }
1248   }
1249
1250   return n_preds;
1251 }
1252
1253 static void optimize_blocks(ir_node *b, void *env) {
1254   int i, j, k, max_preds, n_preds;
1255   ir_node *pred, *phi;
1256   ir_node **in;
1257
1258   /* Count the number of predecessor if this block is merged with pred blocks
1259      that are empty. */
1260   max_preds = 0;
1261   for (i = 0; i < get_Block_n_cfgpreds(b); i++) {
1262     max_preds += test_whether_dispensable(b, i);
1263   }
1264   in = (ir_node **) malloc(max_preds * sizeof(ir_node *));
1265
1266 /**
1267   printf(" working on "); DDMN(b);
1268   for (i = 0; i < get_Block_n_cfgpreds(b); i++) {
1269     pred = get_nodes_Block(get_Block_cfgpred(b, i));
1270     if (is_Bad(get_Block_cfgpred(b, i))) {
1271       printf("  removing Bad %i\n ", i);
1272     } else if (get_Block_block_visited(pred) +1
1273                < get_irg_block_visited(current_ir_graph)) {
1274       printf("  removing pred %i ", i); DDMN(pred);
1275     } else { printf("  Nothing to do for "); DDMN(pred); }
1276   }
1277   * end Debug output **/
1278
1279   /** Fix the Phi nodes **/
1280   phi = get_irn_link(b);
1281   while (phi) {
1282     assert(get_irn_op(phi) == op_Phi);
1283     /* Find the new predecessors for the Phi */
1284     n_preds = 0;
1285     for (i = 0; i < get_Block_n_cfgpreds(b); i++) {
1286       pred = get_nodes_Block(get_Block_cfgpred(b, i));
1287       if (is_Bad(get_Block_cfgpred(b, i))) {
1288         /* Do nothing */
1289       } else if (get_Block_block_visited(pred) +1
1290                  < get_irg_block_visited(current_ir_graph)) {
1291         /* It's an empty block and not yet visited. */
1292         ir_node *phi_pred = get_Phi_pred(phi, i);
1293         for (j = 0; j < get_Block_n_cfgpreds(pred); j++) {
1294           if (get_nodes_Block(phi_pred) == pred) {
1295             assert(get_irn_op(phi_pred) == op_Phi);  /* Block is empty!! */
1296             in[n_preds] = get_Phi_pred(phi_pred, j);
1297           } else {
1298             in[n_preds] = phi_pred;
1299           }
1300           n_preds++;
1301         }
1302         /* The Phi_pred node is replaced now if it is a Phi.
1303            In Schleifen kann offenbar der entfernte Phi Knoten legal verwendet werden.
1304            Daher muss der Phiknoten durch den neuen ersetzt werden.
1305            Weiter muss der alte Phiknoten entfernt werden (durch ersetzen oder
1306            durch einen Bad) damit er aus den keep_alive verschwinden kann.
1307            Man sollte also, falls keine Schleife vorliegt, exchange mit new_Bad
1308            aufrufen.  */
1309         if (get_nodes_Block(phi_pred) == pred) {
1310           /* remove the Phi as it might be kept alive. Further there
1311              might be other users. */
1312           exchange(phi_pred, phi);  /* geht, ist aber doch semantisch falsch! Warum?? */
1313         }
1314       } else {
1315         in[n_preds] = get_Phi_pred(phi, i);
1316         n_preds ++;
1317       }
1318     }
1319     /* Fix the node */
1320     set_irn_in(phi, n_preds, in);
1321
1322     phi = get_irn_link(phi);
1323   }
1324
1325 /**
1326       This happens only if merge between loop backedge and single loop entry. **/
1327   for (k = 0; k < get_Block_n_cfgpreds(b); k++) {
1328     pred = get_nodes_Block(get_Block_cfgpred(b, k));
1329     if (get_Block_block_visited(pred) +1
1330         < get_irg_block_visited(current_ir_graph)) {
1331       phi = get_irn_link(pred);
1332       while (phi) {
1333         if (get_irn_op(phi) == op_Phi) {
1334           set_nodes_Block(phi, b);
1335
1336           n_preds = 0;
1337           for (i = 0; i < k; i++) {
1338             pred = get_nodes_Block(get_Block_cfgpred(b, i));
1339             if (is_Bad(get_Block_cfgpred(b, i))) {
1340               /* Do nothing */
1341             } else if (get_Block_block_visited(pred) +1
1342                        < get_irg_block_visited(current_ir_graph)) {
1343               /* It's an empty block and not yet visited. */
1344               for (j = 0; j < get_Block_n_cfgpreds(pred); j++) {
1345                 /* @@@ Hier brauche ich Schleifeninformation!!! Kontrollflusskante
1346                    muss Rueckwaertskante sein! (An allen vier in[n_preds] = phi
1347                    Anweisungen.) Trotzdem tuts bisher!! */
1348                 in[n_preds] = phi;
1349                 n_preds++;
1350               }
1351             } else {
1352               in[n_preds] = phi;
1353               n_preds++;
1354             }
1355           }
1356           for (i = 0; i < get_Phi_n_preds(phi); i++) {
1357             in[n_preds] = get_Phi_pred(phi, i);
1358             n_preds++;
1359           }
1360           for (i = k+1; i < get_Block_n_cfgpreds(b); i++) {
1361             pred = get_nodes_Block(get_Block_cfgpred(b, i));
1362             if (is_Bad(get_Block_cfgpred(b, i))) {
1363               /* Do nothing */
1364             } else if (get_Block_block_visited(pred) +1
1365                        < get_irg_block_visited(current_ir_graph)) {
1366               /* It's an empty block and not yet visited. */
1367               for (j = 0; j < get_Block_n_cfgpreds(pred); j++) {
1368                 in[n_preds] = phi;
1369                 n_preds++;
1370               }
1371             } else {
1372               in[n_preds] = phi;
1373               n_preds++;
1374             }
1375           }
1376           set_irn_in(phi, n_preds, in);
1377         }
1378         phi = get_irn_link(phi);
1379       }
1380     }
1381   }
1382
1383   /** Fix the block **/
1384   n_preds = 0;
1385   for (i = 0; i < get_Block_n_cfgpreds(b); i++) {
1386     pred = get_nodes_Block(get_Block_cfgpred(b, i));
1387     if (is_Bad(get_Block_cfgpred(b, i))) {
1388       /* Do nothing */
1389     } else if (get_Block_block_visited(pred) +1
1390                < get_irg_block_visited(current_ir_graph)) {
1391       /* It's an empty block and not yet visited. */
1392       assert(get_Block_n_cfgpreds(b) > 1);
1393                         /* Else it should be optimized by equivalent_node. */
1394       for (j = 0; j < get_Block_n_cfgpreds(pred); j++) {
1395         in[n_preds] = get_Block_cfgpred(pred, j);
1396         n_preds++;
1397       }
1398       /* Remove block as it might be kept alive. */
1399       exchange(pred, b/*new_Bad()*/);
1400     } else {
1401       in[n_preds] = get_Block_cfgpred(b, i);
1402       n_preds ++;
1403     }
1404   }
1405   set_irn_in(b, n_preds, in);
1406   free(in);
1407 }
1408
1409 void optimize_cf(ir_graph *irg) {
1410   int i;
1411   ir_node **in;
1412   ir_node *end = get_irg_end(irg);
1413   ir_graph *rem = current_ir_graph;
1414   current_ir_graph = irg;
1415
1416   /* Handle graph state */
1417   assert(get_irg_phase_state(irg) != phase_building);
1418   if (get_irg_outs_state(current_ir_graph) == outs_consistent)
1419     set_irg_outs_inconsistent(current_ir_graph);
1420   if (get_irg_dom_state(current_ir_graph) == dom_consistent)
1421     set_irg_dom_inconsistent(current_ir_graph);
1422
1423   /* Use block visited flag to mark non-empty blocks. */
1424   inc_irg_block_visited(irg);
1425   irg_walk(end, merge_blocks, collect_nodes, NULL);
1426
1427   /* Optimize the standard code. */
1428   irg_block_walk(get_irg_end_block(irg), optimize_blocks, NULL, NULL);
1429
1430   /* Walk all keep alives, optimize them if block, add to new in-array
1431      for end if useful. */
1432   in = NEW_ARR_F (ir_node *, 1);
1433   in[0] = get_nodes_Block(end);
1434   inc_irg_visited(current_ir_graph);
1435   for(i = 0; i < get_End_n_keepalives(end); i++) {
1436     ir_node *ka = get_End_keepalive(end, i);
1437     if (irn_not_visited(ka)) {
1438       if ((get_irn_op(ka) == op_Block) && Block_not_block_visited(ka)) {
1439         set_irg_block_visited(current_ir_graph,  /* Don't walk all the way to Start. */
1440                               get_irg_block_visited(current_ir_graph)-1);
1441         irg_block_walk(ka, optimize_blocks, NULL, NULL);
1442         mark_irn_visited(ka);
1443         ARR_APP1 (ir_node *, in, ka);
1444       } else if (get_irn_op(ka) == op_Phi) {
1445         mark_irn_visited(ka);
1446         ARR_APP1 (ir_node *, in, ka);
1447       }
1448     }
1449   }
1450   /* DEL_ARR_F(end->in);   GL @@@ tut nicht ! */
1451   end->in = in;
1452
1453   current_ir_graph = rem;
1454 }
1455
1456
1457 /**
1458  * Called by walker of remove_critical_cf_edges.
1459  *
1460  * Place an empty block to an edge between a blocks of multiple
1461  * predecessors and a block of multiple sucessors.
1462  *
1463  * @param n IR node
1464  * @param env Envirnment of walker. This field is unused and has
1465  *            the value NULL.
1466  */
1467 static void walk_critical_cf_edges(ir_node *n, void *env) {
1468   int arity, i;
1469   ir_node *pre, *block, **in, *jmp;
1470
1471   /* Block has multiple predecessors */
1472   if ((op_Block == get_irn_op(n)) &&
1473       (get_irn_arity(n) > 1)) {
1474     arity = get_irn_arity(n);
1475
1476     for (i=0; i<arity; i++) {
1477       pre = get_irn_n(n, i);
1478       /* Predecessor has multiple sucessors. Insert new flow edge */
1479       if ((NULL != pre) && (op_Proj == get_irn_op(pre))) {
1480
1481         /* set predeseccor array for new block */
1482         in = NEW_ARR_D (ir_node *, current_ir_graph->obst, 1);
1483         /* set predecessor of new block */
1484         in[0] = pre;
1485         block = new_Block(1, in);
1486         /* insert new jmp node to new block */
1487         switch_block(block);
1488         jmp = new_Jmp();
1489         switch_block(n);
1490         /* set sucessor of new block */
1491         set_irn_n(n, i, jmp);
1492
1493       } /* predecessor has multiple sucessors */
1494     } /* for all predecessors */
1495   } /* n is a block */
1496 }
1497
1498 void remove_critical_cf_edges(ir_graph *irg) {
1499   if (get_opt_critical_edges())
1500     irg_walk_graph(irg, NULL, walk_critical_cf_edges, NULL);
1501 }