a360ee6187ae43b94879de0326524f07864af00e
[libfirm] / ir / ir / irgopt.c
1 /*
2  * Project:     libFIRM
3  * File name:   ir/ir/irgopt.c
4  * Purpose:     Optimizations for a whole ir graph, i.e., a procedure.
5  * Author:      Christian Schaefer, Goetz Lindenmaier
6  * Modified by: Sebastian Felis
7  * Created:
8  * CVS-ID:      $Id$
9  * Copyright:   (c) 1998-2003 Universität Karlsruhe
10  * Licence:     This file protected by GPL -  GNU GENERAL PUBLIC LICENSE.
11  */
12
13
14 #ifdef HAVE_CONFIG_H
15 # include <config.h>
16 #endif
17
18 #include <assert.h>
19 #include <stdbool.h>
20
21 #include "irnode_t.h"
22 #include "irgraph_t.h"
23 #include "irprog_t.h"
24
25 #include "ircons.h"
26 #include "iropt_t.h"
27 #include "irgopt.h"
28 #include "irgmod.h"
29 #include "irgwalk.h"
30
31 #include "array.h"
32 #include "pset.h"
33 #include "eset.h"
34 #include "pdeq.h"       /* Fuer code placement */
35
36 #include "irouts.h"
37 #include "irloop_t.h"
38 #include "irbackedge_t.h"
39 #include "cgana.h"
40
41 #include "irflag_t.h"
42 #include "firmstat.h"
43
44 /* Defined in iropt.c */
45 pset *new_identities (void);
46 void  del_identities (pset *value_table);
47 void  add_identities   (pset *value_table, ir_node *node);
48
49 /*------------------------------------------------------------------*/
50 /* apply optimizations of iropt to all nodes.                       */
51 /*------------------------------------------------------------------*/
52
53 static void init_link (ir_node *n, void *env) {
54   set_irn_link(n, NULL);
55 }
56
57 #if 0   /* Old version. Avoids Ids.
58        This is not necessary:  we do a postwalk, and get_irn_n
59        removes ids anyways.  So it's much cheaper to call the
60        optimization less often and use the exchange() algorithm. */
61 static void
62 optimize_in_place_wrapper (ir_node *n, void *env) {
63   int i, irn_arity;
64   ir_node *optimized, *old;
65
66   irn_arity = get_irn_arity(n);
67   for (i = 0; i < irn_arity; i++) {
68     /* get_irn_n skips Id nodes, so comparison old != optimized does not
69        show all optimizations. Therefore always set new predecessor. */
70     old = get_irn_intra_n(n, i);
71     optimized = optimize_in_place_2(old);
72     set_irn_n(n, i, optimized);
73   }
74
75   if (get_irn_op(n) == op_Block) {
76     optimized = optimize_in_place_2(n);
77     if (optimized != n) exchange (n, optimized);
78   }
79 }
80 #else
81 static void
82 optimize_in_place_wrapper (ir_node *n, void *env) {
83   ir_node *optimized = optimize_in_place_2(n);
84   if (optimized != n) exchange (n, optimized);
85 }
86 #endif
87
88
89
90 void
91 local_optimize_graph (ir_graph *irg) {
92   ir_graph *rem = current_ir_graph;
93   current_ir_graph = irg;
94
95   /* Handle graph state */
96   assert(get_irg_phase_state(irg) != phase_building);
97   if (get_opt_global_cse())
98     set_irg_pinned(current_ir_graph, floats);
99   if (get_irg_outs_state(current_ir_graph) == outs_consistent)
100     set_irg_outs_inconsistent(current_ir_graph);
101   if (get_irg_dom_state(current_ir_graph) == dom_consistent)
102     set_irg_dom_inconsistent(current_ir_graph);
103   set_irg_loopinfo_inconsistent(current_ir_graph);
104
105
106   /* Clean the value_table in irg for the cse. */
107   del_identities(irg->value_table);
108   irg->value_table = new_identities();
109
110   /* walk over the graph */
111   irg_walk(irg->end, init_link, optimize_in_place_wrapper, NULL);
112
113   current_ir_graph = rem;
114 }
115
116 /*------------------------------------------------------------------*/
117 /* Routines for dead node elimination / copying garbage collection  */
118 /* of the obstack.                                                  */
119 /*------------------------------------------------------------------*/
120
121 /**
122  * Remember the new node in the old node by using a field all nodes have.
123  */
124 static INLINE void
125 set_new_node (ir_node *old, ir_node *new)
126 {
127   old->link = new;
128 }
129
130 /**
131  * Get this new node, before the old node is forgotton.
132  */
133 static INLINE ir_node *
134 get_new_node (ir_node * n)
135 {
136   return n->link;
137 }
138
139 /**
140  * We use the block_visited flag to mark that we have computed the
141  * number of useful predecessors for this block.
142  * Further we encode the new arity in this flag in the old blocks.
143  * Remembering the arity is useful, as it saves a lot of pointer
144  * accesses.  This function is called for all Phi and Block nodes
145  * in a Block.
146  */
147 static INLINE int
148 compute_new_arity(ir_node *b) {
149   int i, res, irn_arity;
150   int irg_v, block_v;
151
152   irg_v = get_irg_block_visited(current_ir_graph);
153   block_v = get_Block_block_visited(b);
154   if (block_v >= irg_v) {
155     /* we computed the number of preds for this block and saved it in the
156        block_v flag */
157     return block_v - irg_v;
158   } else {
159     /* compute the number of good predecessors */
160     res = irn_arity = get_irn_arity(b);
161     for (i = 0; i < irn_arity; i++)
162       if (get_irn_opcode(get_irn_n(b, i)) == iro_Bad) res--;
163     /* save it in the flag. */
164     set_Block_block_visited(b, irg_v + res);
165     return res;
166   }
167 }
168
169 /* TODO: add an ir_op operation */
170 static INLINE void new_backedge_info(ir_node *n) {
171   switch(get_irn_opcode(n)) {
172   case iro_Block:
173     n->attr.block.cg_backedge = NULL;
174     n->attr.block.backedge = new_backedge_arr(current_ir_graph->obst, get_irn_arity(n));
175     break;
176   case iro_Phi:
177     n->attr.phi_backedge = new_backedge_arr(current_ir_graph->obst, get_irn_arity(n));
178     break;
179   case iro_Filter:
180     n->attr.filter.backedge = new_backedge_arr(current_ir_graph->obst, get_irn_arity(n));
181     break;
182   default: ;
183   }
184 }
185
186 /**
187  * Copies the node to the new obstack. The Ins of the new node point to
188  * the predecessors on the old obstack.  For block/phi nodes not all
189  * predecessors might be copied.  n->link points to the new node.
190  * For Phi and Block nodes the function allocates in-arrays with an arity
191  * only for useful predecessors.  The arity is determined by counting
192  * the non-bad predecessors of the block.
193  */
194 static void
195 copy_node (ir_node *n, void *env) {
196   ir_node *nn, *block;
197   int new_arity;
198   opcode op = get_irn_opcode(n);
199   /* The end node looses it's flexible in array.  This doesn't matter,
200      as dead node elimination builds End by hand, inlineing doesn't use
201      the End node. */
202   /* assert(n->op == op_End ||  ((_ARR_DESCR(n->in))->cookie != ARR_F_MAGIC)); */
203
204   if (op == iro_Bad) {
205     /* node copied already */
206     return;
207   } else if (op == iro_Block) {
208     block = NULL;
209     new_arity = compute_new_arity(n);
210     n->attr.block.graph_arr = NULL;
211   } else {
212     block = get_nodes_Block(n);
213     if (get_irn_opcode(n) == iro_Phi) {
214       new_arity = compute_new_arity(block);
215     } else {
216       new_arity = get_irn_arity(n);
217     }
218   }
219   nn = new_ir_node(get_irn_dbg_info(n),
220            current_ir_graph,
221            block,
222            get_irn_op(n),
223            get_irn_mode(n),
224            new_arity,
225            get_irn_in(n));
226   /* Copy the attributes.  These might point to additional data.  If this
227      was allocated on the old obstack the pointers now are dangling.  This
228      frees e.g. the memory of the graph_arr allocated in new_immBlock. */
229   copy_attrs(n, nn);
230   new_backedge_info(nn);
231   set_new_node(n, nn);
232
233   /*  printf("\n old node: "); DDMSG2(n);
234       printf(" new node: "); DDMSG2(nn); */
235
236 }
237
238 /**
239  * Copies new predecessors of old node to new node remembered in link.
240  * Spare the Bad predecessors of Phi and Block nodes.
241  */
242 static void
243 copy_preds (ir_node *n, void *env) {
244   ir_node *nn, *block;
245   int i, j, irn_arity;
246
247   nn = get_new_node(n);
248
249   /* printf("\n old node: "); DDMSG2(n);
250      printf(" new node: "); DDMSG2(nn);
251      printf(" arities: old: %d, new: %d\n", get_irn_arity(n), get_irn_arity(nn)); */
252
253   if (get_irn_opcode(n) == iro_Block) {
254     /* Don't copy Bad nodes. */
255     j = 0;
256     irn_arity = get_irn_arity(n);
257     for (i = 0; i < irn_arity; i++)
258       if (get_irn_opcode(get_irn_n(n, i)) != iro_Bad) {
259     set_irn_n (nn, j, get_new_node(get_irn_n(n, i)));
260     /*if (is_backedge(n, i)) set_backedge(nn, j);*/
261     j++;
262       }
263     /* repair the block visited flag from above misuse. Repair it in both
264        graphs so that the old one can still be used. */
265     set_Block_block_visited(nn, 0);
266     set_Block_block_visited(n, 0);
267     /* Local optimization could not merge two subsequent blocks if
268        in array contained Bads.  Now it's possible.
269        We don't call optimize_in_place as it requires
270        that the fields in ir_graph are set properly. */
271     if ((get_opt_control_flow_straightening()) &&
272     (get_Block_n_cfgpreds(nn) == 1) &&
273     (get_irn_op(get_Block_cfgpred(nn, 0)) == op_Jmp)) {
274       ir_node *old = get_nodes_Block(get_Block_cfgpred(nn, 0));
275       if (nn == old) {
276     /* Jmp jumps into the block it is in -- deal self cycle. */
277     assert(is_Bad(get_new_node(get_irg_bad(current_ir_graph))));
278     exchange(nn, get_new_node(get_irg_bad(current_ir_graph)));
279       } else {
280     exchange(nn, old);
281       }
282     }
283   } else if (get_irn_opcode(n) == iro_Phi) {
284     /* Don't copy node if corresponding predecessor in block is Bad.
285        The Block itself should not be Bad. */
286     block = get_nodes_Block(n);
287     set_irn_n (nn, -1, get_new_node(block));
288     j = 0;
289     irn_arity = get_irn_arity(n);
290     for (i = 0; i < irn_arity; i++)
291       if (get_irn_opcode(get_irn_n(block, i)) != iro_Bad) {
292     set_irn_n (nn, j, get_new_node(get_irn_n(n, i)));
293     /*if (is_backedge(n, i)) set_backedge(nn, j);*/
294     j++;
295       }
296     /* If the pre walker reached this Phi after the post walker visited the
297        block block_visited is > 0. */
298     set_Block_block_visited(get_nodes_Block(n), 0);
299     /* Compacting the Phi's ins might generate Phis with only one
300        predecessor. */
301     if (get_irn_arity(n) == 1)
302       exchange(n, get_irn_n(n, 0));
303   } else {
304     irn_arity = get_irn_arity(n);
305     for (i = -1; i < irn_arity; i++)
306       set_irn_n (nn, i, get_new_node(get_irn_n(n, i)));
307   }
308   /* Now the new node is complete.  We can add it to the hash table for cse.
309      @@@ inlinening aborts if we identify End. Why? */
310   if(get_irn_op(nn) != op_End)
311     add_identities (current_ir_graph->value_table, nn);
312 }
313
314 /**
315  * Copies the graph recursively, compacts the keepalive of the end node.
316  */
317 static void
318 copy_graph (void) {
319   ir_node *oe, *ne, *ob, *nb; /* old end, new end, old bad, new bad */
320   ir_node *ka;      /* keep alive */
321   int i, irn_arity;
322
323   oe = get_irg_end(current_ir_graph);
324   /* copy the end node by hand, allocate dynamic in array! */
325   ne = new_ir_node(get_irn_dbg_info(oe),
326            current_ir_graph,
327            NULL,
328            op_End,
329            mode_X,
330            -1,
331            NULL);
332   /* Copy the attributes.  Well, there might be some in the future... */
333   copy_attrs(oe, ne);
334   set_new_node(oe, ne);
335
336   ob = get_irg_bad(current_ir_graph);
337   nb =  new_ir_node(get_irn_dbg_info(ob),
338            current_ir_graph,
339            NULL,
340            op_Bad,
341            mode_T,
342            0,
343            NULL);
344   set_new_node(ob, nb);
345
346   /* copy the live nodes */
347   irg_walk(get_nodes_Block(oe), copy_node, copy_preds, NULL);
348   /* copy_preds for the end node ... */
349   set_nodes_Block(ne, get_new_node(get_nodes_Block(oe)));
350   set_nodes_Block(nb, get_new_node(get_nodes_Block(ob)));
351
352   /*- ... and now the keep alives. -*/
353   /* First pick the not marked block nodes and walk them.  We must pick these
354      first as else we will oversee blocks reachable from Phis. */
355   irn_arity = get_irn_arity(oe);
356   for (i = 0; i < irn_arity; i++) {
357     ka = get_irn_intra_n(oe, i);
358     if ((get_irn_op(ka) == op_Block) &&
359     (get_irn_visited(ka) < get_irg_visited(current_ir_graph))) {
360       /* We must keep the block alive and copy everything reachable */
361       set_irg_visited(current_ir_graph, get_irg_visited(current_ir_graph)-1);
362       irg_walk(ka, copy_node, copy_preds, NULL);
363       add_End_keepalive(ne, get_new_node(ka));
364     }
365   }
366
367   /* Now pick the Phis.  Here we will keep all! */
368   irn_arity = get_irn_arity(oe);
369   for (i = 0; i < irn_arity; i++) {
370     ka = get_irn_intra_n(oe, i);
371     if ((get_irn_op(ka) == op_Phi)) {
372       if (get_irn_visited(ka) < get_irg_visited(current_ir_graph)) {
373     /* We didn't copy the Phi yet.  */
374     set_irg_visited(current_ir_graph, get_irg_visited(current_ir_graph)-1);
375     irg_walk(ka, copy_node, copy_preds, NULL);
376       }
377       add_End_keepalive(ne, get_new_node(ka));
378     }
379   }
380 }
381
382 /**
383  * Copies the graph reachable from current_ir_graph->end to the obstack
384  * in current_ir_graph and fixes the environment.
385  * Then fixes the fields in current_ir_graph containing nodes of the
386  * graph.
387  */
388 static void
389 copy_graph_env (void) {
390   ir_node *old_end;
391   /* Not all nodes remembered in current_ir_graph might be reachable
392      from the end node.  Assure their link is set to NULL, so that
393      we can test whether new nodes have been computed. */
394   set_irn_link(get_irg_frame      (current_ir_graph), NULL);
395   set_irn_link(get_irg_globals    (current_ir_graph), NULL);
396   set_irn_link(get_irg_args       (current_ir_graph), NULL);
397   set_irn_link(get_irg_initial_mem(current_ir_graph), NULL);
398
399   /* we use the block walk flag for removing Bads from Blocks ins. */
400   inc_irg_block_visited(current_ir_graph);
401
402   /* copy the graph */
403   copy_graph();
404
405   /* fix the fields in current_ir_graph */
406   old_end = get_irg_end(current_ir_graph);
407   set_irg_end        (current_ir_graph, get_new_node(old_end));
408   set_irg_end_except (current_ir_graph, get_irg_end(current_ir_graph));
409   set_irg_end_reg    (current_ir_graph, get_irg_end(current_ir_graph));
410   free_End(old_end);
411   set_irg_end_block  (current_ir_graph, get_new_node(get_irg_end_block(current_ir_graph)));
412   if (get_irn_link(get_irg_frame(current_ir_graph)) == NULL) {
413     copy_node (get_irg_frame(current_ir_graph), NULL);
414     copy_preds(get_irg_frame(current_ir_graph), NULL);
415   }
416   if (get_irn_link(get_irg_globals(current_ir_graph)) == NULL) {
417     copy_node (get_irg_globals(current_ir_graph), NULL);
418     copy_preds(get_irg_globals(current_ir_graph), NULL);
419   }
420   if (get_irn_link(get_irg_initial_mem(current_ir_graph)) == NULL) {
421     copy_node (get_irg_initial_mem(current_ir_graph), NULL);
422     copy_preds(get_irg_initial_mem(current_ir_graph), NULL);
423   }
424   if (get_irn_link(get_irg_args(current_ir_graph)) == NULL) {
425     copy_node (get_irg_args(current_ir_graph), NULL);
426     copy_preds(get_irg_args(current_ir_graph), NULL);
427   }
428   set_irg_start      (current_ir_graph, get_new_node(get_irg_start(current_ir_graph)));
429
430   set_irg_start_block(current_ir_graph,
431               get_new_node(get_irg_start_block(current_ir_graph)));
432   set_irg_frame      (current_ir_graph, get_new_node(get_irg_frame(current_ir_graph)));
433   set_irg_globals    (current_ir_graph, get_new_node(get_irg_globals(current_ir_graph)));
434   set_irg_initial_mem(current_ir_graph, get_new_node(get_irg_initial_mem(current_ir_graph)));
435   set_irg_args       (current_ir_graph, get_new_node(get_irg_args(current_ir_graph)));
436
437   if (get_irn_link(get_irg_bad(current_ir_graph)) == NULL) {
438     copy_node(get_irg_bad(current_ir_graph), NULL);
439     copy_preds(get_irg_bad(current_ir_graph), NULL);
440   }
441   set_irg_bad(current_ir_graph, get_new_node(get_irg_bad(current_ir_graph)));
442 }
443
444 /**
445  * Copies all reachable nodes to a new obstack.  Removes bad inputs
446  * from block nodes and the corresponding inputs from Phi nodes.
447  * Merges single exit blocks with single entry blocks and removes
448  * 1-input Phis.
449  * Adds all new nodes to a new hash table for cse.  Does not
450  * perform cse, so the hash table might contain common subexpressions.
451  */
452 void
453 dead_node_elimination(ir_graph *irg) {
454   ir_graph *rem;
455   int rem_ipview = interprocedural_view;
456   struct obstack *graveyard_obst = NULL;
457   struct obstack *rebirth_obst   = NULL;
458
459   /* inform statistics that we started a dead-node elimination run */
460   stat_dead_node_elim_start(irg);
461
462   /* Remember external state of current_ir_graph. */
463   rem = current_ir_graph;
464   current_ir_graph = irg;
465   interprocedural_view = 0;
466
467   /* Handle graph state */
468   assert(get_irg_phase_state(current_ir_graph) != phase_building);
469   free_callee_info(current_ir_graph);
470   free_outs(current_ir_graph);
471   /* @@@ so far we loose loops when copying */
472   free_loop_information(current_ir_graph);
473
474   if (get_opt_optimize() && get_opt_dead_node_elimination()) {
475
476     /* A quiet place, where the old obstack can rest in peace,
477        until it will be cremated. */
478     graveyard_obst = irg->obst;
479
480     /* A new obstack, where the reachable nodes will be copied to. */
481     rebirth_obst = (struct obstack *) xmalloc (sizeof (struct obstack));
482     current_ir_graph->obst = rebirth_obst;
483     obstack_init (current_ir_graph->obst);
484
485     /* We also need a new hash table for cse */
486     del_identities (irg->value_table);
487     irg->value_table = new_identities ();
488
489     /* Copy the graph from the old to the new obstack */
490     copy_graph_env();
491
492     /* Free memory from old unoptimized obstack */
493     obstack_free(graveyard_obst, 0);  /* First empty the obstack ... */
494     xfree (graveyard_obst);           /* ... then free it.           */
495   }
496
497   /* inform statistics that the run is over */
498   stat_dead_node_elim_stop(irg);
499
500   current_ir_graph = rem;
501   interprocedural_view = rem_ipview;
502 }
503
504 /**
505  * Relink bad predeseccors of a block and store the old in array to the
506  * link field. This function is called by relink_bad_predecessors().
507  * The array of link field starts with the block operand at position 0.
508  * If block has bad predecessors, create a new in array without bad preds.
509  * Otherwise let in array untouched.
510  */
511 static void relink_bad_block_predecessors(ir_node *n, void *env) {
512   ir_node **new_in, *irn;
513   int i, new_irn_n, old_irn_arity, new_irn_arity = 0;
514
515   /* if link field of block is NULL, look for bad predecessors otherwise
516      this is allready done */
517   if (get_irn_op(n) == op_Block &&
518       get_irn_link(n) == NULL) {
519
520     /* save old predecessors in link field (position 0 is the block operand)*/
521     set_irn_link(n, (void *)get_irn_in(n));
522
523     /* count predecessors without bad nodes */
524     old_irn_arity = get_irn_arity(n);
525     for (i = 0; i < old_irn_arity; i++)
526       if (!is_Bad(get_irn_n(n, i))) new_irn_arity++;
527
528     /* arity changing: set new predecessors without bad nodes */
529     if (new_irn_arity < old_irn_arity) {
530       /* get new predecessor array without Block predecessor */
531       new_in = NEW_ARR_D (ir_node *, current_ir_graph->obst, (new_irn_arity+1));
532
533       /* set new predeseccors in array */
534       new_in[0] = NULL;
535       new_irn_n = 1;
536       for (i = 1; i < old_irn_arity; i++) {
537     irn = get_irn_n(n, i);
538     if (!is_Bad(irn)) new_in[new_irn_n++] = irn;
539       }
540       n->in = new_in;
541     } /* ir node has bad predecessors */
542
543   } /* Block is not relinked */
544 }
545
546 /*
547  * Relinks Bad predecesors from Bocks and Phis called by walker
548  * remove_bad_predecesors(). If n is a Block, call
549  * relink_bad_block_redecessors(). If n is a Phinode, call also the relinking
550  * function of Phi's Block. If this block has bad predecessors, relink preds
551  * of the Phinode.
552  */
553 static void relink_bad_predecessors(ir_node *n, void *env) {
554   ir_node *block, **old_in;
555   int i, old_irn_arity, new_irn_arity;
556
557   /* relink bad predeseccors of a block */
558   if (get_irn_op(n) == op_Block)
559     relink_bad_block_predecessors(n, env);
560
561   /* If Phi node relink its block and its predecessors */
562   if (get_irn_op(n) == op_Phi) {
563
564     /* Relink predeseccors of phi's block */
565     block = get_nodes_Block(n);
566     if (get_irn_link(block) == NULL)
567       relink_bad_block_predecessors(block, env);
568
569     old_in = (ir_node **)get_irn_link(block); /* Of Phi's Block */
570     old_irn_arity = ARR_LEN(old_in);
571
572     /* Relink Phi predeseccors if count of predeseccors changed */
573     if (old_irn_arity != ARR_LEN(get_irn_in(block))) {
574       /* set new predeseccors in array
575      n->in[0] remains the same block */
576       new_irn_arity = 1;
577       for(i = 1; i < old_irn_arity; i++)
578     if (!is_Bad((ir_node *)old_in[i])) n->in[new_irn_arity++] = n->in[i];
579
580       ARR_SETLEN(ir_node *, n->in, new_irn_arity);
581     }
582
583   } /* n is a Phi node */
584 }
585
586 /**
587  * Removes Bad Bad predecesors from Blocks and the corresponding
588  * inputs to Phi nodes as in dead_node_elimination but without
589  * copying the graph.
590  * On walking up set the link field to NULL, on walking down call
591  * relink_bad_predecessors() (This function stores the old in array
592  * to the link field and sets a new in array if arity of predecessors
593  * changes).
594  */
595 void remove_bad_predecessors(ir_graph *irg) {
596   irg_walk_graph(irg, init_link, relink_bad_predecessors, NULL);
597 }
598
599
600 /*--------------------------------------------------------------------*/
601 /*  Funcionality for inlining                                         */
602 /*--------------------------------------------------------------------*/
603
604 /**
605  * Copy node for inlineing.  Updates attributes that change when
606  * inlineing but not for dead node elimination.
607  *
608  * Copies the node by calling copy_node and then updates the entity if
609  * it's a local one.  env must be a pointer of the frame type of the
610  * inlined procedure. The new entities must be in the link field of
611  * the entities.
612  */
613 static INLINE void
614 copy_node_inline (ir_node *n, void *env) {
615   ir_node *new;
616   type *frame_tp = (type *)env;
617
618   copy_node(n, NULL);
619   if (get_irn_op(n) == op_Sel) {
620     new = get_new_node (n);
621     assert(get_irn_op(new) == op_Sel);
622     if (get_entity_owner(get_Sel_entity(n)) == frame_tp) {
623       set_Sel_entity(new, get_entity_link(get_Sel_entity(n)));
624     }
625   } else if (get_irn_op(n) == op_Block) {
626     new = get_new_node (n);
627     new->attr.block.irg = current_ir_graph;
628   }
629 }
630
631 static void find_addr(ir_node *node, void *env)
632 {
633   if (get_irn_opcode(node) == iro_Proj) {
634     if (get_Proj_proj(node) == pn_Start_P_value_arg_base)
635       *(int *)env = 0;
636   }
637 }
638
639 /*
640  * currently, we cannot inline two cases:
641  * - call with compound arguments
642  * - graphs that take the address of a parameter
643  *
644  * check these condition here
645  */
646 static int can_inline(ir_node *call, ir_graph *called_graph)
647 {
648   type *call_type = get_Call_type(call);
649   int params, ress, i, res;
650
651   assert(is_method_type(call_type));
652
653   params = get_method_n_params(call_type);
654   ress   = get_method_n_ress(call_type);
655
656   /* check params */
657   for (i = 0; i < params; ++i) {
658     type *p_type = get_method_param_type(call_type, i);
659
660     if (is_compound_type(p_type))
661       return 0;
662   }
663
664   /* check res */
665   for (i = 0; i < ress; ++i) {
666     type *r_type = get_method_res_type(call_type, i);
667
668     if (is_compound_type(r_type))
669       return 0;
670   }
671
672   res = 1;
673   irg_walk_graph(called_graph, find_addr, NULL, &res);
674
675   return res;
676 }
677
678 int inline_method(ir_node *call, ir_graph *called_graph) {
679   ir_node *pre_call;
680   ir_node *post_call, *post_bl;
681   ir_node *in[5];
682   ir_node *end, *end_bl;
683   ir_node **res_pred;
684   ir_node **cf_pred;
685   ir_node *ret, *phi;
686   int arity, n_ret, n_exc, n_res, i, j, rem_opt, irn_arity;
687   int exc_handling;
688   type *called_frame;
689   irg_inline_property prop = get_irg_inline_property(called_graph);
690
691   if ( (prop != irg_inline_forced) && (!get_opt_optimize() || !get_opt_inline() ||
692                                        (prop == irg_inline_forbidden))) return 0;
693
694   /*
695    * currently, we cannot inline two cases:
696    * - call with compound arguments
697    * - graphs that take the address of a parameter
698    */
699   if (! can_inline(call, called_graph))
700     return 0;
701
702   /* --  Turn off optimizations, this can cause problems when allocating new nodes. -- */
703   rem_opt = get_opt_optimize();
704   set_optimize(0);
705
706   /* Handle graph state */
707   assert(get_irg_phase_state(current_ir_graph) != phase_building);
708   assert(get_irg_pinned(current_ir_graph) == pinned);
709   assert(get_irg_pinned(called_graph) == pinned);
710   if (get_irg_outs_state(current_ir_graph) == outs_consistent)
711     set_irg_outs_inconsistent(current_ir_graph);
712   set_irg_loopinfo_inconsistent(current_ir_graph);
713
714   /* -- Check preconditions -- */
715   assert(get_irn_op(call) == op_Call);
716   /* @@@ does not work for InterfaceIII.java after cgana
717      assert(get_Call_type(call) == get_entity_type(get_irg_ent(called_graph)));
718      assert(smaller_type(get_entity_type(get_irg_ent(called_graph)),
719      get_Call_type(call)));
720   */
721   assert(get_type_tpop(get_Call_type(call)) == type_method);
722   if (called_graph == current_ir_graph) {
723     set_optimize(rem_opt);
724     return 0;
725   }
726
727   /* here we know we WILL inline, so inform the statistics */
728   stat_inline(call, called_graph);
729
730   /* -- Decide how to handle exception control flow: Is there a handler
731      for the Call node, or do we branch directly to End on an exception?
732      exc_handling: 0 There is a handler.
733      1 Branches to End.
734      2 Exception handling not represented in Firm. -- */
735   {
736     ir_node *proj, *Mproj = NULL, *Xproj = NULL;
737     for (proj = (ir_node *)get_irn_link(call); proj; proj = (ir_node *)get_irn_link(proj)) {
738       assert(get_irn_op(proj) == op_Proj);
739       if (get_Proj_proj(proj) == pn_Call_X_except) Xproj = proj;
740       if (get_Proj_proj(proj) == pn_Call_M_except) Mproj = proj;
741     }
742     if      (Mproj) { assert(Xproj); exc_handling = 0; } /*  Mproj           */
743     else if (Xproj) {                exc_handling = 1; } /* !Mproj &&  Xproj   */
744     else            {                exc_handling = 2; } /* !Mproj && !Xproj   */
745   }
746
747
748   /* --
749      the procedure and later replaces the Start node of the called graph.
750      Post_call is the old Call node and collects the results of the called
751      graph. Both will end up being a tuple.  -- */
752   post_bl = get_nodes_Block(call);
753   set_irg_current_block(current_ir_graph, post_bl);
754   /* XxMxPxP of Start + parameter of Call */
755   in[pn_Start_X_initial_exec] = new_Jmp();
756   in[pn_Start_M]              = get_Call_mem(call);
757   in[pn_Start_P_frame_base]   = get_irg_frame(current_ir_graph);
758   in[pn_Start_P_globals]      = get_irg_globals(current_ir_graph);
759   in[pn_Start_T_args]         = new_Tuple(get_Call_n_params(call), get_Call_param_arr(call));
760   /* in[pn_Start_P_value_arg_base] = ??? */
761   pre_call = new_Tuple(5, in);
762   post_call = call;
763
764   /* --
765      The new block gets the ins of the old block, pre_call and all its
766      predecessors and all Phi nodes. -- */
767   part_block(pre_call);
768
769   /* -- Prepare state for dead node elimination -- */
770   /* Visited flags in calling irg must be >= flag in called irg.
771      Else walker and arity computation will not work. */
772   if (get_irg_visited(current_ir_graph) <= get_irg_visited(called_graph))
773     set_irg_visited(current_ir_graph, get_irg_visited(called_graph)+1);
774   if (get_irg_block_visited(current_ir_graph)< get_irg_block_visited(called_graph))
775     set_irg_block_visited(current_ir_graph, get_irg_block_visited(called_graph));
776   /* Set pre_call as new Start node in link field of the start node of
777      calling graph and pre_calls block as new block for the start block
778      of calling graph.
779      Further mark these nodes so that they are not visited by the
780      copying. */
781   set_irn_link(get_irg_start(called_graph), pre_call);
782   set_irn_visited(get_irg_start(called_graph), get_irg_visited(current_ir_graph));
783   set_irn_link(get_irg_start_block(called_graph), get_nodes_Block(pre_call));
784   set_irn_visited(get_irg_start_block(called_graph), get_irg_visited(current_ir_graph));
785   set_irn_link(get_irg_bad(called_graph), get_irg_bad(current_ir_graph));
786   set_irn_visited(get_irg_bad(called_graph), get_irg_visited(current_ir_graph));
787
788   /* Initialize for compaction of in arrays */
789   inc_irg_block_visited(current_ir_graph);
790
791   /* -- Replicate local entities of the called_graph -- */
792   /* copy the entities. */
793   called_frame = get_irg_frame_type(called_graph);
794   for (i = 0; i < get_class_n_members(called_frame); i++) {
795     entity *new_ent, *old_ent;
796     old_ent = get_class_member(called_frame, i);
797     new_ent = copy_entity_own(old_ent, get_cur_frame_type());
798     set_entity_link(old_ent, new_ent);
799   }
800
801   /* visited is > than that of called graph.  With this trick visited will
802      remain unchanged so that an outer walker, e.g., searching the call nodes
803      to inline, calling this inline will not visit the inlined nodes. */
804   set_irg_visited(current_ir_graph, get_irg_visited(current_ir_graph)-1);
805
806   /* -- Performing dead node elimination inlines the graph -- */
807   /* Copies the nodes to the obstack of current_ir_graph. Updates links to new
808      entities. */
809   /* @@@ endless loops are not copied!! -- they should be, I think... */
810   irg_walk(get_irg_end(called_graph), copy_node_inline, copy_preds,
811            get_irg_frame_type(called_graph));
812
813   /* Repair called_graph */
814   set_irg_visited(called_graph, get_irg_visited(current_ir_graph));
815   set_irg_block_visited(called_graph, get_irg_block_visited(current_ir_graph));
816   set_Block_block_visited(get_irg_start_block(called_graph), 0);
817
818   /* -- Merge the end of the inlined procedure with the call site -- */
819   /* We will turn the old Call node into a Tuple with the following
820      predecessors:
821      -1:  Block of Tuple.
822      0: Phi of all Memories of Return statements.
823      1: Jmp from new Block that merges the control flow from all exception
824      predecessors of the old end block.
825      2: Tuple of all arguments.
826      3: Phi of Exception memories.
827      In case the old Call directly branches to End on an exception we don't
828      need the block merging all exceptions nor the Phi of the exception
829      memories.
830   */
831
832   /* -- Precompute some values -- */
833   end_bl = get_new_node(get_irg_end_block(called_graph));
834   end = get_new_node(get_irg_end(called_graph));
835   arity = get_irn_arity(end_bl);    /* arity = n_exc + n_ret  */
836   n_res = get_method_n_ress(get_Call_type(call));
837
838   res_pred = (ir_node **) malloc (n_res * sizeof (ir_node *));
839   cf_pred =  (ir_node **) malloc (arity * sizeof (ir_node *));
840
841   set_irg_current_block(current_ir_graph, post_bl); /* just to make sure */
842
843   /* -- archive keepalives -- */
844   irn_arity = get_irn_arity(end);
845   for (i = 0; i < irn_arity; i++)
846     add_End_keepalive(get_irg_end(current_ir_graph), get_irn_n(end, i));
847
848   /* The new end node will die.  We need not free as the in array is on the obstack:
849      copy_node only generated 'D' arrays. */
850
851   /* -- Replace Return nodes by Jump nodes. -- */
852   n_ret = 0;
853   for (i = 0; i < arity; i++) {
854     ir_node *ret;
855     ret = get_irn_n(end_bl, i);
856     if (get_irn_op(ret) == op_Return) {
857       cf_pred[n_ret] = new_r_Jmp(current_ir_graph, get_nodes_Block(ret));
858       n_ret++;
859     }
860   }
861   set_irn_in(post_bl, n_ret, cf_pred);
862
863   /* -- Build a Tuple for all results of the method.
864      Add Phi node if there was more than one Return.  -- */
865   turn_into_tuple(post_call, 4);
866   /* First the Memory-Phi */
867   n_ret = 0;
868   for (i = 0; i < arity; i++) {
869     ret = get_irn_n(end_bl, i);
870     if (get_irn_op(ret) == op_Return) {
871       cf_pred[n_ret] = get_Return_mem(ret);
872       n_ret++;
873     }
874   }
875   phi = new_Phi(n_ret, cf_pred, mode_M);
876   set_Tuple_pred(call, pn_Call_M_regular, phi);
877   /* Conserve Phi-list for further inlinings -- but might be optimized */
878   if (get_nodes_Block(phi) == post_bl) {
879     set_irn_link(phi, get_irn_link(post_bl));
880     set_irn_link(post_bl, phi);
881   }
882   /* Now the real results */
883   if (n_res > 0) {
884     for (j = 0; j < n_res; j++) {
885       n_ret = 0;
886       for (i = 0; i < arity; i++) {
887         ret = get_irn_n(end_bl, i);
888         if (get_irn_op(ret) == op_Return) {
889           cf_pred[n_ret] = get_Return_res(ret, j);
890           n_ret++;
891         }
892       }
893       if (n_ret > 0)
894         phi = new_Phi(n_ret, cf_pred, get_irn_mode(cf_pred[0]));
895       else
896         phi = new_Bad();
897       res_pred[j] = phi;
898       /* Conserve Phi-list for further inlinings -- but might be optimized */
899       if (get_nodes_Block(phi) == post_bl) {
900         set_irn_link(phi, get_irn_link(post_bl));
901         set_irn_link(post_bl, phi);
902       }
903     }
904     set_Tuple_pred(call, pn_Call_T_result, new_Tuple(n_res, res_pred));
905   } else {
906     set_Tuple_pred(call, pn_Call_T_result, new_Bad());
907   }
908   /* Finally the exception control flow.
909      We have two (three) possible situations:
910      First if the Call branches to an exception handler: We need to add a Phi node to
911      collect the memory containing the exception objects.  Further we need
912      to add another block to get a correct representation of this Phi.  To
913      this block we add a Jmp that resolves into the X output of the Call
914      when the Call is turned into a tuple.
915      Second the Call branches to End, the exception is not handled.  Just
916      add all inlined exception branches to the End node.
917      Third: there is no Exception edge at all. Handle as case two. */
918   if (exc_handling == 0) {
919     n_exc = 0;
920     for (i = 0; i < arity; i++) {
921       ir_node *ret;
922       ret = get_irn_n(end_bl, i);
923       if (is_fragile_op(skip_Proj(ret)) || (get_irn_op(skip_Proj(ret)) == op_Raise)) {
924         cf_pred[n_exc] = ret;
925         n_exc++;
926       }
927     }
928     if (n_exc > 0) {
929       new_Block(n_exc, cf_pred);      /* watch it: current_block is changed! */
930       set_Tuple_pred(call, pn_Call_X_except, new_Jmp());
931       /* The Phi for the memories with the exception objects */
932       n_exc = 0;
933       for (i = 0; i < arity; i++) {
934         ir_node *ret;
935         ret = skip_Proj(get_irn_n(end_bl, i));
936         if (get_irn_op(ret) == op_Call) {
937           cf_pred[n_exc] = new_r_Proj(current_ir_graph, get_nodes_Block(ret), ret, mode_M, 3);
938           n_exc++;
939         } else if (is_fragile_op(ret)) {
940           /* We rely that all cfops have the memory output at the same position. */
941           cf_pred[n_exc] = new_r_Proj(current_ir_graph, get_nodes_Block(ret), ret, mode_M, 0);
942           n_exc++;
943         } else if (get_irn_op(ret) == op_Raise) {
944           cf_pred[n_exc] = new_r_Proj(current_ir_graph, get_nodes_Block(ret), ret, mode_M, 1);
945           n_exc++;
946         }
947       }
948       set_Tuple_pred(call, pn_Call_M_except, new_Phi(n_exc, cf_pred, mode_M));
949     } else {
950       set_Tuple_pred(call, pn_Call_X_except, new_Bad());
951       set_Tuple_pred(call, pn_Call_M_except, new_Bad());
952     }
953   } else {
954     ir_node *main_end_bl;
955     int main_end_bl_arity;
956     ir_node **end_preds;
957
958     /* assert(exc_handling == 1 || no exceptions. ) */
959     n_exc = 0;
960     for (i = 0; i < arity; i++) {
961       ir_node *ret = get_irn_n(end_bl, i);
962
963       if (is_fragile_op(skip_Proj(ret)) || (get_irn_op(skip_Proj(ret)) == op_Raise)) {
964         cf_pred[n_exc] = ret;
965         n_exc++;
966       }
967     }
968     main_end_bl = get_irg_end_block(current_ir_graph);
969     main_end_bl_arity = get_irn_arity(main_end_bl);
970     end_preds =  (ir_node **) malloc ((n_exc + main_end_bl_arity) * sizeof (ir_node *));
971
972     for (i = 0; i < main_end_bl_arity; ++i)
973       end_preds[i] = get_irn_n(main_end_bl, i);
974     for (i = 0; i < n_exc; ++i)
975       end_preds[main_end_bl_arity + i] = cf_pred[i];
976     set_irn_in(main_end_bl, n_exc + main_end_bl_arity, end_preds);
977     set_Tuple_pred(call, pn_Call_X_except, new_Bad());
978     set_Tuple_pred(call, pn_Call_M_except, new_Bad());
979     free(end_preds);
980   }
981   free(res_pred);
982   free(cf_pred);
983
984 #if 0  /* old. now better, correcter, faster implementation. */
985   if (n_exc > 0) {
986     /* -- If the exception control flow from the inlined Call directly
987        branched to the end block we now have the following control
988        flow predecessor pattern: ProjX -> Tuple -> Jmp.  We must
989        remove the Jmp along with it's empty block and add Jmp's
990        predecessors as predecessors of this end block.  No problem if
991        there is no exception, because then branches Bad to End which
992        is fine. --
993        @@@ can't we know this beforehand: by getting the Proj(1) from
994        the Call link list and checking whether it goes to Proj. */
995     /* find the problematic predecessor of the end block. */
996     end_bl = get_irg_end_block(current_ir_graph);
997     for (i = 0; i < get_Block_n_cfgpreds(end_bl); i++) {
998       cf_op = get_Block_cfgpred(end_bl, i);
999       if (get_irn_op(cf_op) == op_Proj) {
1000         cf_op = get_Proj_pred(cf_op);
1001         if ((get_irn_op(cf_op) == op_Tuple) && (cf_op == call)) {
1002           /*  There are unoptimized tuples from inlineing before when no exc */
1003           assert(get_Proj_proj(get_Block_cfgpred(end_bl, i)) == pn_Call_X_except);
1004           cf_op = get_Tuple_pred(cf_op, pn_Call_X_except);
1005           assert(get_irn_op(cf_op) == op_Jmp);
1006           break;
1007         }
1008       }
1009     }
1010     /* repair */
1011     if (i < get_Block_n_cfgpreds(end_bl)) {
1012       bl = get_nodes_Block(cf_op);
1013       arity = get_Block_n_cfgpreds(end_bl) + get_Block_n_cfgpreds(bl) - 1;
1014       cf_pred = (ir_node **) malloc (arity * sizeof (ir_node *));
1015       for (j = 0; j < i; j++)
1016         cf_pred[j] = get_Block_cfgpred(end_bl, j);
1017       for (j = j; j < i + get_Block_n_cfgpreds(bl); j++)
1018         cf_pred[j] = get_Block_cfgpred(bl, j-i);
1019       for (j = j; j < arity; j++)
1020         cf_pred[j] = get_Block_cfgpred(end_bl, j-get_Block_n_cfgpreds(bl) +1);
1021       set_irn_in(end_bl, arity, cf_pred);
1022       free(cf_pred);
1023       /*  Remove the exception pred from post-call Tuple. */
1024       set_Tuple_pred(call, pn_Call_X_except, new_Bad());
1025     }
1026   }
1027 #endif
1028
1029   /* --  Turn cse back on. -- */
1030   set_optimize(rem_opt);
1031
1032   return 1;
1033 }
1034
1035 /********************************************************************/
1036 /* Apply inlineing to small methods.                                */
1037 /********************************************************************/
1038
1039 /* It makes no sense to inline too many calls in one procedure. Anyways,
1040    I didn't get a version with NEW_ARR_F to run. */
1041 #define MAX_INLINE 1024
1042
1043 /**
1044  * environment for inlining small irgs
1045  */
1046 typedef struct _inline_env_t {
1047   int pos;
1048   ir_node *calls[MAX_INLINE];
1049 } inline_env_t;
1050
1051 /**
1052  * Returns the irg called from a Call node. If the irg is not
1053  * known, NULL is returned.
1054  */
1055 static ir_graph *get_call_called_irg(ir_node *call) {
1056   ir_node *addr;
1057   tarval *tv;
1058   ir_graph *called_irg = NULL;
1059
1060   assert(get_irn_op(call) == op_Call);
1061
1062   addr = get_Call_ptr(call);
1063   if (get_irn_op(addr) == op_Const) {
1064     /* Check whether the constant is the pointer to a compiled entity. */
1065     tv = get_Const_tarval(addr);
1066     if (get_tarval_entity(tv))
1067       called_irg = get_entity_irg(get_tarval_entity(tv));
1068   } else if (get_irn_op(addr) == op_SymConst && get_SymConst_kind(addr) == symconst_addr_ent) {
1069     called_irg = get_entity_irg(get_SymConst_entity(addr));
1070   }
1071   return called_irg;
1072 }
1073
1074 static void collect_calls(ir_node *call, void *env) {
1075   inline_env_t *ienv = env;
1076   ir_node *addr;
1077   tarval *tv;
1078   ir_graph *called_irg;
1079
1080   if (get_irn_op(call) != op_Call) return;
1081
1082   addr = get_Call_ptr(call);
1083   if (get_irn_op(addr) == op_Const) {
1084     /* Check whether the constant is the pointer to a compiled entity. */
1085     tv = get_Const_tarval(addr);
1086     if (get_tarval_entity(tv)) {
1087       called_irg = get_entity_irg(get_tarval_entity(tv));
1088       if (called_irg && ienv->pos < MAX_INLINE) {
1089         /* The Call node calls a locally defined method.  Remember to inline. */
1090         ienv->calls[ienv->pos++] = call;
1091       }
1092     }
1093   }
1094 }
1095
1096 /**
1097  * Inlines all small methods at call sites where the called address comes
1098  * from a Const node that references the entity representing the called
1099  * method.
1100  * The size argument is a rough measure for the code size of the method:
1101  * Methods where the obstack containing the firm graph is smaller than
1102  * size are inlined.
1103  */
1104 void inline_small_irgs(ir_graph *irg, int size) {
1105   int i;
1106   ir_graph *rem = current_ir_graph;
1107   inline_env_t env;
1108
1109   if (!(get_opt_optimize() && get_opt_inline())) return;
1110
1111   current_ir_graph = irg;
1112   /* Handle graph state */
1113   assert(get_irg_phase_state(current_ir_graph) != phase_building);
1114   free_callee_info(current_ir_graph);
1115
1116   /* Find Call nodes to inline.
1117      (We can not inline during a walk of the graph, as inlineing the same
1118      method several times changes the visited flag of the walked graph:
1119      after the first inlineing visited of the callee equals visited of
1120      the caller.  With the next inlineing both are increased.) */
1121   env.pos = 0;
1122   irg_walk(get_irg_end(irg), NULL, collect_calls, &env);
1123
1124   if ((env.pos > 0) && (env.pos < MAX_INLINE)) {
1125     /* There are calls to inline */
1126     collect_phiprojs(irg);
1127     for (i = 0; i < env.pos; i++) {
1128       tarval *tv;
1129       ir_graph *callee;
1130       tv = get_Const_tarval(get_Call_ptr(env.calls[i]));
1131       callee = get_entity_irg(get_tarval_entity(tv));
1132       if (((_obstack_memory_used(callee->obst) - obstack_room(callee->obst)) < size) ||
1133         (get_irg_inline_property(callee) == irg_inline_forced)) {
1134         inline_method(env.calls[i], callee);
1135       }
1136     }
1137   }
1138
1139   current_ir_graph = rem;
1140 }
1141
1142 /**
1143  * Environment for inlining irgs.
1144  */
1145 typedef struct {
1146   int n_nodes;       /**< Nodes in graph except Id, Tuple, Proj, Start, End */
1147   int n_nodes_orig;  /**< for statistics */
1148   eset *call_nodes;  /**< All call nodes in this graph */
1149   int n_call_nodes;
1150   int n_call_nodes_orig; /**< for statistics */
1151   int n_callers;   /**< Number of known graphs that call this graphs. */
1152   int n_callers_orig; /**< for statistics */
1153 } inline_irg_env;
1154
1155 static inline_irg_env *new_inline_irg_env(void) {
1156   inline_irg_env *env = malloc(sizeof(inline_irg_env));
1157   env->n_nodes = -2; /* uncount Start, End */
1158   env->n_nodes_orig = -2; /* uncount Start, End */
1159   env->call_nodes = eset_create();
1160   env->n_call_nodes = 0;
1161   env->n_call_nodes_orig = 0;
1162   env->n_callers = 0;
1163   env->n_callers_orig = 0;
1164   return env;
1165 }
1166
1167 static void free_inline_irg_env(inline_irg_env *env) {
1168   eset_destroy(env->call_nodes);
1169   free(env);
1170 }
1171
1172 static void collect_calls2(ir_node *call, void *env) {
1173   inline_irg_env *x = (inline_irg_env *)env;
1174   ir_op *op = get_irn_op(call);
1175   ir_graph *callee;
1176
1177   /* count nodes in irg */
1178   if (op != op_Proj && op != op_Tuple && op != op_Sync) {
1179     x->n_nodes++;
1180     x->n_nodes_orig++;
1181   }
1182
1183   if (op != op_Call) return;
1184
1185   /* collect all call nodes */
1186   eset_insert(x->call_nodes, (void *)call);
1187   x->n_call_nodes++;
1188   x->n_call_nodes_orig++;
1189
1190   /* count all static callers */
1191   callee = get_call_called_irg(call);
1192   if (callee) {
1193     ((inline_irg_env *)get_irg_link(callee))->n_callers++;
1194     ((inline_irg_env *)get_irg_link(callee))->n_callers_orig++;
1195   }
1196 }
1197
1198 INLINE static int is_leave(ir_graph *irg) {
1199   return (((inline_irg_env *)get_irg_link(irg))->n_call_nodes == 0);
1200 }
1201
1202 INLINE static int is_smaller(ir_graph *callee, int size) {
1203   return (((inline_irg_env *)get_irg_link(callee))->n_nodes < size);
1204 }
1205
1206
1207 /*
1208  * Inlines small leave methods at call sites where the called address comes
1209  * from a Const node that references the entity representing the called
1210  * method.
1211  * The size argument is a rough measure for the code size of the method:
1212  * Methods where the obstack containing the firm graph is smaller than
1213  * size are inlined.
1214  */
1215 void inline_leave_functions(int maxsize, int leavesize, int size) {
1216   inline_irg_env *env;
1217   int i, n_irgs = get_irp_n_irgs();
1218   ir_graph *rem = current_ir_graph;
1219   int did_inline = 1;
1220
1221   if (!(get_opt_optimize() && get_opt_inline())) return;
1222
1223   /* extend all irgs by a temporary data structure for inlineing. */
1224   for (i = 0; i < n_irgs; ++i)
1225     set_irg_link(get_irp_irg(i), new_inline_irg_env());
1226
1227   /* Precompute information in temporary data structure. */
1228   for (i = 0; i < n_irgs; ++i) {
1229     current_ir_graph = get_irp_irg(i);
1230     assert(get_irg_phase_state(current_ir_graph) != phase_building);
1231     free_callee_info(current_ir_graph);
1232
1233     irg_walk(get_irg_end(current_ir_graph), NULL, collect_calls2,
1234          get_irg_link(current_ir_graph));
1235   }
1236
1237   /* and now inline.
1238      Inline leaves recursively -- we might construct new leaves. */
1239   /* int itercnt = 1; */
1240   while (did_inline) {
1241     /* printf("iteration %d\n", itercnt++); */
1242     did_inline = 0;
1243     for (i = 0; i < n_irgs; ++i) {
1244       ir_node *call;
1245       eset *walkset;
1246       int phiproj_computed = 0;
1247
1248       current_ir_graph = get_irp_irg(i);
1249       env = (inline_irg_env *)get_irg_link(current_ir_graph);
1250
1251       /* we can not walk and change a set, nor remove from it.
1252       So recompute.*/
1253       walkset = env->call_nodes;
1254       env->call_nodes = eset_create();
1255       for (call = eset_first(walkset); call; call = eset_next(walkset)) {
1256         inline_irg_env *callee_env;
1257         ir_graph *callee = get_call_called_irg(call);
1258
1259         if (env->n_nodes > maxsize) break;
1260         if (callee &&
1261         ((is_leave(callee) && is_smaller(callee, leavesize)) ||
1262          (get_irg_inline_property(callee) == irg_inline_forced))) {
1263           if (!phiproj_computed) {
1264             phiproj_computed = 1;
1265             collect_phiprojs(current_ir_graph);
1266           }
1267           callee_env = (inline_irg_env *)get_irg_link(callee);
1268 /*         printf(" %s: Inlineing %s.\n", get_entity_name(get_irg_entity(current_ir_graph)), */
1269 /*         get_entity_name(get_irg_entity(callee))); */
1270           if (inline_method(call, callee)) {
1271             did_inline = 1;
1272             env->n_call_nodes--;
1273             eset_insert_all(env->call_nodes, callee_env->call_nodes);
1274             env->n_call_nodes += callee_env->n_call_nodes;
1275             env->n_nodes += callee_env->n_nodes;
1276             callee_env->n_callers--;
1277           }
1278         } else {
1279           eset_insert(env->call_nodes, call);
1280         }
1281       }
1282       eset_destroy(walkset);
1283     }
1284   }
1285
1286   /* printf("Non leaves\n"); */
1287   /* inline other small functions. */
1288   for (i = 0; i < n_irgs; ++i) {
1289     ir_node *call;
1290     eset *walkset;
1291     int phiproj_computed = 0;
1292
1293     current_ir_graph = get_irp_irg(i);
1294     env = (inline_irg_env *)get_irg_link(current_ir_graph);
1295
1296     /* we can not walk and change a set, nor remove from it.
1297        So recompute.*/
1298     walkset = env->call_nodes;
1299     env->call_nodes = eset_create();
1300     for (call = eset_first(walkset); call; call = eset_next(walkset)) {
1301       inline_irg_env *callee_env;
1302       ir_graph *callee = get_call_called_irg(call);
1303
1304       if (env->n_nodes > maxsize) break;
1305       if (callee && is_smaller(callee, size)) {
1306         if (!phiproj_computed) {
1307             phiproj_computed = 1;
1308             collect_phiprojs(current_ir_graph);
1309         }
1310         callee_env = (inline_irg_env *)get_irg_link(callee);
1311 /*       printf(" %s: Inlineing %s.\n", get_entity_name(get_irg_entity(current_ir_graph)), */
1312 /*       get_entity_name(get_irg_entity(callee))); */
1313         if (inline_method(call, callee)) {
1314       did_inline = 1;
1315       env->n_call_nodes--;
1316       eset_insert_all(env->call_nodes, callee_env->call_nodes);
1317       env->n_call_nodes += callee_env->n_call_nodes;
1318       env->n_nodes += callee_env->n_nodes;
1319       callee_env->n_callers--;
1320     }
1321       } else {
1322         eset_insert(env->call_nodes, call);
1323       }
1324     }
1325     eset_destroy(walkset);
1326   }
1327
1328   for (i = 0; i < n_irgs; ++i) {
1329     current_ir_graph = get_irp_irg(i);
1330 #if 0
1331     env = (inline_irg_env *)get_irg_link(current_ir_graph);
1332     if ((env->n_call_nodes_orig != env->n_call_nodes) ||
1333     (env->n_callers_orig != env->n_callers))
1334       printf("Nodes:%3d ->%3d, calls:%3d ->%3d, callers:%3d ->%3d, -- %s\n",
1335          env->n_nodes_orig, env->n_nodes, env->n_call_nodes_orig, env->n_call_nodes,
1336          env->n_callers_orig, env->n_callers,
1337          get_entity_name(get_irg_entity(current_ir_graph)));
1338 #endif
1339     free_inline_irg_env((inline_irg_env *)get_irg_link(current_ir_graph));
1340   }
1341
1342   current_ir_graph = rem;
1343 }
1344
1345 /*******************************************************************/
1346 /*  Code Placement.  Pins all floating nodes to a block where they */
1347 /*  will be executed only if needed.                               */
1348 /*******************************************************************/
1349
1350 /**
1351  * Find the earliest correct block for N.  --- Place N into the
1352  * same Block as its dominance-deepest Input.
1353  */
1354 static void
1355 place_floats_early(ir_node *n, pdeq *worklist)
1356 {
1357   int i, start, irn_arity;
1358
1359   /* we must not run into an infinite loop */
1360   assert (irn_not_visited(n));
1361   mark_irn_visited(n);
1362
1363   /* Place floating nodes. */
1364   if (get_op_pinned(get_irn_op(n)) == floats) {
1365     int depth         = 0;
1366     ir_node *b        = new_Bad();   /* The block to place this node in */
1367     int bad_recursion = is_Bad(get_nodes_block(n));
1368
1369     assert(get_irn_op(n) != op_Block);
1370
1371     if ((get_irn_op(n) == op_Const) ||
1372         (get_irn_op(n) == op_SymConst) ||
1373         (is_Bad(n)) ||
1374         (get_irn_op(n) == op_Unknown)) {
1375       /* These nodes will not be placed by the loop below. */
1376       b = get_irg_start_block(current_ir_graph);
1377       depth = 1;
1378     }
1379
1380     /* find the block for this node. */
1381     irn_arity = get_irn_arity(n);
1382     for (i = 0; i < irn_arity; i++) {
1383       ir_node *dep = get_irn_n(n, i);
1384       ir_node *dep_block;
1385
1386       if ((irn_not_visited(dep))
1387           && (get_op_pinned(get_irn_op(dep)) == floats)) {
1388         place_floats_early(dep, worklist);
1389       }
1390
1391       /*
1392        * A node in the Bad block must stay in the bad block,
1393        * so don't compute a new block for it.
1394        */
1395       if (bad_recursion)
1396         continue;
1397
1398       /* Because all loops contain at least one pinned node, now all
1399          our inputs are either pinned or place_early has already
1400          been finished on them.  We do not have any unfinished inputs!  */
1401       dep_block = get_nodes_Block(dep);
1402       if ((!is_Bad(dep_block)) &&
1403           (get_Block_dom_depth(dep_block) > depth)) {
1404         b = dep_block;
1405         depth = get_Block_dom_depth(dep_block);
1406       }
1407       /* Avoid that the node is placed in the Start block */
1408       if ((depth == 1) && (get_Block_dom_depth(get_nodes_Block(n)) > 1)) {
1409         b = get_Block_cfg_out(get_irg_start_block(current_ir_graph), 0);
1410         assert(b != get_irg_start_block(current_ir_graph));
1411         depth = 2;
1412       }
1413     }
1414     set_nodes_Block(n, b);
1415   }
1416
1417   /* Add predecessors of non floating nodes on worklist. */
1418   start = (get_irn_op(n) == op_Block) ? 0 : -1;
1419   irn_arity = get_irn_arity(n);
1420   for (i = start; i < irn_arity; i++) {
1421     ir_node *pred = get_irn_n(n, i);
1422     if (irn_not_visited(pred)) {
1423       pdeq_putr (worklist, pred);
1424     }
1425   }
1426 }
1427
1428 /**
1429  * Floating nodes form subgraphs that begin at nodes as Const, Load,
1430  * Start, Call and that end at pinned nodes as Store, Call.  Place_early
1431  * places all floating nodes reachable from its argument through floating
1432  * nodes and adds all beginnings at pinned nodes to the worklist.
1433  */
1434 static INLINE void place_early(pdeq* worklist) {
1435   assert(worklist);
1436   inc_irg_visited(current_ir_graph);
1437
1438   /* this inits the worklist */
1439   place_floats_early(get_irg_end(current_ir_graph), worklist);
1440
1441   /* Work the content of the worklist. */
1442   while (!pdeq_empty (worklist)) {
1443     ir_node *n = pdeq_getl (worklist);
1444     if (irn_not_visited(n)) place_floats_early(n, worklist);
1445   }
1446
1447   set_irg_outs_inconsistent(current_ir_graph);
1448   current_ir_graph->pinned = pinned;
1449 }
1450
1451
1452 /** deepest common dominance ancestor of DCA and CONSUMER of PRODUCER. */
1453 static ir_node *
1454 consumer_dom_dca (ir_node *dca, ir_node *consumer, ir_node *producer)
1455 {
1456   ir_node *block = NULL;
1457
1458   /* Compute the latest block into which we can place a node so that it is
1459      before consumer. */
1460   if (get_irn_op(consumer) == op_Phi) {
1461     /* our consumer is a Phi-node, the effective use is in all those
1462        blocks through which the Phi-node reaches producer */
1463     int i, irn_arity;
1464     ir_node *phi_block = get_nodes_Block(consumer);
1465     irn_arity = get_irn_arity(consumer);
1466     for (i = 0;  i < irn_arity; i++) {
1467       if (get_irn_n(consumer, i) == producer) {
1468         block = get_nodes_Block(get_Block_cfgpred(phi_block, i));
1469       }
1470     }
1471   } else {
1472     assert(is_no_Block(consumer));
1473     block = get_nodes_Block(consumer);
1474   }
1475
1476   /* Compute the deepest common ancestor of block and dca. */
1477   assert(block);
1478   if (!dca) return block;
1479   while (get_Block_dom_depth(block) > get_Block_dom_depth(dca))
1480     block = get_Block_idom(block);
1481   while (get_Block_dom_depth(dca) > get_Block_dom_depth(block))
1482     dca = get_Block_idom(dca);
1483   while (block != dca)
1484     { block = get_Block_idom(block); dca = get_Block_idom(dca); }
1485
1486   return dca;
1487 }
1488
1489 static INLINE int get_irn_loop_depth(ir_node *n) {
1490   return get_loop_depth(get_irn_loop(n));
1491 }
1492
1493 /**
1494  * Move n to a block with less loop depth than it's current block. The
1495  * new block must be dominated by early.
1496  */
1497 static void
1498 move_out_of_loops (ir_node *n, ir_node *early)
1499 {
1500   ir_node *best, *dca;
1501   assert(n && early);
1502
1503
1504   /* Find the region deepest in the dominator tree dominating
1505      dca with the least loop nesting depth, but still dominated
1506      by our early placement. */
1507   dca = get_nodes_Block(n);
1508   best = dca;
1509   while (dca != early) {
1510     dca = get_Block_idom(dca);
1511     if (!dca) break; /* should we put assert(dca)? */
1512     if (get_irn_loop_depth(dca) < get_irn_loop_depth(best)) {
1513       best = dca;
1514     }
1515   }
1516   if (best != get_nodes_Block(n)) {
1517     /* debug output
1518     printf("Moving out of loop: "); DDMN(n);
1519     printf(" Outermost block: "); DDMN(early);
1520     printf(" Best block: "); DDMN(best);
1521     printf(" Innermost block: "); DDMN(get_nodes_Block(n));
1522     */
1523     set_nodes_Block(n, best);
1524   }
1525 }
1526
1527 /**
1528  * Find the latest legal block for N and place N into the
1529  * `optimal' Block between the latest and earliest legal block.
1530  * The `optimal' block is the dominance-deepest block of those
1531  * with the least loop-nesting-depth.  This places N out of as many
1532  * loops as possible and then makes it as control dependant as
1533  * possible.
1534  */
1535 static void
1536 place_floats_late(ir_node *n, pdeq *worklist)
1537 {
1538   int i;
1539   ir_node *early;
1540
1541   assert (irn_not_visited(n)); /* no multiple placement */
1542
1543   /* no need to place block nodes, control nodes are already placed. */
1544   if ((get_irn_op(n) != op_Block) &&
1545       (!is_cfop(n)) &&
1546       (get_irn_mode(n) != mode_X)) {
1547     /* Remember the early placement of this block to move it
1548        out of loop no further than the early placement. */
1549     early = get_nodes_Block(n);
1550     /* Assure that our users are all placed, except the Phi-nodes.
1551        --- Each data flow cycle contains at least one Phi-node.  We
1552        have to break the `user has to be placed before the
1553        producer' dependence cycle and the Phi-nodes are the
1554        place to do so, because we need to base our placement on the
1555        final region of our users, which is OK with Phi-nodes, as they
1556        are pinned, and they never have to be placed after a
1557        producer of one of their inputs in the same block anyway. */
1558     for (i = 0; i < get_irn_n_outs(n); i++) {
1559       ir_node *succ = get_irn_out(n, i);
1560       if (irn_not_visited(succ) && (get_irn_op(succ) != op_Phi))
1561         place_floats_late(succ, worklist);
1562     }
1563
1564     /* We have to determine the final block of this node... except for
1565        constants. */
1566     if ((get_op_pinned(get_irn_op(n)) == floats) &&
1567         (get_irn_op(n) != op_Const) &&
1568         (get_irn_op(n) != op_SymConst)) {
1569       ir_node *dca = NULL;  /* deepest common ancestor in the
1570                    dominator tree of all nodes'
1571                    blocks depending on us; our final
1572                    placement has to dominate DCA. */
1573       for (i = 0; i < get_irn_n_outs(n); i++) {
1574         dca = consumer_dom_dca (dca, get_irn_out(n, i), n);
1575       }
1576       set_nodes_Block(n, dca);
1577
1578       move_out_of_loops (n, early);
1579     }
1580   }
1581
1582   mark_irn_visited(n);
1583
1584   /* Add predecessors of all non-floating nodes on list. (Those of floating
1585      nodes are placeded already and therefore are marked.)  */
1586   for (i = 0; i < get_irn_n_outs(n); i++) {
1587     if (irn_not_visited(get_irn_out(n, i))) {
1588       pdeq_putr (worklist, get_irn_out(n, i));
1589     }
1590   }
1591 }
1592
1593 static INLINE void place_late(pdeq *worklist) {
1594   assert(worklist);
1595   inc_irg_visited(current_ir_graph);
1596
1597   /* This fills the worklist initially. */
1598   place_floats_late(get_irg_start_block(current_ir_graph), worklist);
1599   /* And now empty the worklist again... */
1600   while (!pdeq_empty (worklist)) {
1601     ir_node *n = pdeq_getl (worklist);
1602     if (irn_not_visited(n)) place_floats_late(n, worklist);
1603   }
1604 }
1605
1606 void place_code(ir_graph *irg) {
1607   pdeq* worklist;
1608   ir_graph *rem = current_ir_graph;
1609
1610   current_ir_graph = irg;
1611
1612   if (!(get_opt_optimize() && get_opt_global_cse())) return;
1613
1614   /* Handle graph state */
1615   assert(get_irg_phase_state(irg) != phase_building);
1616   if (get_irg_dom_state(irg) != dom_consistent)
1617     compute_doms(irg);
1618
1619   if (1 || get_irg_loopinfo_state(irg) != loopinfo_consistent) {
1620     free_loop_information(irg);
1621     construct_backedges(irg);
1622   }
1623
1624   /* Place all floating nodes as early as possible. This guarantees
1625      a legal code placement. */
1626   worklist = new_pdeq();
1627   place_early(worklist);
1628
1629   /* place_early invalidates the outs, place_late needs them. */
1630   compute_outs(irg);
1631   /* Now move the nodes down in the dominator tree. This reduces the
1632      unnecessary executions of the node. */
1633   place_late(worklist);
1634
1635   set_irg_outs_inconsistent(current_ir_graph);
1636   set_irg_loopinfo_inconsistent(current_ir_graph);
1637   del_pdeq(worklist);
1638   current_ir_graph = rem;
1639 }
1640
1641
1642
1643 /********************************************************************/
1644 /* Control flow optimization.                                       */
1645 /* Removes Bad control flow predecessors and empty blocks.  A block */
1646 /* is empty if it contains only a Jmp node.                         */
1647 /* Blocks can only be removed if they are not needed for the        */
1648 /* semantics of Phi nodes.                                          */
1649 /********************************************************************/
1650
1651 /**
1652  * Removes Tuples from Block control flow predecessors.
1653  * Optimizes blocks with equivalent_node().
1654  * Replaces n by Bad if n is unreachable control flow.
1655  */
1656 static void merge_blocks(ir_node *n, void *env) {
1657   int i;
1658   set_irn_link(n, NULL);
1659
1660   if (get_irn_op(n) == op_Block) {
1661     /* Remove Tuples */
1662     for (i = 0; i < get_Block_n_cfgpreds(n); i++)
1663       /* GL @@@ : is this possible? if (get_opt_normalize()) -- added, all tests go through.
1664        A different order of optimizations might cause problems. */
1665       if (get_opt_normalize())
1666         set_Block_cfgpred(n, i, skip_Tuple(get_Block_cfgpred(n, i)));
1667   } else if (get_opt_optimize() && (get_irn_mode(n) == mode_X)) {
1668     /* We will soon visit a block.  Optimize it before visiting! */
1669     ir_node *b = get_nodes_Block(n);
1670     ir_node *new_node = equivalent_node(b);
1671     while (irn_not_visited(b) && (!is_Bad(new_node)) && (new_node != b)) {
1672       /* We would have to run gigo if new is bad, so we
1673          promote it directly below. */
1674       assert(((b == new_node) ||
1675           get_opt_control_flow_straightening() ||
1676           get_opt_control_flow_weak_simplification()) &&
1677          ("strange flag setting"));
1678       exchange (b, new_node);
1679       b = new_node;
1680       new_node = equivalent_node(b);
1681     }
1682     if (is_Bad(new_node) && get_opt_normalize()) exchange(n, new_Bad());
1683   }
1684 }
1685
1686 /**
1687  * Collects all Phi nodes in link list of Block.
1688  * Marks all blocks "block_visited" if they contain a node other
1689  * than Jmp.
1690  *
1691  * Colelct Conds and its Projs in the cond_list
1692  */
1693 static void collect_nodes(ir_node *n, void *env) {
1694   ir_node **cond_list = env;
1695
1696   if (is_no_Block(n)) {
1697     ir_node *b = get_nodes_Block(n);
1698
1699     switch (get_irn_opcode(n)) {
1700
1701     case iro_Phi:
1702       /* Collect Phi nodes to compact ins along with block's ins. */
1703       set_irn_link(n, get_irn_link(b));
1704       set_irn_link(b, n);
1705       break;
1706
1707     case iro_Cond:
1708       {
1709         ir_node *value = get_Cond_selector(n);
1710         tarval *tv = computed_value(value);
1711
1712         if (tv != tarval_bad && mode_is_int(get_tarval_mode(tv))) {
1713           set_irn_link(n, *cond_list);
1714           *cond_list = n;
1715         }
1716         else { /* mark the cond, we cannot optimize it */
1717           set_irn_link(n, NULL);
1718         }
1719       }
1720       break;
1721
1722     case iro_Proj:
1723       {
1724         ir_node *cond = get_Proj_pred(n);
1725
1726         if (get_irn_op(cond) == op_Cond) {
1727           void *link = get_irn_link(cond);
1728
1729           if (link) {
1730             /* the cond node can be optimized, collect Proj */
1731             set_irn_link(n, link);
1732             set_irn_link(cond, n);
1733           }
1734         }
1735       }
1736       break;
1737
1738     default:
1739       break;
1740     }
1741
1742     if ((get_irn_op(n) != op_Jmp) && !is_Bad(b)) {  /* Check for non empty block. */
1743       mark_Block_block_visited(b);
1744     }
1745   }
1746 }
1747
1748 /** Returns true if pred is predecessor of block. */
1749 static int is_pred_of(ir_node *pred, ir_node *b) {
1750   int i;
1751   for (i = 0; i < get_Block_n_cfgpreds(b); i++) {
1752     ir_node *b_pred = get_nodes_Block(get_Block_cfgpred(b, i));
1753     if (b_pred == pred) return 1;
1754   }
1755   return 0;
1756 }
1757
1758 static int test_whether_dispensable(ir_node *b, int pos) {
1759   int i, j, n_preds = 1;
1760   int dispensable = 1;
1761   ir_node *cfop = get_Block_cfgpred(b, pos);
1762   ir_node *pred = get_nodes_Block(cfop);
1763
1764   if (get_Block_block_visited(pred) + 1
1765       < get_irg_block_visited(current_ir_graph)) {
1766     if (!get_opt_optimize() || !get_opt_control_flow_strong_simplification()) {
1767       /* Mark block so that is will not be removed. */
1768       set_Block_block_visited(pred, get_irg_block_visited(current_ir_graph)-1);
1769       return 1;
1770     }
1771     /* Seems to be empty. */
1772     if (!get_irn_link(b)) {
1773       /* There are no Phi nodes ==> dispensable. */
1774       n_preds = get_Block_n_cfgpreds(pred);
1775     } else {
1776       /* b's pred blocks and pred's pred blocks must be pairwise disjunct.
1777          Work preds < pos as if they were already removed. */
1778       for (i = 0; i < pos; i++) {
1779         ir_node *b_pred = get_nodes_Block(get_Block_cfgpred(b, i));
1780         if (get_Block_block_visited(b_pred) + 1
1781             < get_irg_block_visited(current_ir_graph)) {
1782           for (j = 0; j < get_Block_n_cfgpreds(b_pred); j++) {
1783             ir_node *b_pred_pred = get_nodes_Block(get_Block_cfgpred(b_pred, j));
1784             if (is_pred_of(b_pred_pred, pred)) dispensable = 0;
1785           }
1786         } else {
1787           if (is_pred_of(b_pred, pred)) dispensable = 0;
1788         }
1789       }
1790       for (i = pos +1; i < get_Block_n_cfgpreds(b); i++) {
1791         ir_node *b_pred = get_nodes_Block(get_Block_cfgpred(b, i));
1792         if (is_pred_of(b_pred, pred)) dispensable = 0;
1793       }
1794       if (!dispensable) {
1795         set_Block_block_visited(pred, get_irg_block_visited(current_ir_graph)-1);
1796         n_preds = 1;
1797       } else {
1798         n_preds = get_Block_n_cfgpreds(pred);
1799       }
1800     }
1801   }
1802
1803   return n_preds;
1804 }
1805
1806 static void optimize_blocks(ir_node *b, void *env) {
1807   int i, j, k, max_preds, n_preds;
1808   ir_node *pred, *phi;
1809   ir_node **in;
1810
1811   /* Count the number of predecessor if this block is merged with pred blocks
1812      that are empty. */
1813   max_preds = 0;
1814   for (i = 0; i < get_Block_n_cfgpreds(b); i++) {
1815     max_preds += test_whether_dispensable(b, i);
1816   }
1817   in = (ir_node **) malloc(max_preds * sizeof(ir_node *));
1818
1819 /*-
1820   printf(" working on "); DDMN(b);
1821   for (i = 0; i < get_Block_n_cfgpreds(b); i++) {
1822     pred = get_nodes_Block(get_Block_cfgpred(b, i));
1823     if (is_Bad(get_Block_cfgpred(b, i))) {
1824       printf("  removing Bad %i\n ", i);
1825     } else if (get_Block_block_visited(pred) +1
1826            < get_irg_block_visited(current_ir_graph)) {
1827       printf("  removing pred %i ", i); DDMN(pred);
1828     } else { printf("  Nothing to do for "); DDMN(pred); }
1829   }
1830   * end Debug output -*/
1831
1832   /*- Fix the Phi nodes -*/
1833   phi = get_irn_link(b);
1834   while (phi) {
1835     assert(get_irn_op(phi) == op_Phi);
1836     /* Find the new predecessors for the Phi */
1837     n_preds = 0;
1838     for (i = 0; i < get_Block_n_cfgpreds(b); i++) {
1839       pred = get_nodes_Block(get_Block_cfgpred(b, i));
1840       if (is_Bad(get_Block_cfgpred(b, i))) {
1841         /* Do nothing */
1842       } else if (get_Block_block_visited(pred) +1
1843                  < get_irg_block_visited(current_ir_graph)) {
1844         /* It's an empty block and not yet visited. */
1845         ir_node *phi_pred = get_Phi_pred(phi, i);
1846         for (j = 0; j < get_Block_n_cfgpreds(pred); j++) {
1847           if (get_nodes_Block(phi_pred) == pred) {
1848             assert(get_irn_op(phi_pred) == op_Phi);  /* Block is empty!! */
1849             in[n_preds] = get_Phi_pred(phi_pred, j);
1850           } else {
1851             in[n_preds] = phi_pred;
1852           }
1853           n_preds++;
1854         }
1855         /* The Phi_pred node is replaced now if it is a Phi.
1856            In Schleifen kann offenbar der entfernte Phi Knoten legal verwendet werden.
1857            Daher muss der Phiknoten durch den neuen ersetzt werden.
1858            Weiter muss der alte Phiknoten entfernt werden (durch ersetzen oder
1859            durch einen Bad) damit er aus den keep_alive verschwinden kann.
1860            Man sollte also, falls keine Schleife vorliegt, exchange mit new_Bad
1861            aufrufen.  */
1862         if (get_nodes_Block(phi_pred) == pred) {
1863           /* remove the Phi as it might be kept alive. Further there
1864              might be other users. */
1865           exchange(phi_pred, phi);  /* geht, ist aber doch semantisch falsch! Warum?? */
1866         }
1867       } else {
1868         in[n_preds] = get_Phi_pred(phi, i);
1869         n_preds ++;
1870       }
1871     }
1872     /* Fix the node */
1873     set_irn_in(phi, n_preds, in);
1874
1875     phi = get_irn_link(phi);
1876   }
1877
1878   /*- This happens only if merge between loop backedge and single loop entry. -*/
1879   for (k = 0; k < get_Block_n_cfgpreds(b); k++) {
1880     pred = get_nodes_Block(get_Block_cfgpred(b, k));
1881     if (get_Block_block_visited(pred)+1 < get_irg_block_visited(current_ir_graph)) {
1882       phi = get_irn_link(pred);
1883       while (phi) {
1884         if (get_irn_op(phi) == op_Phi) {
1885           set_nodes_Block(phi, b);
1886
1887           n_preds = 0;
1888           for (i = 0; i < k; i++) {
1889             pred = get_nodes_Block(get_Block_cfgpred(b, i));
1890             if (is_Bad(get_Block_cfgpred(b, i))) {
1891               /* Do nothing */
1892             } else if (get_Block_block_visited(pred) +1
1893                        < get_irg_block_visited(current_ir_graph)) {
1894               /* It's an empty block and not yet visited. */
1895               for (j = 0; j < get_Block_n_cfgpreds(pred); j++) {
1896                 /* @@@ Hier brauche ich Schleifeninformation!!! Kontrollflusskante
1897                    muss Rueckwaertskante sein! (An allen vier in[n_preds] = phi
1898                    Anweisungen.) Trotzdem tuts bisher!! */
1899                 in[n_preds] = phi;
1900                 n_preds++;
1901               }
1902             } else {
1903               in[n_preds] = phi;
1904               n_preds++;
1905             }
1906           }
1907           for (i = 0; i < get_Phi_n_preds(phi); i++) {
1908             in[n_preds] = get_Phi_pred(phi, i);
1909             n_preds++;
1910           }
1911           for (i = k+1; i < get_Block_n_cfgpreds(b); i++) {
1912             pred = get_nodes_Block(get_Block_cfgpred(b, i));
1913             if (is_Bad(get_Block_cfgpred(b, i))) {
1914               /* Do nothing */
1915             } else if (get_Block_block_visited(pred) +1
1916                        < get_irg_block_visited(current_ir_graph)) {
1917               /* It's an empty block and not yet visited. */
1918               for (j = 0; j < get_Block_n_cfgpreds(pred); j++) {
1919                 in[n_preds] = phi;
1920                 n_preds++;
1921               }
1922             } else {
1923               in[n_preds] = phi;
1924               n_preds++;
1925             }
1926           }
1927           set_irn_in(phi, n_preds, in);
1928         }
1929         phi = get_irn_link(phi);
1930       }
1931     }
1932   }
1933
1934   /*- Fix the block -*/
1935   n_preds = 0;
1936   for (i = 0; i < get_Block_n_cfgpreds(b); i++) {
1937     pred = get_nodes_Block(get_Block_cfgpred(b, i));
1938     if (is_Bad(get_Block_cfgpred(b, i))) {
1939       /* Do nothing */
1940     } else if (get_Block_block_visited(pred) +1
1941            < get_irg_block_visited(current_ir_graph)) {
1942       /* It's an empty block and not yet visited. */
1943       assert(get_Block_n_cfgpreds(b) > 1);
1944                         /* Else it should be optimized by equivalent_node. */
1945       for (j = 0; j < get_Block_n_cfgpreds(pred); j++) {
1946         in[n_preds] = get_Block_cfgpred(pred, j);
1947         n_preds++;
1948       }
1949       /* Remove block as it might be kept alive. */
1950       exchange(pred, b/*new_Bad()*/);
1951     } else {
1952       in[n_preds] = get_Block_cfgpred(b, i);
1953       n_preds ++;
1954     }
1955   }
1956   set_irn_in(b, n_preds, in);
1957   free(in);
1958 }
1959
1960 /**
1961  * an impossible ir_node * != NULL
1962  */
1963 static const char _anchor;
1964 #define ANCHOR  ((ir_node *)&_anchor)
1965
1966 /**
1967  * optimize constant cond with projs
1968  *
1969  * If we come here, we should have 3 situations:
1970  *
1971  * 1.) Only one Proj exists: This should be the default Proj, convert to jump
1972  * 2.) Two Proj's exists: One is the taken, the other the not-taken default proj
1973  * 3.) More than 2 Proj's: local_optimize() did not run or internal error do nothing
1974  */
1975 static void optimize_const_conds(ir_node *cond_list)
1976 {
1977   ir_node *cond, *next;
1978
1979   for (cond = cond_list; cond != ANCHOR; cond = next) {
1980     ir_node *block, *jmp;
1981     ir_node *proj = NULL, *def_proj = NULL;
1982     int num = 0;
1983
1984     for (next = get_irn_link(cond); next != ANCHOR; next = get_irn_link(next)) {
1985       if (get_irn_op(next) == op_Cond)
1986         break;
1987
1988       assert(get_irn_op(next) == op_Proj && "something neither Cond not Proj in cond-list");
1989       assert(get_Proj_pred(next) == cond && "cond-list corrupt");
1990
1991       if (get_Proj_proj(next) == get_Cond_defaultProj(cond))
1992         def_proj = next;
1993       else
1994         proj = next;
1995       ++num;
1996     }
1997
1998     if (num == 1) {
1999       assert(def_proj);
2000
2001       block = get_nodes_block(def_proj);
2002       jmp = new_rd_Jmp(get_irn_dbg_info(def_proj), current_ir_graph, block);
2003       exchange(def_proj, jmp);
2004     }
2005     else if (num == 2) {
2006       assert(def_proj && proj);
2007
2008       exchange(def_proj, new_Bad());
2009
2010       block = get_nodes_block(proj);
2011       jmp = new_rd_Jmp(get_irn_dbg_info(proj), current_ir_graph, block);
2012       exchange(proj, jmp);
2013     }
2014   }
2015 }
2016
2017 void optimize_cf(ir_graph *irg) {
2018   int i;
2019   ir_node **in;
2020   ir_node *end = get_irg_end(irg);
2021   ir_graph *rem = current_ir_graph;
2022   current_ir_graph = irg;
2023   ir_node *cond_list = ANCHOR;
2024
2025   /* Handle graph state */
2026   assert(get_irg_phase_state(irg) != phase_building);
2027   if (get_irg_outs_state(current_ir_graph) == outs_consistent)
2028     set_irg_outs_inconsistent(current_ir_graph);
2029   if (get_irg_dom_state(current_ir_graph) == dom_consistent)
2030     set_irg_dom_inconsistent(current_ir_graph);
2031
2032   /* Use block visited flag to mark non-empty blocks. */
2033   inc_irg_block_visited(irg);
2034   irg_walk(end, merge_blocks, collect_nodes, &cond_list);
2035
2036   /* now, optimize switches */
2037   if (get_opt_unreachable_code())
2038     optimize_const_conds(cond_list);
2039
2040   /* Optimize the standard code. */
2041   irg_block_walk(get_irg_end_block(irg), optimize_blocks, NULL, NULL);
2042
2043   /* Walk all keep alives, optimize them if block, add to new in-array
2044      for end if useful. */
2045   in = NEW_ARR_F (ir_node *, 1);
2046   in[0] = get_nodes_Block(end);
2047   inc_irg_visited(current_ir_graph);
2048   for(i = 0; i < get_End_n_keepalives(end); i++) {
2049     ir_node *ka = get_End_keepalive(end, i);
2050     if (irn_not_visited(ka)) {
2051       if ((get_irn_op(ka) == op_Block) && Block_not_block_visited(ka)) {
2052         set_irg_block_visited(current_ir_graph,  /* Don't walk all the way to Start. */
2053          get_irg_block_visited(current_ir_graph)-1);
2054         irg_block_walk(ka, optimize_blocks, NULL, NULL);
2055         mark_irn_visited(ka);
2056         ARR_APP1 (ir_node *, in, ka);
2057       } else if (get_irn_op(ka) == op_Phi) {
2058         mark_irn_visited(ka);
2059         ARR_APP1 (ir_node *, in, ka);
2060       }
2061     }
2062   }
2063   /* DEL_ARR_F(end->in);   GL @@@ tut nicht ! */
2064   end->in = in;
2065
2066   current_ir_graph = rem;
2067 }
2068
2069
2070 /**
2071  * Called by walker of remove_critical_cf_edges().
2072  *
2073  * Place an empty block to an edge between a blocks of multiple
2074  * predecessors and a block of multiple successors.
2075  *
2076  * @param n IR node
2077  * @param env Environment of walker. This field is unused and has
2078  *            the value NULL.
2079  */
2080 static void walk_critical_cf_edges(ir_node *n, void *env) {
2081   int arity, i;
2082   ir_node *pre, *block, **in, *jmp;
2083
2084   arity = get_irn_arity(n);
2085
2086   /* Block has multiple predecessors */
2087   if (op_Block == get_irn_op(n) && arity > 1) {
2088
2089     if (n == get_irg_end_block(current_ir_graph))
2090       return;  /*  No use to add a block here.      */
2091
2092     for (i = 0; i < arity; ++i) {
2093       pre = get_irn_n(n, i);
2094       /* Predecessor has multiple successors. Insert new flow edge */
2095       if ((NULL != pre) &&
2096         (op_Proj == get_irn_op(pre)) &&
2097         op_Raise != get_irn_op(skip_Proj(pre))) {
2098
2099         /* set predecessor array for new block */
2100         in = NEW_ARR_D (ir_node *, current_ir_graph->obst, 1);
2101         /* set predecessor of new block */
2102         in[0] = pre;
2103         block = new_Block(1, in);
2104         /* insert new jmp node to new block */
2105         switch_block(block);
2106         jmp = new_Jmp();
2107         switch_block(n);
2108         /* set successor of new block */
2109         set_irn_n(n, i, jmp);
2110
2111       } /* predecessor has multiple successors */
2112     } /* for all predecessors */
2113   } /* n is a block */
2114 }
2115
2116 void remove_critical_cf_edges(ir_graph *irg) {
2117   if (get_opt_critical_edges())
2118     irg_walk_graph(irg, NULL, walk_critical_cf_edges, NULL);
2119 }