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