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