cac1527797a6fdc540ff7d95e1c88eb3d82648c6
[libfirm] / ir / ir / irgopt.c
1 /* Coyright (C) 1998 - 2000 by Universitaet Karlsruhe
2 ** All rights reserved.
3 **
4 ** Author: Christian Schaefer
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 void init_link (ir_node *n, void *env) {
43   set_irn_link(n, NULL);
44 }
45
46 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 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 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 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()) &&
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 () {
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 void
312 copy_graph_env () {
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 /**********************************************************************/
414 /*  Funcionality for inlining                                         */
415 /**********************************************************************/
416
417 /* Copy node for inlineing.  Copies the node by calling copy_node and
418    then updates the entity if it's a local one.  env must be a pointer
419    to the frame type of the procedure. The new entities must be in
420    the link field of the entities. */
421 static INLINE void
422 copy_node_inline (ir_node *n, void *env) {
423   ir_node *new;
424   type *frame_tp = (type *)env;
425
426   copy_node(n, NULL);
427   if (get_irn_op(n) == op_Sel) {
428     new = get_new_node (n);
429     assert(get_irn_op(new) == op_Sel);
430     if (get_entity_owner(get_Sel_entity(n)) == frame_tp) {
431       set_Sel_entity(new, get_entity_link(get_Sel_entity(n)));
432     }
433   }
434 }
435
436 void inline_method(ir_node *call, ir_graph *called_graph) {
437   ir_node *pre_call;
438   ir_node *post_call, *post_bl;
439   ir_node *in[5];
440   ir_node *end, *end_bl;
441   ir_node **res_pred;
442   ir_node **cf_pred;
443   ir_node *ret, *phi;
444   ir_node *cf_op = NULL, *bl;
445   int arity, n_ret, n_exc, n_res, i, j, rem_opt;
446   type *called_frame;
447
448   if (!get_optimize() || !get_opt_inline()) return;
449   /** Turn off optimizations, this can cause problems when allocating new nodes. **/
450   rem_opt = get_optimize();
451   set_optimize(0);
452
453   /* Handle graph state */
454   assert(get_irg_phase_state(current_ir_graph) != phase_building);
455   assert(get_irg_pinned(current_ir_graph) == pinned);
456   assert(get_irg_pinned(called_graph) == pinned);
457   if (get_irg_outs_state(current_ir_graph) == outs_consistent)
458     set_irg_outs_inconsistent(current_ir_graph);
459
460   /** Check preconditions **/
461   assert(get_irn_op(call) == op_Call);
462   /* @@@ TODO does not work for InterfaceIII.java after cgana
463      assert(get_Call_type(call) == get_entity_type(get_irg_ent(called_graph)));
464      assert(smaller_type(get_entity_type(get_irg_ent(called_graph)),
465      get_Call_type(call)));
466   */
467   assert(get_type_tpop(get_Call_type(call)) == type_method);
468   if (called_graph == current_ir_graph) return;
469
470
471   /** Part the Call node into two nodes.  Pre_call collects the parameters of
472       the procedure and later replaces the Start node of the called graph.
473       Post_call is the old Call node and collects the results of the called
474       graph. Both will end up being a tuple.  **/
475   post_bl = get_nodes_Block(call);
476   set_irg_current_block(current_ir_graph, post_bl);
477   /* XxMxPxP of Start + parameter of Call */
478   in[0] = new_Jmp();
479   in[1] = get_Call_mem(call);
480   in[2] = get_irg_frame(current_ir_graph);
481   in[3] = get_irg_globals(current_ir_graph);
482   in[4] = new_Tuple (get_Call_n_params(call), get_Call_param_arr(call));
483   pre_call = new_Tuple(5, in);
484   post_call = call;
485
486   /** Part the block of the Call node into two blocks.
487       The new block gets the ins of the old block, pre_call and all its
488       predecessors and all Phi nodes. **/
489   part_block(pre_call);
490
491   /** Prepare state for dead node elimination **/
492   /* Visited flags in calling irg must be >= flag in called irg.
493      Else walker and arity computation will not work. */
494   if (get_irg_visited(current_ir_graph) <= get_irg_visited(called_graph))
495     set_irg_visited(current_ir_graph, get_irg_visited(called_graph)+1);
496   if (get_irg_block_visited(current_ir_graph)< get_irg_block_visited(called_graph))
497     set_irg_block_visited(current_ir_graph, get_irg_block_visited(called_graph));
498   /* Set pre_call as new Start node in link field of the start node of
499      calling graph and pre_calls block as new block for the start block
500      of calling graph.
501      Further mark these nodes so that they are not visited by the
502      copying. */
503   set_irn_link(get_irg_start(called_graph), pre_call);
504   set_irn_visited(get_irg_start(called_graph),
505                   get_irg_visited(current_ir_graph));
506   set_irn_link(get_irg_start_block(called_graph),
507                get_nodes_Block(pre_call));
508   set_irn_visited(get_irg_start_block(called_graph),
509                   get_irg_visited(current_ir_graph));
510
511   /* Initialize for compaction of in arrays */
512   inc_irg_block_visited(current_ir_graph);
513
514   /*** Replicate local entities of the called_graph ***/
515   /* copy the entities. */
516   called_frame = get_irg_frame_type(called_graph);
517   for (i = 0; i < get_class_n_members(called_frame); i++) {
518     entity *new_ent, *old_ent;
519     old_ent = get_class_member(called_frame, i);
520     new_ent = copy_entity_own(old_ent, get_cur_frame_type());
521     set_entity_link(old_ent, new_ent);
522   }
523
524   /* visited is > than that of called graph.  With this trick visited will
525      remain unchanged so that an outer walker, e.g., searching the call nodes
526      to inline, calling this inline will not visit the inlined nodes. */
527   set_irg_visited(current_ir_graph, get_irg_visited(current_ir_graph)-1);
528
529   /** Performing dead node elimination inlines the graph **/
530   /* Copies the nodes to the obstack of current_ir_graph. Updates links to new
531      entities. */
532   /* @@@ endless loops are not copied!! -- they should be, I think... */
533   irg_walk(get_irg_end(called_graph), copy_node_inline, copy_preds,
534            get_irg_frame_type(called_graph));
535
536   /* Repair called_graph */
537   set_irg_visited(called_graph, get_irg_visited(current_ir_graph));
538   set_irg_block_visited(called_graph, get_irg_block_visited(current_ir_graph));
539   set_Block_block_visited(get_irg_start_block(called_graph), 0);
540
541   /*** Merge the end of the inlined procedure with the call site ***/
542   /* We will turn the old Call node into a Tuple with the following
543      predecessors:
544      -1:  Block of Tuple.
545      0: Phi of all Memories of Return statements.
546      1: Jmp from new Block that merges the control flow from all exception
547          predecessors of the old end block.
548      2: Tuple of all arguments.
549      3: Phi of Exception memories.
550   */
551
552   /** Precompute some values **/
553   end_bl = get_new_node(get_irg_end_block(called_graph));
554   end = get_new_node(get_irg_end(called_graph));
555   arity = get_irn_arity(end_bl);    /* arity = n_exc + n_ret  */
556   n_res = get_method_n_ress(get_Call_type(call));
557
558   res_pred = (ir_node **) malloc (n_res * sizeof (ir_node *));
559   cf_pred = (ir_node **) malloc (arity * sizeof (ir_node *));
560
561   set_irg_current_block(current_ir_graph, post_bl); /* just to make sure */
562
563   /** archive keepalives **/
564   for (i = 0; i < get_irn_arity(end); i++)
565     add_End_keepalive(get_irg_end(current_ir_graph), get_irn_n(end, i));
566   /* The new end node will die, but the in array is not on the obstack ... */
567   free_End(end);
568
569   /** Collect control flow from Return blocks to post_calls block. Replace
570       Return nodes by Jump nodes. **/
571   n_ret = 0;
572   for (i = 0; i < arity; i++) {
573     ir_node *ret;
574     ret = get_irn_n(end_bl, i);
575     if (get_irn_op(ret) == op_Return) {
576       cf_pred[n_ret] = new_r_Jmp(current_ir_graph, get_nodes_Block(ret));
577       n_ret++;
578     }
579   }
580   set_irn_in(post_bl, n_ret, cf_pred);
581
582   /** Collect results from Return nodes to post_call. Post_call is
583       turned into a tuple. **/
584   turn_into_tuple(post_call, 4);
585   /* First the Memory-Phi */
586   n_ret = 0;
587   for (i = 0; i < arity; i++) {
588     ret = get_irn_n(end_bl, i);
589     if (get_irn_op(ret) == op_Return) {
590       cf_pred[n_ret] = get_Return_mem(ret);
591       n_ret++;
592     }
593   }
594   phi = new_Phi(n_ret, cf_pred, mode_M);
595   set_Tuple_pred(call, 0, phi);
596   /* Conserve Phi-list for further inlinings -- but might be optimized */
597   if (get_nodes_Block(phi) == post_bl) {
598     set_irn_link(phi, get_irn_link(post_bl));
599     set_irn_link(post_bl, phi);
600   }
601   /* Now the real results */
602   if (n_res > 0) {
603     for (j = 0; j < n_res; j++) {
604       n_ret = 0;
605       for (i = 0; i < arity; i++) {
606         ret = get_irn_n(end_bl, i);
607         if (get_irn_op(ret) == op_Return) {
608           cf_pred[n_ret] = get_Return_res(ret, j);
609           n_ret++;
610         }
611       }
612       phi = new_Phi(n_ret, cf_pred, get_irn_mode(cf_pred[0]));
613       res_pred[j] = phi;
614       /* Conserve Phi-list for further inlinings -- but might be optimized */
615       if (get_nodes_Block(phi) == post_bl) {
616         set_irn_link(phi, get_irn_link(post_bl));
617         set_irn_link(post_bl, phi);
618       }
619     }
620     set_Tuple_pred(call, 2, new_Tuple(n_res, res_pred));
621   } else {
622     set_Tuple_pred(call, 2, new_Bad());
623   }
624   /* Finally the exception control flow.  We need to add a Phi node to
625      collect the memory containing the exception objects.  Further we need
626      to add another block to get a correct representation of this Phi.  To
627      this block we add a Jmp that resolves into the X output of the Call
628      when the Call is turned into a tuple. */
629   n_exc = 0;
630   for (i = 0; i < arity; i++) {
631     ir_node *ret;
632     ret = get_irn_n(end_bl, i);
633     if (is_fragile_op(skip_Proj(ret)) || (get_irn_op(skip_Proj(ret)) == op_Raise)) {
634       cf_pred[n_exc] = ret;
635       n_exc++;
636     }
637   }
638   if (n_exc > 0) {
639     new_Block(n_exc, cf_pred);      /* watch it: current_block is changed! */
640     set_Tuple_pred(call, 1, new_Jmp());
641     /* The Phi for the memories with the exception objects */
642     n_exc = 0;
643     for (i = 0; i < arity; i++) {
644       ir_node *ret;
645       ret = skip_Proj(get_irn_n(end_bl, i));
646       if (get_irn_op(ret) == op_Call) {
647         cf_pred[n_exc] = new_r_Proj(current_ir_graph, get_nodes_Block(ret), ret, mode_M, 3);
648         n_exc++;
649       } else if (is_fragile_op(ret)) {
650         /* We rely that all cfops have the memory output at the same position. */
651         cf_pred[n_exc] = new_r_Proj(current_ir_graph, get_nodes_Block(ret), ret, mode_M, 0);
652         n_exc++;
653       } else if (get_irn_op(ret) == op_Raise) {
654         cf_pred[n_exc] = new_r_Proj(current_ir_graph, get_nodes_Block(ret), ret, mode_M, 1);
655         n_exc++;
656       }
657     }
658     set_Tuple_pred(call, 3, new_Phi(n_exc, cf_pred, mode_M));
659   } else {
660     set_Tuple_pred(call, 1, new_Bad());
661     set_Tuple_pred(call, 3, new_Bad());
662   }
663   free(res_pred);
664   free(cf_pred);
665
666   /*** Correct the control flow to the end node.
667        If the exception control flow from the Call directly branched to the
668        end block we now have the following control flow predecessor pattern:
669        ProjX -> Tuple -> Jmp.
670        We must remove the Jmp along with it's empty block and add Jmp's
671        predecessors as predecessors of this end block. ***/
672   /* find the problematic predecessor of the end block. */
673   end_bl = get_irg_end_block(current_ir_graph);
674   for (i = 0; i < get_Block_n_cfgpreds(end_bl); i++) {
675     cf_op = get_Block_cfgpred(end_bl, i);
676     if (get_irn_op(cf_op) == op_Proj) {
677       cf_op = get_Proj_pred(cf_op);
678       if (get_irn_op(cf_op) == op_Tuple) {
679         cf_op = get_Tuple_pred(cf_op, 1);
680         assert(get_irn_op(cf_op) == op_Jmp);
681         break;
682       }
683     }
684   }
685   /* repair */
686   if (i < get_Block_n_cfgpreds(end_bl)) {
687     bl = get_nodes_Block(cf_op);
688     arity = get_Block_n_cfgpreds(end_bl) + get_Block_n_cfgpreds(bl) - 1;
689     cf_pred = (ir_node **) malloc (arity * sizeof (ir_node *));
690     for (j = 0; j < i; j++)
691       cf_pred[j] = get_Block_cfgpred(end_bl, j);
692     for (j = j; j < i + get_Block_n_cfgpreds(bl); j++)
693       cf_pred[j] = get_Block_cfgpred(bl, j-i);
694     for (j = j; j < arity; j++)
695       cf_pred[j] = get_Block_cfgpred(end_bl, j-get_Block_n_cfgpreds(bl) +1);
696     set_irn_in(end_bl, arity, cf_pred);
697     free(cf_pred);
698   }
699
700   /** Turn cse back on. **/
701   set_optimize(rem_opt);
702 }
703
704 /********************************************************************/
705 /* Apply inlineing to small methods.                                */
706 /********************************************************************/
707
708 static int pos;
709
710 /* It makes no sense to inline too many calls in one procedure. Anyways,
711    I didn't get a version with NEW_ARR_F to run. */
712 #define MAX_INLINE 1024
713
714 static void collect_calls(ir_node *call, void *env) {
715   ir_node **calls = (ir_node **)env;
716   ir_node *addr;
717   tarval *tv;
718   ir_graph *called_irg;
719
720   if (get_irn_op(call) != op_Call) return;
721
722   addr = get_Call_ptr(call);
723   if (get_irn_op(addr) == op_Const) {
724     /* Check whether the constant is the pointer to a compiled entity. */
725     tv = get_Const_tarval(addr);
726     if (tv->u.p.ent) {
727       called_irg = get_entity_irg(tv->u.p.ent);
728       if (called_irg && pos < MAX_INLINE) {
729         /* The Call node calls a locally defined method.  Remember to inline. */
730         calls[pos] = call;
731         pos++;
732       }
733     }
734   }
735 }
736
737 /* Inlines all small methods at call sites where the called address comes
738    from a Const node that references the entity representing the called
739    method.
740    The size argument is a rough measure for the code size of the method:
741    Methods where the obstack containing the firm graph is smaller than
742    size are inlined. */
743 void inline_small_irgs(ir_graph *irg, int size) {
744   int i;
745   ir_node *calls[MAX_INLINE];
746   ir_graph *rem = current_ir_graph;
747
748   if (!(get_optimize() && get_opt_inline())) return;
749
750   current_ir_graph = irg;
751   /* Handle graph state */
752   assert(get_irg_phase_state(current_ir_graph) != phase_building);
753
754   /* Find Call nodes to inline.
755      (We can not inline during a walk of the graph, as inlineing the same
756      method several times changes the visited flag of the walked graph:
757      after the first inlineing visited of the callee equals visited of
758      the caller.  With the next inlineing both are increased.) */
759   pos = 0;
760   irg_walk(get_irg_end(irg), NULL, collect_calls, (void *) calls);
761
762   if ((pos > 0) && (pos < MAX_INLINE)) {
763     /* There are calls to inline */
764     collect_phiprojs(irg);
765     for (i = 0; i < pos; i++) {
766       char buf[1024];
767       tarval *tv;
768       ir_graph *callee;
769       tv = get_Const_tarval(get_Call_ptr(calls[i]));
770       callee = get_entity_irg(tv->u.p.ent);
771       if ((_obstack_memory_used(callee->obst) - obstack_room(callee->obst)) < size) {
772         inline_method(calls[i], callee);
773       }
774     }
775   }
776
777   current_ir_graph = rem;
778 }
779
780
781 /********************************************************************/
782 /*  Code Placement.  Pinns all floating nodes to a block where they */
783 /*  will be executed only if needed.                                */
784 /********************************************************************/
785
786 static pdeq *worklist;          /* worklist of ir_node*s */
787
788 /* Find the earliest correct block for N.  --- Place N into the
789    same Block as its dominance-deepest Input.  */
790 static void
791 place_floats_early (ir_node *n)
792 {
793   int i, start;
794
795   /* we must not run into an infinite loop */
796   assert (irn_not_visited(n));
797   mark_irn_visited(n);
798
799   /* Place floating nodes. */
800   if (get_op_pinned(get_irn_op(n)) == floats) {
801     int depth = 0;
802     ir_node *b = new_Bad();   /* The block to place this node in */
803
804     assert(get_irn_op(n) != op_Block);
805
806     if ((get_irn_op(n) == op_Const) ||
807         (get_irn_op(n) == op_SymConst) ||
808         (is_Bad(n))) {
809       /* These nodes will not be placed by the loop below. */
810       b = get_irg_start_block(current_ir_graph);
811       depth = 1;
812     }
813
814     /* find the block for this node. */
815     for (i = 0; i < get_irn_arity(n); i++) {
816       ir_node *dep = get_irn_n(n, i);
817       ir_node *dep_block;
818       if ((irn_not_visited(dep)) &&
819           (get_op_pinned(get_irn_op(dep)) == floats)) {
820         place_floats_early (dep);
821       }
822       /* Because all loops contain at least one pinned node, now all
823          our inputs are either pinned or place_early has already
824          been finished on them.  We do not have any unfinished inputs!  */
825       dep_block = get_nodes_Block(dep);
826       if ((!is_Bad(dep_block)) &&
827           (get_Block_dom_depth(dep_block) > depth)) {
828         b = dep_block;
829         depth = get_Block_dom_depth(dep_block);
830       }
831       /* Avoid that the node is placed in the Start block */
832       if ((depth == 1) && (get_Block_dom_depth(get_nodes_Block(n)) > 1)) {
833         b = get_Block_cfg_out(get_irg_start_block(current_ir_graph), 0);
834         assert(b != get_irg_start_block(current_ir_graph));
835         depth = 2;
836       }
837     }
838     set_nodes_Block(n, b);
839   }
840
841   /* Add predecessors of non floating nodes on worklist. */
842   start = (get_irn_op(n) == op_Block) ? 0 : -1;
843   for (i = start; i < get_irn_arity(n); i++) {
844     ir_node *pred = get_irn_n(n, i);
845     if (irn_not_visited(pred)) {
846       pdeq_putr (worklist, pred);
847     }
848   }
849 }
850
851 /* Floating nodes form subgraphs that begin at nodes as Const, Load,
852    Start, Call and end at pinned nodes as Store, Call.  Place_early
853    places all floating nodes reachable from its argument through floating
854    nodes and adds all beginnings at pinned nodes to the worklist. */
855 INLINE void place_early () {
856   assert(worklist);
857   inc_irg_visited(current_ir_graph);
858
859   /* this inits the worklist */
860   place_floats_early (get_irg_end(current_ir_graph));
861
862   /* Work the content of the worklist. */
863   while (!pdeq_empty (worklist)) {
864     ir_node *n = pdeq_getl (worklist);
865     if (irn_not_visited(n)) place_floats_early (n);
866   }
867
868   set_irg_outs_inconsistent(current_ir_graph);
869   current_ir_graph->pinned = pinned;
870 }
871
872
873 /* deepest common dominance ancestor of DCA and CONSUMER of PRODUCER */
874 static ir_node *
875 consumer_dom_dca (ir_node *dca, ir_node *consumer, ir_node *producer)
876 {
877   ir_node *block = NULL;
878
879   /* Compute the latest block into which we can place a node so that it is
880      before consumer. */
881   if (get_irn_op(consumer) == op_Phi) {
882     /* our comsumer is a Phi-node, the effective use is in all those
883        blocks through which the Phi-node reaches producer */
884     int i;
885     ir_node *phi_block = get_nodes_Block(consumer);
886     for (i = 0;  i < get_irn_arity(consumer); i++) {
887       if (get_irn_n(consumer, i) == producer) {
888         block = get_nodes_Block(get_Block_cfgpred(phi_block, i));
889       }
890     }
891   } else {
892     assert(is_no_Block(consumer));
893     block = get_nodes_Block(consumer);
894   }
895
896   /* Compute the deepest common ancestor of block and dca. */
897   assert(block);
898   if (!dca) return block;
899   while (get_Block_dom_depth(block) > get_Block_dom_depth(dca))
900     block = get_Block_idom(block);
901   while (get_Block_dom_depth(dca) > get_Block_dom_depth(block))
902     dca = get_Block_idom(dca);
903   while (block != dca)
904     { block = get_Block_idom(block); dca = get_Block_idom(dca); }
905
906   return dca;
907 }
908
909 INLINE int get_irn_loop_depth(ir_node *n) {
910   return get_loop_depth(get_irn_loop(n));
911 }
912
913 /* Move n to a block with less loop depth than it's current block. The
914    new block must be dominated by early. */
915 static void
916 move_out_of_loops (ir_node *n, ir_node *early)
917 {
918   ir_node *best, *dca;
919   assert(n && early);
920
921
922   /* Find the region deepest in the dominator tree dominating
923      dca with the least loop nesting depth, but still dominated
924      by our early placement. */
925   dca = get_nodes_Block(n);
926   best = dca;
927   while (dca != early) {
928     dca = get_Block_idom(dca);
929     if (!dca) break; /* should we put assert(dca)? */
930     if (get_irn_loop_depth(dca) < get_irn_loop_depth(best)) {
931       best = dca;
932     }
933   }
934   if (best != get_nodes_Block(n)) {
935     /* debug output
936     printf("Moving out of loop: "); DDMN(n);
937     printf(" Outermost block: "); DDMN(early);
938     printf(" Best block: "); DDMN(best);
939     printf(" Innermost block: "); DDMN(get_nodes_Block(n));
940     */
941     set_nodes_Block(n, best);
942   }
943 }
944
945 /* Find the latest legal block for N and place N into the
946    `optimal' Block between the latest and earliest legal block.
947    The `optimal' block is the dominance-deepest block of those
948    with the least loop-nesting-depth.  This places N out of as many
949    loops as possible and then makes it as controldependant as
950    possible. */
951 static void
952 place_floats_late (ir_node *n)
953 {
954   int i;
955   ir_node *early;
956
957   assert (irn_not_visited(n)); /* no multiple placement */
958
959   /* no need to place block nodes, control nodes are already placed. */
960   if ((get_irn_op(n) != op_Block) &&
961       (!is_cfop(n)) &&
962       (get_irn_mode(n) != mode_X)) {
963     /* Remember the early palacement of this block to move it
964        out of loop no further than the early placement. */
965     early = get_nodes_Block(n);
966     /* Assure that our users are all placed, except the Phi-nodes.
967        --- Each dataflow cycle contains at least one Phi-node.  We
968        have to break the `user has to be placed before the
969        producer' dependance cycle and the Phi-nodes are the
970        place to do so, because we need to base our placement on the
971        final region of our users, which is OK with Phi-nodes, as they
972        are pinned, and they never have to be placed after a
973        producer of one of their inputs in the same block anyway. */
974     for (i = 0; i < get_irn_n_outs(n); i++) {
975       ir_node *succ = get_irn_out(n, i);
976       if (irn_not_visited(succ) && (get_irn_op(succ) != op_Phi))
977         place_floats_late (succ);
978     }
979
980     /* We have to determine the final block of this node... except for
981        constants. */
982     if ((get_op_pinned(get_irn_op(n)) == floats) &&
983         (get_irn_op(n) != op_Const) &&
984         (get_irn_op(n) != op_SymConst)) {
985       ir_node *dca = NULL;      /* deepest common ancestor in the
986                                    dominator tree of all nodes'
987                                    blocks depending on us; our final
988                                    placement has to dominate DCA. */
989       for (i = 0; i < get_irn_n_outs(n); i++) {
990         dca = consumer_dom_dca (dca, get_irn_out(n, i), n);
991       }
992       set_nodes_Block(n, dca);
993
994       move_out_of_loops (n, early);
995     }
996   }
997
998   mark_irn_visited(n);
999
1000   /* Add predecessors of all non-floating nodes on list. (Those of floating
1001      nodes are placeded already and therefore are marked.)  */
1002   for (i = 0; i < get_irn_n_outs(n); i++) {
1003     if (irn_not_visited(get_irn_out(n, i))) {
1004       pdeq_putr (worklist, get_irn_out(n, i));
1005     }
1006   }
1007 }
1008
1009 INLINE void place_late() {
1010   assert(worklist);
1011   inc_irg_visited(current_ir_graph);
1012
1013   /* This fills the worklist initially. */
1014   place_floats_late(get_irg_start_block(current_ir_graph));
1015   /* And now empty the worklist again... */
1016   while (!pdeq_empty (worklist)) {
1017     ir_node *n = pdeq_getl (worklist);
1018     if (irn_not_visited(n)) place_floats_late(n);
1019   }
1020 }
1021
1022 void place_code(ir_graph *irg) {
1023   ir_graph *rem = current_ir_graph;
1024   current_ir_graph = irg;
1025
1026   if (!(get_optimize() && get_opt_global_cse())) return;
1027
1028   /* Handle graph state */
1029   assert(get_irg_phase_state(irg) != phase_building);
1030   if (get_irg_dom_state(irg) != dom_consistent)
1031     compute_doms(irg);
1032
1033   construct_backedges(irg);
1034
1035   /* Place all floating nodes as early as possible. This guarantees
1036      a legal code placement. */
1037   worklist = new_pdeq ();
1038   place_early();
1039
1040   /* place_early invalidates the outs, place_late needs them. */
1041   compute_outs(irg);
1042   /* Now move the nodes down in the dominator tree. This reduces the
1043      unnecessary executions of the node. */
1044   place_late();
1045
1046   set_irg_outs_inconsistent(current_ir_graph);
1047   del_pdeq (worklist);
1048   current_ir_graph = rem;
1049 }
1050
1051
1052
1053 /********************************************************************/
1054 /* Control flow optimization.                                       */
1055 /* Removes Bad control flow predecessors and empty blocks.  A block */
1056 /* is empty if it contains only a Jmp node.                         */
1057 /* */
1058 /********************************************************************/
1059
1060
1061 static void merge_blocks(ir_node *n, void *env) {
1062   int i;
1063   set_irn_link(n, NULL);
1064
1065   if (get_irn_op(n) == op_Block) {
1066     /* Remove Tuples */
1067     for (i = 0; i < get_Block_n_cfgpreds(n); i++)
1068       set_Block_cfgpred(n, i, skip_Tuple(get_Block_cfgpred(n, i)));
1069   } else if (get_irn_mode(n) == mode_X) {
1070     /* We will soon visit a block.  Optimize it before visiting! */
1071     ir_node *b = get_nodes_Block(n);
1072     ir_node *new = equivalent_node(b);
1073     while (irn_not_visited(b) && (!is_Bad(new)) && (new != b)) {
1074       /* We would have to run gigo if new is bad. */
1075       if (get_optimize() && get_opt_control_flow()) exchange (b, new);
1076       b = new;
1077       new = equivalent_node(b);
1078     }
1079     if (is_Bad(new)) exchange (n, new_Bad());
1080   }
1081 }
1082
1083 static void collect_nodes(ir_node *n, void *env) {
1084   if (is_no_Block(n)) {
1085     ir_node *b = get_nodes_Block(n);
1086
1087     if ((get_irn_op(n) == op_Phi)) {
1088       /* Collect Phi nodes to compact ins along with block's ins. */
1089       set_irn_link(n, get_irn_link(b));
1090       set_irn_link(b, n);
1091     } else if (get_irn_op(n) != op_Jmp) {  /* Check for non empty block. */
1092       mark_Block_block_visited(b);
1093     }
1094   }
1095 }
1096
1097 /* Returns true if pred is pred of block */
1098 int is_pred_of(ir_node *pred, ir_node *b) {
1099   int i;
1100   for (i = 0; i < get_Block_n_cfgpreds(b); i++) {
1101     ir_node *b_pred = get_nodes_Block(get_Block_cfgpred(b, i));
1102     if (b_pred == pred) return 1;
1103   }
1104   return 0;
1105 }
1106
1107 int test_whether_dispensable(ir_node *b, int pos) {
1108   int i, j, n_preds = 1;
1109   int dispensable = 1;
1110   ir_node *cfop = get_Block_cfgpred(b, pos);
1111   ir_node *pred = get_nodes_Block(cfop);
1112
1113   if (get_Block_block_visited(pred) + 1
1114       < get_irg_block_visited(current_ir_graph)) {
1115     if (!get_optimize() || !get_opt_control_flow()) {
1116       /* Mark block so that is will not be removed. */
1117       set_Block_block_visited(pred, get_irg_block_visited(current_ir_graph)-1);
1118       return 1;
1119     }
1120     /* Seems to be empty. */
1121     if (!get_irn_link(b)) {
1122       /* There are no Phi nodes ==> dispensable. */
1123       n_preds = get_Block_n_cfgpreds(pred);
1124     } else {
1125       /* b's pred blocks and pred's pred blocks must be pairwise disjunct.
1126          Work preds < pos as if they were already removed. */
1127       for (i = 0; i < pos; i++) {
1128         ir_node *b_pred = get_nodes_Block(get_Block_cfgpred(b, i));
1129         if (get_Block_block_visited(b_pred) + 1
1130             < get_irg_block_visited(current_ir_graph)) {
1131           for (j = 0; j < get_Block_n_cfgpreds(b_pred); j++) {
1132             ir_node *b_pred_pred = get_nodes_Block(get_Block_cfgpred(b_pred, j));
1133             if (is_pred_of(b_pred_pred, pred)) dispensable = 0;
1134           }
1135         } else {
1136           if (is_pred_of(b_pred, pred)) dispensable = 0;
1137         }
1138       }
1139       for (i = pos +1; i < get_Block_n_cfgpreds(b); i++) {
1140         ir_node *b_pred = get_nodes_Block(get_Block_cfgpred(b, i));
1141         if (is_pred_of(b_pred, pred)) dispensable = 0;
1142       }
1143       if (!dispensable) {
1144         set_Block_block_visited(pred, get_irg_block_visited(current_ir_graph)-1);
1145         n_preds = 1;
1146       } else {
1147         n_preds = get_Block_n_cfgpreds(pred);
1148       }
1149     }
1150   }
1151
1152   return n_preds;
1153 }
1154
1155 void optimize_blocks(ir_node *b, void *env) {
1156   int i, j, k, max_preds, n_preds;
1157   ir_node *pred, *phi;
1158   ir_node **in;
1159
1160   /* Count the number of predecessor if this block is merged with pred blocks
1161      that are empty. */
1162   max_preds = 0;
1163   for (i = 0; i < get_Block_n_cfgpreds(b); i++) {
1164     max_preds += test_whether_dispensable(b, i);
1165   }
1166   in = (ir_node **) malloc(max_preds * sizeof(ir_node *));
1167
1168   /** Debug output **
1169   printf(" working on "); DDMN(b);
1170   for (i = 0; i < get_Block_n_cfgpreds(b); i++) {
1171     pred = get_nodes_Block(get_Block_cfgpred(b, i));
1172     if (is_Bad(get_Block_cfgpred(b, i))) {
1173       printf("  removing Bad %i\n ", i);
1174     } else if (get_Block_block_visited(pred) +1
1175                < get_irg_block_visited(current_ir_graph)) {
1176       printf("  removing pred %i ", i); DDMN(pred);
1177     } else { printf("  Nothing to do for "); DDMN(pred); }
1178   }
1179   ** end Debug output **/
1180
1181   /** Fix the Phi nodes **/
1182   phi = get_irn_link(b);
1183   while (phi) {
1184     assert(get_irn_op(phi) == op_Phi);
1185     /* Find the new predecessors for the Phi */
1186     n_preds = 0;
1187     for (i = 0; i < get_Block_n_cfgpreds(b); i++) {
1188       pred = get_nodes_Block(get_Block_cfgpred(b, i));
1189       if (is_Bad(get_Block_cfgpred(b, i))) {
1190         /* Do nothing */
1191       } else if (get_Block_block_visited(pred) +1
1192                  < get_irg_block_visited(current_ir_graph)) {
1193         /* It's an empty block and not yet visited. */
1194         ir_node *phi_pred = get_Phi_pred(phi, i);
1195         for (j = 0; j < get_Block_n_cfgpreds(pred); j++) {
1196           if (get_nodes_Block(phi_pred) == pred) {
1197             assert(get_irn_op(phi_pred) == op_Phi);  /* Block is empty!! */
1198             in[n_preds] = get_Phi_pred(phi_pred, j);
1199           } else {
1200             in[n_preds] = phi_pred;
1201           }
1202           n_preds++;
1203         }
1204 #if 0
1205         /* @@@ hier brauche ich schleifeninformation!!! Wenn keine Rueckwaertskante
1206            dann darfs auch keine Verwendung geben. */
1207         if (get_nodes_Block(phi_pred) == pred) {
1208           /* remove the Phi as it might be kept alive. Further there
1209              might be other users. */
1210           exchange(phi_pred, phi);  /* geht, is aber doch semantisch falsch! */
1211         }
1212 #endif
1213       } else {
1214         in[n_preds] = get_Phi_pred(phi, i);
1215         n_preds ++;
1216       }
1217     }
1218     /* Fix the node */
1219     set_irn_in(phi, n_preds, in);
1220     phi = get_irn_link(phi);
1221   }
1222
1223   /** Move Phi nodes from removed blocks to this one.
1224       This happens only if merge between loop backedge and single loop entry. **/
1225   for (k = 0; k < get_Block_n_cfgpreds(b); k++) {
1226     pred = get_nodes_Block(get_Block_cfgpred(b, k));
1227     if (get_Block_block_visited(pred) +1
1228         < get_irg_block_visited(current_ir_graph)) {
1229       phi = get_irn_link(pred);
1230       while (phi) {
1231         if (get_irn_op(phi) == op_Phi) {
1232           set_nodes_Block(phi, b);
1233
1234           n_preds = 0;
1235           for (i = 0; i < k; i++) {
1236             pred = get_nodes_Block(get_Block_cfgpred(b, i));
1237             if (is_Bad(get_Block_cfgpred(b, i))) {
1238               /* Do nothing */
1239             } else if (get_Block_block_visited(pred) +1
1240                        < get_irg_block_visited(current_ir_graph)) {
1241               /* It's an empty block and not yet visited. */
1242               for (j = 0; j < get_Block_n_cfgpreds(pred); j++) {
1243                 /* @@@ Hier brauche ich schleifeninformation!!! Kontrllflusskante
1244                    muss Rueckwaertskante sein! (An allen vier in[n_preds] = phi
1245                    Anweisungen.) Trotzdem tuts bisher!! */
1246                 in[n_preds] = phi;
1247                 n_preds++;
1248               }
1249             } else {
1250               in[n_preds] = phi;
1251               n_preds++;
1252             }
1253           }
1254           for (i = 0; i < get_Phi_n_preds(phi); i++) {
1255             in[n_preds] = get_Phi_pred(phi, i);
1256             n_preds++;
1257           }
1258           for (i = k+1; i < get_Block_n_cfgpreds(b); i++) {
1259             pred = get_nodes_Block(get_Block_cfgpred(b, i));
1260             if (is_Bad(get_Block_cfgpred(b, i))) {
1261               /* Do nothing */
1262             } else if (get_Block_block_visited(pred) +1
1263                        < get_irg_block_visited(current_ir_graph)) {
1264               /* It's an empty block and not yet visited. */
1265               for (j = 0; j < get_Block_n_cfgpreds(pred); j++) {
1266                 in[n_preds] = phi;
1267                 n_preds++;
1268               }
1269             } else {
1270               in[n_preds] = phi;
1271               n_preds++;
1272             }
1273           }
1274           set_irn_in(phi, n_preds, in);
1275         }
1276         phi = get_irn_link(phi);
1277       }
1278     }
1279   }
1280
1281   /** Fix the block **/
1282   n_preds = 0;
1283   for (i = 0; i < get_Block_n_cfgpreds(b); i++) {
1284     pred = get_nodes_Block(get_Block_cfgpred(b, i));
1285     if (is_Bad(get_Block_cfgpred(b, i))) {
1286       /* Do nothing */
1287     } else if (get_Block_block_visited(pred) +1
1288                < get_irg_block_visited(current_ir_graph)) {
1289       /* It's an empty block and not yet visited. */
1290       assert(get_Block_n_cfgpreds(b) > 1);
1291                         /* Else it should be optimized by equivalent_node. */
1292       for (j = 0; j < get_Block_n_cfgpreds(pred); j++) {
1293         in[n_preds] = get_Block_cfgpred(pred, j);
1294         n_preds++;
1295       }
1296       /* Remove block as it might be kept alive. */
1297       exchange(pred, b/*new_Bad()*/);
1298     } else {
1299       in[n_preds] = get_Block_cfgpred(b, i);
1300       n_preds ++;
1301     }
1302   }
1303   set_irn_in(b, n_preds, in);
1304   free(in);
1305 }
1306
1307 void optimize_cf(ir_graph *irg) {
1308   int i;
1309   ir_node **in;
1310   ir_node *end = get_irg_end(irg);
1311   ir_graph *rem = current_ir_graph;
1312   current_ir_graph = irg;
1313
1314
1315   /* Handle graph state */
1316   assert(get_irg_phase_state(irg) != phase_building);
1317   if (get_irg_outs_state(current_ir_graph) == outs_consistent)
1318     set_irg_outs_inconsistent(current_ir_graph);
1319   if (get_irg_dom_state(current_ir_graph) == dom_consistent)
1320     set_irg_dom_inconsistent(current_ir_graph);
1321
1322   /* Use block visited flag to mark non-empty blocks. */
1323   inc_irg_block_visited(irg);
1324   irg_walk(end, merge_blocks, collect_nodes, NULL);
1325
1326   /* Optimize the standard code. */
1327   irg_block_walk(get_irg_end_block(irg), optimize_blocks, NULL, NULL);
1328
1329   /* Walk all keep alives, optimize them if block, add to new in-array
1330      for end if useful. */
1331   in = NEW_ARR_F (ir_node *, 1);
1332   in[0] = get_nodes_Block(end);
1333
1334   inc_irg_visited(current_ir_graph);
1335   for(i = 0; i < get_End_n_keepalives(end); i++) {
1336     ir_node *ka = get_End_keepalive(end, i);
1337     if (irn_not_visited(ka)) {
1338       if ((get_irn_op(ka) == op_Block) && Block_not_block_visited(ka)) {
1339         set_irg_block_visited(current_ir_graph,  /* Don't walk all the way to Start. */
1340                               get_irg_block_visited(current_ir_graph)-1);
1341         irg_block_walk(ka, optimize_blocks, NULL, NULL);
1342         mark_irn_visited(ka);
1343         ARR_APP1 (ir_node *, in, ka);
1344       } else if (get_irn_op(ka) == op_Phi) {
1345         mark_irn_visited(ka);
1346         ARR_APP1 (ir_node *, in, ka);
1347       }
1348     }
1349   }
1350   /* DEL_ARR_F(end->in);   GL @@@ tut nicht ! */
1351   end->in = in;
1352
1353   current_ir_graph = rem;
1354 }