adding assertion to prevent recursive compound types
[libfirm] / ir / opt / cfopt.c
1 /*
2  * Project:     libFIRM
3  * File name:   ir/opt/cfopt.c
4  * Purpose:     control flow optimizations
5  * Author:
6  * Created:
7  * CVS-ID:      $Id$
8  * Copyright:   (c) 1998-2004 Universität Karlsruhe
9  * Licence:     This file protected by GPL -  GNU GENERAL PUBLIC LICENSE.
10  */
11
12 #ifdef HAVE_CONFIG_H
13 # include "config.h"
14 #endif
15
16 #include <assert.h>
17
18 #include "xmalloc.h"
19 #include "irnode_t.h"
20 #include "irgraph_t.h"
21 #include "irprog_t.h"
22
23 #include "ircons.h"
24 #include "iropt_t.h"
25 #include "irgwalk.h"
26 #include "irgmod.h"
27 #include "irdump.h"
28 #include "irvrfy.h"
29
30 #include "array.h"
31
32 #include "irouts.h"
33 #include "irbackedge_t.h"
34
35 #include "irflag_t.h"
36 #include "firmstat.h"
37
38 #include "cfopt.h"
39 #include "iropt_dbg.h"
40
41 /*------------------------------------------------------------------*/
42 /* Control flow optimization.                                       */
43 /*                                                                  */
44 /* Removes Bad control flow predecessors and empty blocks.  A block */
45 /* is empty if it contains only a Jmp node.                         */
46 /* Blocks can only be removed if they are not needed for the        */
47 /* semantics of Phi nodes.                                          */
48 /*------------------------------------------------------------------*/
49
50 /**
51  * Replace binary Conds that jumps twice into the same block
52  * by a simple Jmp.
53  * E.g.
54  * @code
55  *               Cond                     Jmp  Bad
56  *             /       \                   |   /
57  *       ProjX True   ProjX False  ==>     |  /
58  *             \       /                   | /
59  *               Block                    Block
60  * @endcode
61  *
62  * Such pattern are the result of if-conversion.
63  *
64  * Note that the simple case that Block has only these two
65  * predecessors are already handled in equivalent_node_Block().
66  */
67 static void remove_senseless_conds(ir_node *bl, void *data)
68 {
69   int i, j;
70   int n = get_Block_n_cfgpreds(bl);
71
72   assert(is_Block(bl));
73
74   for (i = 0; i < n; ++i) {
75     ir_node *pred_i = get_Block_cfgpred(bl, i);
76     ir_node *cond_i = skip_Proj(pred_i);
77
78     for (j = i + 1; j < n; ++j) {
79       ir_node *pred_j = get_Block_cfgpred(bl, j);
80       ir_node *cond_j = skip_Proj(pred_j);
81
82       if (cond_j == cond_i
83           && get_irn_op(cond_i) == op_Cond
84           && get_irn_mode(get_Cond_selector(cond_i)) == mode_b) {
85
86         ir_node *jmp = new_r_Jmp(current_ir_graph, get_nodes_block(cond_i));
87         set_irn_n(bl, i, jmp);
88         set_irn_n(bl, j, new_Bad());
89
90         DBG_OPT_IFSIM2(cond_i, jmp);
91         break;
92       }
93     }
94   }
95 }
96
97
98 /**
99  * Removes Tuples from Block control flow predecessors.
100  * Optimizes blocks with equivalent_node().  This is tricky,
101  * as we want to avoid nodes that have as block predecessor Bads.
102  * Therefore we also optimize at control flow operations, depending
103  * how we first reach the Block.
104  */
105 static void merge_blocks(ir_node *n, void *env) {
106   int i;
107   ir_node *new_block;
108
109   /* clear the link field for ALL nodes first */
110   set_irn_link(n, NULL);
111
112   if (get_irn_op(n) == op_Block) {
113     /* Remove Tuples */
114     for (i = 0; i < get_Block_n_cfgpreds(n); i++) {
115       /* GL @@@ : is this possible? if (get_opt_normalize()) -- added, all tests go through.
116          A different order of optimizations might cause problems. */
117       if (get_opt_normalize())
118         set_Block_cfgpred(n, i, skip_Tuple(get_Block_cfgpred(n, i)));
119     }
120
121     /* see below */
122     new_block = equivalent_node(n);
123     if (new_block != n && ! is_Block_dead(new_block))
124       exchange (n, new_block);
125
126   } else if (get_opt_optimize() && (get_irn_mode(n) == mode_X)) {
127     /* We will soon visit a block.  Optimize it before visiting! */
128     ir_node *b = get_nodes_block(skip_Proj(n));
129
130     if (!is_Block_dead(b)) {
131       new_block = equivalent_node(b);
132
133       while (irn_not_visited(b) && (!is_Block_dead(new_block)) && (new_block != b)) {
134         /* We would have to run gigo() if new is bad, so we
135            promote it directly below. Nevertheless, we sometimes reach a block
136            the first time through a dataflow node.  In this case we optimized the
137            block as such and have to promote the Bad here. */
138         assert((get_opt_control_flow_straightening() ||
139                 get_opt_control_flow_weak_simplification()) &&
140                ("strange flag setting"));
141         exchange (b, new_block);
142         b = new_block;
143         new_block = equivalent_node(b);
144       }
145
146       /* normally, we would create a Bad block here, but this must be
147        * prevented, so just set it's cf to Bad.
148        */
149       if (is_Block_dead(new_block))
150         exchange(n, new_Bad());
151     }
152   }
153 }
154
155 /**
156  * Remove cf from dead block by inspecting dominance info
157  * Do not replace blocks by Bad.  This optimization shall
158  * ensure, that all Bad control flow predecessors are
159  * removed, and no new other Bads are introduced.
160  *
161  * Must be run in the post walker.
162  */
163 static void remove_dead_block_cf(ir_node *block, void *env)
164 {
165   int i, n;
166
167   /* check block predecessors and turn control flow into bad */
168   for (i = 0, n = get_Block_n_cfgpreds(block); i < n; ++i) {
169     ir_node *pred_X = get_Block_cfgpred(block, i);
170
171     if (! is_Bad(pred_X)) {
172       ir_node *pred_bl = get_nodes_block(skip_Proj(pred_X));
173
174       if (is_Block_dead(pred_bl) || (get_Block_dom_depth(pred_bl) < 0))
175         exchange (pred_X, new_Bad());
176     }
177   }
178 }
179
180 /**
181  * Collects all Phi nodes in link list of Block.
182  * Marks all blocks "block_visited" if they contain a node other
183  * than Jmp.
184  * Replaces n by Bad if n is unreachable control flow. We do that
185  * in the post walker, so we catch all blocks.
186  */
187 static void collect_nodes(ir_node *n, void *env) {
188   if (is_no_Block(n)) {
189     ir_node *b = get_nodes_block(n);
190
191     if ((get_irn_op(n) == op_Phi)) {
192       /* Collect Phi nodes to compact ins along with block's ins. */
193       set_irn_link(n, get_irn_link(b));
194       set_irn_link(b, n);
195     }
196     else if ((get_irn_op(n) != op_Jmp) && !is_Bad(b)) {  /* Check for non empty block. */
197       mark_Block_block_visited(b);
198     }
199   }
200 }
201
202 /** Returns true if pred is predecessor of block. */
203 static int is_pred_of(ir_node *pred, ir_node *b) {
204   int i, n;
205
206   for (i = 0, n = get_Block_n_cfgpreds(b); i < n; ++i) {
207     ir_node *b_pred = get_nodes_block(get_Block_cfgpred(b, i));
208     if (b_pred == pred) return 1;
209   }
210   return 0;
211 }
212
213
214 /** Test whether we can optimize away pred block pos of b.
215  *
216  *  @param  b    A block node.
217  *  @param  pos  The position of the predecessor block to judge about.
218  *
219  *  @returns     The number of predecessors
220  *
221  *  The test is rather tricky.
222  *
223  *  The situation is something like the following:
224  *
225  *                 if-block
226  *                  /   \
227  *              then-b  else-b
228  *                  \   /
229  *                    b
230  *
231  *     b merges the control flow of an if-then-else.  We may not remove
232  *     the 'then' _and_ the 'else' block of an 'if' if there is a Phi
233  *     node in b, even if both are empty.  The destruction of this Phi
234  *     requires that a copy is added before the merge.  We have to
235  *     keep one of the case blocks to place the copies in.
236  *
237  *     To perform the test for pos, we must regard predecessors before pos
238  *     as already removed.
239  **/
240 static int test_whether_dispensable(ir_node *b, int pos) {
241   int i, j, n_preds = 1;
242   int dispensable = 1;
243   ir_node *cfop = get_Block_cfgpred(b, pos);
244   ir_node *pred = get_nodes_block(cfop);
245
246   /* Bad blocks will be optimized away, so we don't need space for them */
247   if (is_Bad(pred))
248     return 0;
249
250   if (get_Block_block_visited(pred) + 1
251       < get_irg_block_visited(current_ir_graph)) {
252
253     if (!get_opt_optimize() || !get_opt_control_flow_strong_simplification()) {
254       /* Mark block so that is will not be removed: optimization is turned off. */
255       set_Block_block_visited(pred, get_irg_block_visited(current_ir_graph)-1);
256       return 1;
257     }
258
259     /* Seems to be empty. At least we detected this in collect_nodes. */
260     if (!get_irn_link(b)) {
261       /* There are no Phi nodes ==> all predecessors are dispensable. */
262       n_preds = get_Block_n_cfgpreds(pred);
263     } else {
264       /* b's pred blocks and pred's pred blocks must be pairwise disjunct.
265          Work preds < pos as if they were already removed. */
266       for (i = 0; i < pos; i++) {
267         ir_node *b_pred = get_nodes_block(get_Block_cfgpred(b, i));
268         if (get_Block_block_visited(b_pred) + 1
269             < get_irg_block_visited(current_ir_graph)) {
270           for (j = 0; j < get_Block_n_cfgpreds(b_pred); j++) {
271             ir_node *b_pred_pred = get_nodes_block(get_Block_cfgpred(b_pred, j));
272             if (is_pred_of(b_pred_pred, pred)) dispensable = 0;
273           }
274         } else {
275           if (is_pred_of(b_pred, pred)) dispensable = 0;
276         }
277       }
278       for (i = pos +1; i < get_Block_n_cfgpreds(b); i++) {
279         ir_node *b_pred = get_nodes_block(get_Block_cfgpred(b, i));
280         if (is_pred_of(b_pred, pred)) dispensable = 0;
281       }
282       if (!dispensable) {
283         set_Block_block_visited(pred, get_irg_block_visited(current_ir_graph)-1);
284         n_preds = 1;
285       } else {
286         n_preds = get_Block_n_cfgpreds(pred);
287       }
288     }
289   }
290
291   return n_preds;
292 }
293
294
295 /**
296  * This method removed Bad cf predecessors from Blocks and Phis, and removes
297  * empty blocks.  A block is empty if it only contains Phi and Jmp nodes.
298  *
299  * We first adapt Phi nodes, then Block nodes, as we need the old ins
300  * of the Block to adapt the Phi nodes.  We do this by computing new
301  * in arrays, and then replacing the old ones.  So far we compute new in arrays
302  * for all nodes, not regarding whether there is a possibility for optimization.
303  *
304  * For each predecessor p of a Block b there are three cases:
305  *  1. The predecessor p is a Bad node:  just skip it.  The in array of b shrinks by one.
306  *  2. The predecessor p is empty.  Remove p.  All predecessors of p are now
307  *     predecessors of b.
308  *  3. The predecessor p is a block containing useful code.  Just keep p as is.
309  *
310  * For Phi nodes f we have to check the conditions at the Block of f.
311  * For cases 1 and 3 we proceed as for Blocks.  For case 2 we can have two
312  * cases:
313  *  2a: The old predecessor of the Phi f is a Phi pred_f IN THE BLOCK REMOVED.  In this
314  *      case we proceed as for blocks. We remove pred_f.  All
315  *      predecessors of pred_f now are predecessors of f.
316  *  2b: The old predecessor of f is NOT in the block removed. It might be a Phi, too.
317  *      We have to replicate f for each predecessor of the removed block. Or, with
318  *      other words, the removed predecessor block has exactly one predecessor.
319  *
320  * Further there is a special case for self referencing blocks:
321  *
322  *    then_b     else_b                              then_b  else_b
323  *       \      /                                      \      /
324  *        \    /                                        |    /
325  *        pred_b                                        |   /
326  *         |   ____                                     |  /
327  *         |  |    |                                    |  | |    |
328  *         |  |    |       === optimized to ===>        \  | |    |
329  *        loop_b   |                                     loop_b   |
330  *         |  |    |                                      |  |    |
331  *         |  |____|                                      |  |____|
332  *         |                                              |
333  *
334  * If there is a Phi in pred_b, but we remove pred_b, we have to generate a
335  * Phi in loop_b, that has the ins of the Phi in pred_b and a self referencing
336  * backedge.
337  * @@@ It is negotiable whether we should do this ... there might end up a copy
338  * from the Phi in the loop when removing the Phis.
339  */
340 static void optimize_blocks(ir_node *b, void *env) {
341   int i, j, k, n, max_preds, n_preds, p_preds;
342   ir_node *pred, *phi;
343   ir_node **in;
344
345   /* Count the number of predecessor if this block is merged with pred blocks
346      that are empty. */
347   max_preds = 0;
348   for (i = 0, k = get_Block_n_cfgpreds(b); i < k; ++i) {
349     max_preds += test_whether_dispensable(b, i);
350   }
351   in = xmalloc(max_preds * sizeof(*in));
352
353 /*-
354   printf(" working on "); DDMN(b);
355   for (i = 0; i < get_Block_n_cfgpreds(b); i++) {
356     pred = get_nodes_block(get_Block_cfgpred(b, i));
357     if (is_Bad(get_Block_cfgpred(b, i))) {
358       printf("  removing Bad %i\n ", i);
359     } else if (get_Block_block_visited(pred) +1
360            < get_irg_block_visited(current_ir_graph)) {
361       printf("  removing pred %i ", i); DDMN(pred);
362     } else { printf("  Nothing to do for "); DDMN(pred); }
363   }
364   * end Debug output -*/
365
366   /*- Fix the Phi nodes of the current block -*/
367   for (phi = get_irn_link(b); phi; ) {
368     assert(get_irn_op(phi) == op_Phi);
369
370     /* Find the new predecessors for the Phi */
371     p_preds = 0;
372     for (i = 0, n = get_Block_n_cfgpreds(b); i < n; ++i) {
373       pred = get_nodes_block(get_Block_cfgpred(b, i));
374
375       if (is_Bad(get_Block_cfgpred(b, i))) {
376         /* case Phi 1: Do nothing */
377       }
378       else if (get_Block_block_visited(pred) + 1
379                  < get_irg_block_visited(current_ir_graph)) {
380         /* case Phi 2: It's an empty block and not yet visited. */
381         ir_node *phi_pred = get_Phi_pred(phi, i);
382
383         for (j = 0, k = get_Block_n_cfgpreds(pred); j < k; j++) {
384           /* because of breaking loops, not all predecessors are Bad-clean,
385            * so we must check this here again */
386           if (! is_Bad(get_Block_cfgpred(pred, j))) {
387             if (get_nodes_block(phi_pred) == pred) {
388               /* case Phi 2a: */
389               assert(get_irn_op(phi_pred) == op_Phi);  /* Block is empty!! */
390
391               in[p_preds++] = get_Phi_pred(phi_pred, j);
392             } else {
393               /* case Phi 2b: */
394               in[p_preds++] = phi_pred;
395             }
396           }
397         }
398
399         /* The Phi_pred node is replaced now if it is a Phi.
400
401            Somehow the removed Phi node can be used legally in loops.
402            Therefore we replace the old phi by the new one.
403
404            Further we have to remove the old Phi node by replacing it
405            by Bad.  Else it will remain in the keep alive array of End
406            and cause illegal situations.  So if there is no loop, we should
407            replace it by Bad.
408         */
409         if (get_nodes_block(phi_pred) == pred) {
410           /* remove the Phi as it might be kept alive. Further there
411              might be other users. */
412           exchange(phi_pred, phi);  /* geht, ist aber doch semantisch falsch! Warum?? */
413         }
414       } else {
415         /* case Phi 3: */
416         in[p_preds++] = get_Phi_pred(phi, i);
417       }
418     }
419     assert(p_preds <= max_preds);
420
421     /* Fix the node */
422     if (p_preds == 1)
423       /* By removal of Bad ins the Phi might be degenerated. */
424       exchange(phi, in[0]);
425     else
426       set_irn_in(phi, p_preds, in);
427
428     phi = get_irn_link(phi);
429   }
430
431   /*- This happens only if merge between loop backedge and single loop entry.
432       See special case above. -*/
433   for (k = 0, n = get_Block_n_cfgpreds(b); k < n; ++k) {
434     pred = get_nodes_block(get_Block_cfgpred(b, k));
435
436     if (get_Block_block_visited(pred) + 1 < get_irg_block_visited(current_ir_graph)) {
437       /* we found a predecessor block at position k that will be removed */
438       for (phi = get_irn_link(pred); phi;) {
439         /*
440          * the previous phase may already changed the phi, and even
441          * removed it at all, so check here if this node is still a phi
442          */
443         if (get_irn_op(phi) == op_Phi) {
444           int q_preds = 0;
445
446           /* move this phi from the predecessor into the block b */
447           set_nodes_block(phi, b);
448
449           /* first, copy all 0..k-1 predecessors */
450           for (i = 0; i < k; i++) {
451             pred = get_nodes_block(get_Block_cfgpred(b, i));
452
453             if (is_Bad(get_Block_cfgpred(b, i))) {
454               /* Do nothing */
455             } else if (get_Block_block_visited(pred) + 1
456                < get_irg_block_visited(current_ir_graph)) {
457               /* It's an empty block and not yet visited. */
458               for (j = 0; j < get_Block_n_cfgpreds(pred); j++) {
459                 /* @@@ Hier brauche ich Schleifeninformation!!! Kontrollflusskante
460                    muss Rueckwaertskante sein! (An allen vier in[q_preds] = phi
461                    Anweisungen.) Trotzdem tuts bisher!! */
462                 if (! is_Bad(get_Block_cfgpred(pred, j)))
463                   in[q_preds++] = phi;
464               }
465             } else {
466               in[q_preds++] = phi;
467             }
468           }
469
470           /* now we are at k, copy the phi predecessors */
471           pred = get_nodes_block(get_Block_cfgpred(b, k));
472           for (i = 0; i < get_Phi_n_preds(phi); i++) {
473             if (! is_Bad(get_Block_cfgpred(pred, i)))
474               in[q_preds++] = get_Phi_pred(phi, i);
475           }
476
477           /* and now all the rest */
478           for (i = k+1; i < get_Block_n_cfgpreds(b); i++) {
479             pred = get_nodes_block(get_Block_cfgpred(b, i));
480
481             if (is_Bad(get_Block_cfgpred(b, i))) {
482               /* Do nothing */
483             } else if (get_Block_block_visited(pred) +1
484                < get_irg_block_visited(current_ir_graph)) {
485               /* It's an empty block and not yet visited. */
486               for (j = 0; j < get_Block_n_cfgpreds(pred); j++) {
487                 if (! is_Bad(get_Block_cfgpred(pred, j)))
488                   in[q_preds++] = phi;
489               }
490             } else {
491               in[q_preds++] = phi;
492             }
493           }
494
495           /* Fix the node */
496           if (q_preds == 1)
497             exchange(phi, in[0]);
498           else
499             set_irn_in(phi, q_preds, in);
500
501           assert(q_preds <= max_preds);
502 //        assert(p_preds == q_preds && "Wrong Phi Fix");
503         }
504         phi = get_irn_link(phi);
505       }
506     }
507   }
508
509   /*- Fix the block -*/
510   n_preds = 0;
511   for (i = 0; i < get_Block_n_cfgpreds(b); i++) {
512     pred = get_nodes_block(get_Block_cfgpred(b, i));
513
514     if (is_Bad(get_Block_cfgpred(b, i))) {
515       /* case 1: Do nothing */
516     } else if (get_Block_block_visited(pred) +1
517            < get_irg_block_visited(current_ir_graph)) {
518       /* case 2: It's an empty block and not yet visited. */
519       assert(get_Block_n_cfgpreds(b) > 1);
520                         /* Else it should be optimized by equivalent_node. */
521       for (j = 0; j < get_Block_n_cfgpreds(pred); j++) {
522         ir_node *pred_block = get_Block_cfgpred(pred, j);
523
524         /* because of breaking loops, not all predecessors are Bad-clean,
525          * so we must check this here again */
526         if (! is_Bad(pred_block))
527           in[n_preds++] = pred_block;
528       }
529       /* Remove block as it might be kept alive. */
530       exchange(pred, b/*new_Bad()*/);
531     } else {
532       /* case 3: */
533       in[n_preds++] = get_Block_cfgpred(b, i);
534     }
535   }
536   assert(n_preds <= max_preds);
537
538   set_irn_in(b, n_preds, in);
539
540   assert(get_irn_link(b) == NULL || (n_preds == p_preds && "Wrong Phi Fix"));
541
542   xfree(in);
543 }
544
545
546 /* Optimizations of the control flow that also require changes of Phi nodes.
547  *
548  * This optimization performs two passes over the graph.
549  *
550  * The first pass collects all Phi nodes in a link list in the block
551  * nodes.  Further it performs simple control flow optimizations.
552  * Finally it marks all blocks that do not contain useful
553  * computations, i.e., these blocks might be removed.
554  *
555  * The second pass performs the optimizations intended by this algorithm.
556  * It walks only over block nodes and adapts these and the Phi nodes in these blocks,
557  * which it finds in a linked list computed by the first pass.
558  *
559  * We use the block_visited flag to mark empty blocks in the first
560  * phase.
561  * @@@ It would be better to add a struct in the link field
562  * that keeps the Phi list and the mark.  Place it on an obstack, as
563  * we will lose blocks and thereby generate memory leaks.
564  */
565 void optimize_cf(ir_graph *irg) {
566   int i, n;
567   ir_node **in;
568   ir_node *end = get_irg_end(irg);
569   ir_graph *rem = current_ir_graph;
570   irg_dom_state dom_state = get_irg_dom_state(current_ir_graph);
571   current_ir_graph = irg;
572
573   /* if the graph is not pinned, we cannot determine empty blocks */
574   assert(get_irg_pinned(irg) != op_pin_state_floats &&
575          "Control flow optimization need a pinned graph");
576
577   /* Handle graph state */
578   assert(get_irg_phase_state(irg) != phase_building);
579   if (get_irg_outs_state(current_ir_graph) == outs_consistent)
580     set_irg_outs_inconsistent(current_ir_graph);
581   if (get_irg_dom_state(current_ir_graph) == dom_consistent)
582     set_irg_dom_inconsistent(current_ir_graph);
583
584   if (dom_state == dom_consistent && get_opt_optimize() && get_opt_unreachable_code()) {
585     ir_node *end = get_irg_end(irg);
586
587     /* we have dominance info, we can kill dead block */
588     irg_block_walk_graph(irg, NULL, remove_dead_block_cf, NULL);
589
590     /* fix the keep-alives */
591     for (i = 0, n = get_End_n_keepalives(end); i < n; ++i) {
592       ir_node *ka = get_End_keepalive(end, i);
593
594       if (is_Block(ka)) {
595         if (get_Block_dom_depth(ka) == -1)
596           set_End_keepalive(end, i, new_Bad());
597       }
598       else if (get_Block_dom_depth(get_nodes_block(ka)) == -1)
599         set_End_keepalive(end, i, new_Bad());
600     }
601   }
602
603   irg_block_walk_graph(current_ir_graph, NULL, remove_senseless_conds, NULL);
604
605   /* Use block visited flag to mark non-empty blocks. */
606   inc_irg_block_visited(irg);
607   irg_walk(end, merge_blocks, collect_nodes, NULL);
608
609   /* Optimize the standard code. */
610   irg_block_walk(get_irg_end_block(irg), optimize_blocks, NULL, NULL);
611
612   /* Walk all keep alives, optimize them if block, add to new in-array
613      for end if useful. */
614   in = NEW_ARR_F (ir_node *, 1);
615   in[0] = get_nodes_block(end);
616   inc_irg_visited(current_ir_graph);
617
618   for (i = 0; i < get_End_n_keepalives(end); i++) {
619     ir_node *ka = get_End_keepalive(end, i);
620
621     if (irn_not_visited(ka)) {
622       if ((get_irn_op(ka) == op_Block) && Block_not_block_visited(ka)) {
623         set_irg_block_visited(current_ir_graph,  /* Don't walk all the way to Start. */
624               get_irg_block_visited(current_ir_graph)-1);
625         irg_block_walk(ka, optimize_blocks, NULL, NULL);
626         mark_irn_visited(ka);
627         ARR_APP1 (ir_node *, in, ka);
628       } else if (get_irn_op(ka) == op_Phi) {
629         mark_irn_visited(ka);
630         ARR_APP1 (ir_node *, in, ka);
631       } else if (get_irn_op(ka) == op_IJmp) {
632         mark_irn_visited(ka);
633         ARR_APP1 (ir_node *, in, ka);
634       }
635     }
636   }
637   /* DEL_ARR_F(end->in);   GL @@@ tut nicht ! */
638   end->in = in;
639
640
641   /* the verifier doesn't work yet with floating nodes */
642   if (get_irg_pinned(irg) == op_pin_state_pinned) {
643     /* after optimize_cf(), only Bad data flow may remain. */
644     if (irg_vrfy_bads(irg, BAD_DF | BAD_BLOCK | TUPLE)) {
645       dump_ir_block_graph(irg, "-vrfy-cf");
646       dump_ir_graph(irg, "-vrfy-cf");
647       fprintf(stderr, "VRFY_BAD in optimize_cf()\n");
648     }
649   }
650
651   current_ir_graph = rem;
652 }