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