optimize_graph_df():
[libfirm] / ir / opt / ifconv.c
1 /*
2  * Project:     libFIRM
3  * File name:   ir/opt/ifconv.c
4  * Purpose:     If conversion
5  * Author:      Sebastian Hack.
6  * Created:
7  * CVS-ID:      $Id$
8  * Copyright:   (c) 1998-2005 Universität Karlsruhe
9  * Licence:     This file protected by GPL -  GNU GENERAL PUBLIC LICENSE.
10  */
11
12 #if 1
13
14 #include <assert.h>
15 #include <stdlib.h>
16 #include "cdep.h"
17 #include "ircons.h"
18 #include "ifconv.h"
19 #include "irdom.h"
20 #include "irgmod.h"
21 #include "irgopt.h"
22 #include "irgwalk.h"
23 #include "irtools.h"
24 #include "return.h"
25 #include "xmalloc.h"
26
27 // debug
28 #include "irdump.h"
29 #include "irprintf.h"
30
31
32 static ir_node* walk_to_projx(ir_node* start)
33 {
34         ir_node* pred;
35
36         pred = get_nodes_block(start);
37
38         /* if there are multiple control flow predecessors nothing sensible can be
39          * done */
40         if (get_irn_arity(pred) > 1) return NULL;
41
42         pred = get_irn_n(pred, 0);
43         if (get_irn_op(pred) == op_Proj) {
44                 assert(get_irn_mode(pred) == mode_X);
45                 return pred;
46         } else {
47                 return NULL;
48         }
49 }
50
51
52 typedef struct block_info {
53         ir_node* phi;
54         int evil;
55 } block_info;
56
57 #define get_block_blockinfo(block) ((block_info*)get_irn_link(block))
58
59 static int can_empty_block(ir_node* block)
60 {
61         return !get_block_blockinfo(block)->evil;
62 }
63
64
65 /**
66  * Copies the DAG starting at node to the ith predecessor block of src_block
67  * -if the node isn't in the src_block, this is a nop and the node is returned
68  * -if the node is a phi in the src_block, the ith predecessor of the phi is
69  *   returned
70  * otherwise returns the copy of the passed node
71  */
72 static ir_node* copy_to(ir_node* node, ir_node* src_block, int i)
73 {
74         ir_node* dst_block;
75         ir_node* copy;
76         int arity;
77         int j;
78
79         if (get_nodes_block(node) != src_block) return node;
80         if (get_irn_op(node) == op_Phi) return get_irn_n(node, i);
81
82         copy_irn_to_irg(node, current_ir_graph);
83         copy = get_irn_link(node);
84         dst_block = get_nodes_block(get_irn_n(src_block, i));
85         set_nodes_block(copy, dst_block);
86
87         ir_fprintf(stderr, "Copying node %+F to block %+F, copy is %+F\n",
88                 node, dst_block, copy
89         );
90
91         arity = get_irn_arity(node);
92         for (j = 0; j < arity; ++j) {
93                 set_irn_n(copy, j, copy_to(get_irn_n(node, j), src_block, i));
94                 ir_fprintf(stderr, "-- pred %d is %+F\n", j, get_irn_n(copy, j));
95         }
96         return copy;
97 }
98
99
100 /**
101  * Duplicate and move the contents of ith block predecessor into its
102  * predecessors if the block has multiple control dependencies and only one
103  * successor.
104  * Also bail out if the block contains non-movable nodes, because later
105  * if-conversion would be pointless.
106  */
107 static int fission_block(ir_node* block, int i)
108 {
109         ir_node* pred = get_irn_n(block, i);
110         ir_node* pred_block;
111         block_info* info;
112         ir_node* phi;
113         int pred_arity;
114         int arity;
115         ir_node** ins;
116         int j;
117
118         if (get_irn_op(pred) != op_Jmp) return 0;
119         pred_block = get_nodes_block(pred);
120
121         if (!has_multiple_cdep(pred_block)) return 0;
122         if (!can_empty_block(pred_block)) return 0;
123
124         ir_fprintf(stderr, "Fissioning block %+F\n", pred_block);
125
126         pred_arity = get_irn_arity(pred_block);
127         arity = get_irn_arity(block);
128         info = get_irn_link(block);
129         ins = xmalloc(sizeof(*ins) * (arity + pred_arity - 1));
130         for (phi = info->phi; phi != NULL; phi = get_irn_link(phi)) {
131                 for (j = 0; j < i; ++j) ins[j] = get_irn_n(phi, j);
132                 for (j = 0; j < pred_arity; ++j) {
133                         ins[i + j] = copy_to(get_irn_n(phi, i), pred_block, j);
134                 }
135                 for (j = i + 1; j < arity; ++j) {
136                         ins[pred_arity - 1 + j] = get_irn_n(phi, j);
137                 }
138                 set_irn_in(phi, arity + pred_arity - 1, ins);
139         }
140         for (j = 0; j < i; ++j) ins[j] = get_irn_n(block, j);
141         for (j = 0; j < pred_arity; ++j) ins[i + j] = get_irn_n(pred_block, j);
142         for (j = i + 1; j < arity; ++j) ins[pred_arity - 1 + j] = get_irn_n(block, j);
143         set_irn_in(block, arity + pred_arity - 1, ins);
144         xfree(ins);
145
146         /* Kill all Phis in the fissioned block
147          * This is to make sure they're not kept alive
148          */
149         info = get_irn_link(pred_block);
150         phi = info->phi;
151         while (phi != NULL) {
152                 ir_node* next = get_irn_link(phi);
153                 exchange(phi, new_Bad());
154                 phi = next;
155         }
156         return 1;
157 }
158
159
160 /**
161  * Remove predecessors i and j from node and add predecessor new_pred
162  */
163 static void rewire(ir_node* node, int i, int j, ir_node* new_pred)
164 {
165         int arity = get_irn_arity(node);
166         ir_node** ins = xmalloc(sizeof(*ins) * (arity - 1));
167         int k;
168         int l;
169
170         l = 0;
171         for (k = 0; k < i; ++k) ins[l++] = get_irn_n(node, k);
172         for (++k; k < j; ++k) ins[l++] = get_irn_n(node, k);
173         for (++k; k < arity; ++k) ins[l++] = get_irn_n(node, k);
174         ins[l++] = new_pred;
175         assert(l == arity - 1);
176         set_irn_in(node, l, ins);
177
178         xfree(ins);
179 }
180
181
182 static void if_conv_walker(ir_node* block, void* env)
183 {
184         ir_node* phi;
185         int arity;
186         int i;
187
188         // Bail out, if there are no Phis at all
189         if (get_block_blockinfo(block)->phi == NULL) return;
190
191 restart:
192         arity = get_irn_arity(block);
193         for (i = 0; i < arity; ++i) {
194                 if (fission_block(block, i)) goto restart;
195         }
196         //return;
197
198         arity = get_irn_arity(block);
199         for (i = 0; i < arity; ++i) {
200                 ir_node* pred;
201                 ir_node* cond;
202                 ir_node* projx0;
203                 int j;
204
205                 projx0 = walk_to_projx(get_irn_n(block, i));
206                 if (projx0 == NULL) return;
207                 pred = get_Proj_pred(projx0);
208                 if (get_irn_op(pred) != op_Cond || get_irn_mode(get_Cond_selector(pred)) != mode_b) continue;
209                 cond = pred;
210
211                 if (!can_empty_block(get_nodes_block(get_irn_n(block, i)))) {
212                         ir_fprintf(stderr, "Cannot empty block %+F\n",
213                                 get_nodes_block(get_irn_n(block, i))
214                         );
215                         continue;
216                 }
217
218                 for (j = i + 1; j < arity; ++j) {
219                         ir_node* projx1;
220                         ir_node* psi_block;
221                         ir_node* conds[1];
222                         ir_node* vals[2];
223                         ir_node* psi;
224
225                         projx1 = walk_to_projx(get_irn_n(block, j));
226                         if (projx1 == NULL) continue;
227                         pred = get_Proj_pred(projx1);
228                         if (get_irn_op(pred) != op_Cond || get_irn_mode(get_Cond_selector(pred)) != mode_b) continue;
229                         if (pred != cond) continue;
230                         ir_fprintf(stderr, "Found Cond %+F with proj %+F and %+F\n", cond, projx0, projx1);
231
232                         if (!can_empty_block(get_nodes_block(get_irn_n(block, j)))) {
233                                 ir_fprintf(stderr, "Cannot empty block %+F\n",
234                                         get_nodes_block(get_irn_n(block, j))
235                                 );
236                                 continue;
237                         }
238
239                         conds[0] = get_Cond_selector(cond);
240
241                         psi_block = get_nodes_block(cond);
242                         phi = get_block_blockinfo(block)->phi;
243                         do {
244                                 // Don't generate PsiMs
245                                 if (get_irn_mode(phi) == mode_M) {
246                                         /* Something is very fishy if to predecessors of a PhiM point into the
247                                          * block but not at the same memory node
248                                          */
249                                         assert(get_irn_n(phi, i) == get_irn_n(phi, j));
250                                         // fake memory Psi
251                                         psi = get_irn_n(phi, i);
252                                         ir_fprintf(stderr, "Handling memory Phi %+F\n", phi);
253                                 } else {
254                                         ir_node* val_i = get_irn_n(phi, i);
255                                         ir_node* val_j = get_irn_n(phi, j);
256
257                                         if (val_i == val_j) {
258                                                 psi = val_i;
259                                                 ir_fprintf(stderr, "Generating no psi, because both values are equal\n");
260                                         } else {
261                                                 if (get_Proj_proj(projx0) == pn_Cond_true) {
262                                                         vals[0] = val_i;
263                                                         vals[1] = val_j;
264                                                 } else {
265                                                         vals[0] = val_j;
266                                                         vals[1] = val_i;
267                                                 }
268                                                 psi = new_r_Psi(
269                                                         current_ir_graph, psi_block, 1, conds, vals, get_irn_mode(phi)
270                                                 );
271                                                 ir_fprintf(stderr, "Generating %+F for %+F\n", psi, phi);
272                                         }
273                                 }
274
275                                 if (arity == 2) {
276                                         exchange(phi, psi);
277                                 } else {
278                                         rewire(phi, i, j, psi);
279                                 }
280
281                                 phi = get_irn_link(phi);
282                         } while (phi != NULL);
283
284                         exchange(get_nodes_block(get_irn_n(block, i)), psi_block);
285                         exchange(get_nodes_block(get_irn_n(block, j)), psi_block);
286
287                         if (arity == 2) {
288                                 ir_fprintf(stderr, "Welding block %+F to %+F\n", block, psi_block);
289                                 get_block_blockinfo(psi_block)->evil |= get_block_blockinfo(block)->evil;
290                                 exchange(block, psi_block);
291                                 return;
292                         } else {
293                                 rewire(block, i, j, new_r_Jmp(current_ir_graph, psi_block));
294                                 goto restart;
295                         }
296                 }
297         }
298 }
299
300
301 static void init_block_link(ir_node* block, void* env)
302 {
303         block_info* bi = xmalloc(sizeof(*bi));
304
305         bi->phi = NULL;
306         bi->evil = 0;
307         set_irn_link(block, bi);
308 }
309
310
311 /* Daisy-chain all phis in a block
312  * If a non-movable node is encountered set the evil flag
313  */
314 static void collect_phis(ir_node* node, void* env)
315 {
316         ir_node* block;
317         block_info* bi;
318
319         if (get_irn_op(node) == op_Block) return;
320
321         block = get_nodes_block(node);
322         bi = get_irn_link(block);
323
324         if (get_irn_op(node) == op_Phi) {
325                 set_irn_link(node, bi->phi);
326                 bi->phi = node;
327         } else {
328 #if 1
329                 if (get_irn_op(node) == op_Call ||
330                                 get_irn_op(node) == op_Store ||
331                                 get_irn_op(node) == op_Load) {
332                         ir_fprintf(stderr, "Node %+F in block %+F is unmovable\n", node, block);
333                         bi->evil = 1;
334                 }
335 #else
336                 if (get_irn_op(node) != op_Jmp &&
337                                 get_irn_op(node) != op_Proj &&
338                                 get_irn_op(node) != op_Cond &&
339                                 get_irn_op(node) != op_Cmp &&
340                     !mode_is_datab(get_irn_mode(node))) {
341         ir_fprintf(stderr, "Node %+F in block %+F is unmovable\n", node, block);
342                         bi->evil = 1;
343                 }
344 #endif
345         }
346 }
347
348
349 /*
350  * Transform multiple cascaded Psis into one Psi
351  */
352 static ir_node* fold_psi(ir_node* psi)
353 {
354         int arity = get_Psi_n_conds(psi);
355         int new_arity = 0;
356         int i;
357         ir_node* n;
358         ir_node** conds;
359         ir_node** vals;
360         int j;
361         int k;
362         int a;
363         ir_node* new_psi;
364
365         for (i = 0; i < arity; ++i) {
366                 n = get_Psi_val(psi, i);
367                 if (get_irn_op(n) == op_Psi) {
368                         new_arity += get_Psi_n_conds(n) + 1;
369                 } else {
370                         ++new_arity;
371                 }
372         }
373         n = get_Psi_default(psi);
374         if (get_irn_op(n) == op_Psi) {
375                 new_arity += get_Psi_n_conds(n);
376         }
377
378         if (arity == new_arity) return psi; // no attached Psis found
379         ir_fprintf(stderr, "Folding %+F from %d to %d conds\n", psi, arity, new_arity);
380
381         conds = xmalloc(new_arity * sizeof(*conds));
382         vals = xmalloc((new_arity + 1) * sizeof(*vals));
383         j = 0;
384         for (i = 0; i < arity; ++i) {
385                 ir_node* c = get_Psi_cond(psi, i);
386
387                 n = get_Psi_val(psi, i);
388                 if (get_irn_op(n) == op_Psi) {
389                         a = get_Psi_n_conds(n);
390                         for (k = 0; k < a; ++k) {
391                                 conds[j] = new_r_And(
392                                         current_ir_graph, get_nodes_block(psi),
393                                         c, get_Psi_cond(n, k), mode_b
394                                 );
395                                 vals[j] = get_Psi_val(n, k);
396                                 ++j;
397                         }
398                         conds[j] = c;
399                         vals[j] = get_Psi_default(n);
400                 } else {
401                         conds[j] = c;
402                         vals[j] = n;
403                 }
404                 ++j;
405         }
406         n = get_Psi_default(psi);
407         if (get_irn_op(n) == op_Psi) {
408                 a = get_Psi_n_conds(n);
409                 for (k = 0; k < a; ++k) {
410                         conds[j] = get_Psi_cond(n, k);
411                         vals[j] = get_Psi_val(n, k);
412                         ++j;
413                 }
414                 vals[j] = get_Psi_default(n);
415         } else {
416                 vals[j] = n;
417         }
418         assert(j == new_arity);
419         new_psi = new_r_Psi(
420                 current_ir_graph, get_nodes_block(psi),
421                 new_arity, conds, vals, get_irn_mode(psi)
422         );
423         ir_fprintf(stderr, "Folded %+F into new %+F\n", psi, new_psi);
424         exchange(psi, new_psi);
425         xfree(vals);
426         xfree(conds);
427         return new_psi;
428 }
429
430
431 /*
432  * Merge consecutive psi inputs if the data inputs are the same
433  */
434 static void meld_psi(ir_node* psi)
435 {
436         int arity = get_Psi_n_conds(psi);
437         int new_arity;
438         ir_node** conds;
439         ir_node** vals;
440         ir_node* cond;
441         ir_node* val;
442         int i;
443         int j;
444         ir_node* new_psi;
445
446         new_arity = 1;
447         val = get_Psi_val(psi, 0);
448         ir_fprintf(stderr, "Pred  0 of %+F is %+F\n", psi, val);
449         for (i = 1; i < arity; ++i) {
450                 ir_node* v = get_Psi_val(psi, i);
451                 ir_fprintf(stderr, "Pred %2d of %+F is %+F\n", i, psi, v);
452                 if (val != v) {
453                         val = v;
454                         ++new_arity;
455                 }
456         }
457         ir_fprintf(stderr, "Default of %+F is %+F\n", psi, get_Psi_default(psi));
458         if (val == get_Psi_default(psi)) --new_arity;
459
460         ir_fprintf(stderr, "Melding Psi %+F from %d conds to %d\n",
461                 psi, arity, new_arity
462         );
463
464         if (new_arity == arity) return;
465
466         // If all data inputs of the Psi are equal, exchange the Psi with that value
467         if (new_arity == 0) {
468                 exchange(psi, val);
469                 return;
470         }
471
472         conds = xmalloc(sizeof(*conds) * new_arity);
473         vals = xmalloc(sizeof(*vals) * (new_arity + 1));
474         cond = get_Psi_cond(psi, 0);
475         val = get_Psi_val(psi, 0);
476         j = 0;
477         for (i = 1; i < arity; ++i) {
478                 ir_node* v = get_Psi_val(psi, i);
479
480                 if (v == val) {
481                         cond = new_r_Or(
482                                 current_ir_graph, get_nodes_block(psi),
483                                 cond, get_Psi_cond(psi, i), mode_b
484                         );
485                 } else {
486                         conds[j] = cond;
487                         vals[j] = val;
488                         ++j;
489                         val = v;
490                 }
491         }
492         if (val != get_Psi_default(psi)) {
493                 conds[j] = cond;
494                 vals[j] = val;
495                 ++j;
496         }
497         vals[j] = get_Psi_default(psi);
498         assert(j == new_arity);
499         new_psi = new_r_Psi(
500                 current_ir_graph, get_nodes_block(psi),
501                 new_arity, conds, vals, get_irn_mode(psi)
502         );
503         ir_fprintf(stderr, "Molded %+F into %+F\n", psi, new_psi);
504         exchange(psi, new_psi);
505 }
506
507
508 static void optimise_psis(ir_node* node, void* env)
509 {
510         if (get_irn_op(node) != op_Psi) return;
511 #if 1
512         node = fold_psi(node);
513 #endif
514 #if 1
515         meld_psi(node);
516 #endif
517 }
518
519
520 void opt_if_conv(ir_graph *irg, const opt_if_conv_info_t *params)
521 {
522         ir_fprintf(stderr, "Running if-conversion on %+F\n", irg);
523
524         dump_ir_block_graph(irg, "_00_pre");
525
526         normalize_one_return(irg);
527         remove_critical_cf_edges(irg);
528
529         dump_ir_block_graph(irg, "_01_normal");
530
531         compute_cdep(irg);
532         compute_doms(irg);
533
534         irg_block_walk_graph(irg, init_block_link, NULL, NULL);
535         irg_walk_graph(irg, collect_phis, NULL, NULL);
536         irg_block_walk_graph(irg, NULL, if_conv_walker, NULL);
537
538         local_optimize_graph(irg);
539         dump_ir_block_graph(irg, "_02_ifconv");
540
541         irg_walk_graph(irg, NULL, optimise_psis, NULL);
542
543         dump_ir_block_graph(irg, "_03_postifconv");
544
545         free_dom(irg);
546         free_cdep(irg);
547 }
548
549 #else
550
551 /**
552  * @file ifconv.c
553  * If conversion.
554  * Make Mux nodes from Conds where it its possible.
555  * @author Sebastian Hack
556  * @date 4.2.2005
557  */
558 #ifdef HAVE_CONFIG_H
559 #include "config.h"
560 #endif
561
562 #ifdef HAVE_STDLIB_H
563 #include <stdlib.h>
564 #endif
565 #ifdef HAVE_STRING_H
566 #include <string.h>
567 #endif
568 #ifdef HAVE_ALLOCA_H
569 #include <alloca.h>
570 #endif
571 #ifdef HAVE_xmalloc_H
572 #include <xmalloc.h>
573 #endif
574
575 #include "irgraph_t.h"
576 #include "irnode_t.h"
577 #include "irgwalk.h"
578 #include "iropt_t.h"
579 #include "irgmod.h"
580 #include "irmode_t.h"
581 #include "ircons_t.h"
582 #include "irdom_t.h"
583 #include "irgwalk.h"
584
585 #include "ifconv.h"
586 #include "irflag_t.h"
587
588 #include "irprintf.h"
589 #include "debug.h"
590 #include "obst.h"
591 #include "set.h"
592 #include "bitset.h"
593 #include "bitfiddle.h"
594 #include "irhooks.h"
595 #include "return.h"
596
597 #define MAX_DEPTH   4
598
599 /**
600  * check, if a node is const and return its tarval or
601  * return a default tarval.
602  * @param cnst The node whose tarval to get.
603  * @param or The alternative tarval, if the node is no Const.
604  * @return The tarval of @p cnst, if the node is Const, @p otherwise.
605  */
606 static tarval *get_value_or(ir_node *cnst, tarval *or)
607 {
608   return get_irn_op(cnst) == op_Const ? get_Const_tarval(cnst) : or;
609 }
610
611
612 /**
613  * Try to optimize nested muxes into a dis- or conjunction
614  * of two muxes.
615  * @param mux The parent mux, which has muxes as operands.
616  * @return The replacement node for this mux. If the optimization is
617  * successful, this might be an And or Or node, if not, its the mux
618  * himself.
619  */
620 static ir_node *optimize_mux_chain(ir_node *mux)
621 {
622   int i;
623   ir_node *res;
624   ir_node *ops[2];
625   ir_mode *mode = get_irn_mode(mux);
626   tarval *null;
627   tarval *minus_one;
628
629   /*
630    * If we have no mux, or its mode is not integer, we
631    * can return.
632    */
633   if(get_irn_op(mux) != op_Mux || !mode_is_int(mode))
634     return mux;
635
636   res = mux;
637   null = get_mode_null(mode);
638   minus_one = tarval_sub(null, get_tarval_one(mode));
639
640   ops[0] = get_Mux_false(mux);
641   ops[1] = get_Mux_true(mux);
642
643   for(i = 0; i < 2; ++i) {
644     ir_node *a, *b, *d;
645     tarval *tva, *tvb, *tvd;
646     ir_node *child_mux;
647
648     /*
649      * A mux operand at the first position can be factored
650      * out, if the operands fulfill several conditions:
651      *
652      * mux(c1, mux(c2, a, b), d)
653      *
654      * This can be made into:
655      * 1) mux(c1, 0, d) | mux(c2, a, b)
656      *    if a | d == d and b | d == d
657      *
658      * 2) mux(c1, -1, d) & mux(c2, a, b)
659      *    if a & d == d and a & b == b
660      */
661     if(get_irn_op(ops[i]) == op_Mux) {
662
663       child_mux = ops[i];
664       a = get_Mux_false(child_mux);
665       b = get_Mux_true(child_mux);
666       d = ops[1 - i];
667
668       /* Try the or stuff */
669       tva = get_value_or(a, minus_one);
670       tvb = get_value_or(b, minus_one);
671       tvd = get_value_or(d, null);
672
673       if(tarval_cmp(tarval_or(tva, tvd), tvd) == pn_Cmp_Eq
674           && tarval_cmp(tarval_or(tvb, tvd), tvd) == pn_Cmp_Eq) {
675
676         ops[i] = new_Const(mode, null);
677         res = new_r_Or(current_ir_graph, get_nodes_block(mux),
678             mux, child_mux, mode);
679         break;
680       }
681
682       /* If the or didn't go, try the and stuff */
683       tva = get_value_or(a, null);
684       tvb = get_value_or(b, null);
685       tvd = get_value_or(d, minus_one);
686
687       if(tarval_cmp(tarval_and(tva, tvd), tvd) == pn_Cmp_Eq
688           && tarval_cmp(tarval_and(tvb, tvd), tvd) == pn_Cmp_Eq) {
689
690         ops[i] = new_Const(mode, minus_one);
691         res = new_r_And(current_ir_graph, get_nodes_block(mux),
692             mux, child_mux, mode);
693         break;
694       }
695     }
696   }
697
698   /* recursively optimize nested muxes. */
699   set_irn_n(mux, 1, optimize_mux_chain(ops[0]));
700   set_irn_n(mux, 2, optimize_mux_chain(ops[1]));
701
702   return res;
703 }
704
705
706 /***********************************************************
707  * The If conversion itself.
708  ***********************************************************/
709
710 /** allow every Mux to be created. */
711 static int default_allow_mux(ir_node *sel, ir_node *false_res, ir_node *true_res) {
712   return 1;
713 }
714
715 /**
716  * Default options.
717  */
718 static const opt_if_conv_info_t default_info = {
719   MAX_DEPTH,
720   default_allow_mux
721 };
722
723 /** The debugging module. */
724 DEBUG_ONLY(static firm_dbg_module_t *dbg;)
725
726 /**
727  * A simple check for side effects upto an opcode of a ir node.
728  * @param irn The ir node to check,
729  * @return 1 if the opcode itself may produce side effects, 0 if not.
730  */
731 static INLINE int has_side_effects(const ir_node *irn)
732 {
733   ir_op *op = get_irn_op(irn);
734
735   if (op == op_Cmp)
736     return 0;
737
738   return !mode_is_datab(get_irn_mode(irn));
739 }
740
741 /**
742  * Possible failure reasons
743  */
744 enum failure_reason_t {
745   SUCCESS      = IF_RESULT_SUCCESS,
746   TO_DEEP      = IF_RESULT_TOO_DEEP,
747   SIDE_EFFECTS = IF_RESULT_SIDE_EFFECT,
748   PHI_FOUND    = IF_RESULT_SIDE_EFFECT_PHI,
749   DENIED       = IF_RESULT_DENIED
750 };
751
752 /**
753  * Decides, if a given expression and its subexpressions
754  * (to certain, also given extent) can be moved to a block.
755  *
756  * @param expr      The expression to examine.
757  * @param block     The block where the expression should go.
758  * @param depth     The current depth, passed recursively. Use 0 for
759  *                  non-recursive calls.
760  * @param info      The options for createing Mux nodes.
761  * examined.
762  *
763  * @return a failure reason
764  */
765 static int _can_move_to(ir_node *expr, ir_node *dest_block, int depth, const opt_if_conv_info_t *info)
766 {
767   int i, n;
768   int res = SUCCESS;
769   ir_node *expr_block = get_nodes_block(expr);
770
771   /*
772    * If we are forced to look too deep into the expression,
773    * treat it like it could not be moved.
774    */
775   if(depth >= info->max_depth) {
776     res = TO_DEEP;
777     goto end;
778   }
779
780   /*
781    * If the block of the expression dominates the specified
782    * destination block, it does not matter if the expression
783    * has side effects or anything else. It is executed on each
784    * path the destination block is reached.
785    */
786   if (block_dominates(expr_block, dest_block))
787     goto end;
788
789   /*
790    * We cannot move phis!
791    */
792   if (is_Phi(expr)) {
793     res = PHI_FOUND;
794     goto end;
795   }
796
797   /*
798    * This should be superfluous and could be converted into a assertion.
799    * The destination block _must_ dominate the block of the expression,
800    * else the expression could be used without its definition.
801    */
802   if (! block_dominates(dest_block, expr_block)) {
803     res = IF_RESULT_SIDE_EFFECT;
804     goto end;
805   }
806
807   /*
808    * Surely, if the expression does not have a data mode, it is not
809    * movable. Perhaps one should also test the floating property of
810    * the opcode/node.
811    */
812   if (has_side_effects(expr)) {
813     res = IF_RESULT_SIDE_EFFECT;
814     goto end;
815   }
816
817   /*
818    * If the node looks alright so far, look at its operands and
819    * check them out. If one of them cannot be moved, this one
820    * cannot be moved either.
821    */
822   for (i = 0, n = get_irn_arity(expr); i < n; ++i) {
823     ir_node *op = get_irn_n(expr, i);
824     int new_depth = is_Proj(op) ? depth : depth + 1;
825
826     res = _can_move_to(op, dest_block, new_depth, info);
827
828     if (res != SUCCESS)
829       goto end;
830   }
831
832 end:
833   DBG((dbg, LEVEL_3, "\t\t\tcan move to %n: %d\n", expr, res));
834
835   return res;
836 }
837
838 /**
839  * Convenience function for _can_move_to.
840  * Checks, if an expression can be moved to another block. The check can
841  * be limited to a expression depth meaning if we need to crawl in
842  * deeper into an expression than a given threshold to examine if
843  * it can be moved, the expression is rejected and the test returns
844  * false.
845  *
846  * @param expr       The expression to check for.
847  * @param dest_block The destination block you want @p expr to be.
848  * @param info       The options for createing Mux nodes.
849  *
850  * @return return a failure reason
851  */
852 static INLINE int can_move_to(ir_node *expr, ir_node *dest_block, const opt_if_conv_info_t *info)
853 {
854   return _can_move_to(expr, dest_block, 0, info);
855 }
856
857 /**
858  * move a DAG given by a root node expr into a new block
859  *
860  * @param expr       the root of a dag
861  * @param dest_block the destination block
862  */
863 static void move_to(ir_node *expr, ir_node *dest_block)
864 {
865   int i, n;
866   ir_node *expr_block = get_nodes_block(expr);
867
868   /*
869    * If we reached the dominator, we are done.
870    * We will never put code through the dominator
871    */
872   if (block_dominates(expr_block, dest_block))
873     return;
874
875   for (i = 0, n = get_irn_arity(expr); i < n; ++i)
876     move_to(get_irn_n(expr, i), dest_block);
877
878   set_nodes_block(expr, dest_block);
879 }
880
881 /**
882  * return the common dominator of two blocks
883  */
884 static INLINE ir_node *common_idom(ir_node *b1, ir_node *b2)
885 {
886   if(block_dominates(b1, b2))
887     return b1;
888   else if(block_dominates(b2, b1))
889     return b2;
890   else {
891     ir_node *p;
892
893     for (p = get_Block_idom(b1); !block_dominates(p, b2); p = get_Block_idom(p));
894     return p;
895   }
896 }
897
898 /**
899  * Information about a cond node.
900  */
901 typedef struct _cond_t {
902   ir_node *cond;          /**< The cond node. */
903   struct list_head list;  /**< List head which is used for queuing this cond
904                                into the cond bunch it belongs to. */
905   unsigned is_new : 1;
906   unsigned totally_covers : 1;
907   struct _cond_t *link;
908   long visited_nr;
909
910   /**
911    * Information about the both 'branches'
912    * (true and false), the cond creates.
913    */
914   struct {
915     int pos;         /**< Number of the predecessor of the
916                           phi block by which this branch is
917                           reached. It is -1, if this branch is
918                           only reached through another cond. */
919
920     struct _cond_t *masked_by; /**< If this cond's branch is only reached
921                                     through another cond, we store this
922                                     cond ir_node here. */
923   } cases[2];
924 } cond_t;
925
926 /**
927  * retrieve the conditional information from a Cond node
928  */
929 static INLINE cond_t *get_cond(ir_node *irn, set *cond_set)
930 {
931   cond_t templ;
932
933   templ.cond = irn;
934   return set_find(cond_set, &templ, sizeof(templ), HASH_PTR(templ.cond));
935 }
936
937
938 typedef void (cond_walker_t)(cond_t *cond, void *env);
939
940 static void _walk_conds(cond_t *cond, cond_walker_t *pre, cond_walker_t *post,
941       long visited_nr, void *env)
942 {
943   int i;
944
945   if(cond->visited_nr >= visited_nr)
946     return;
947
948   cond->visited_nr = visited_nr;
949
950   if(pre)
951     pre(cond, env);
952
953   for(i = 0; i < 2; ++i) {
954     cond_t *c = cond->cases[i].masked_by;
955
956     if(c)
957       _walk_conds(c, pre, post, visited_nr, env);
958   }
959
960   if(post)
961     post(cond, env);
962 }
963
964 static long cond_visited_nr = 0;
965
966 static void walk_conds(cond_t *cond, cond_walker_t *pre, cond_walker_t *post, void *env)
967 {
968   _walk_conds(cond, pre, post, ++cond_visited_nr, env);
969 }
970
971 static void link_conds(cond_t *cond, void *env)
972 {
973   cond_t **ptr = (cond_t **) env;
974
975   cond->link = *ptr;
976   *ptr = cond;
977 }
978
979 /**
980  * Compare two conds for use in a firm set.
981  * Two cond_t's are equal, if they designate the same cond node.
982  * @param a A cond_t.
983  * @param b Another one.
984  * @param size Not used.
985  * @return 0 (!) if they are equal, != 0 otherwise.
986  */
987 static int cond_cmp(const void *a, const void *b, size_t size)
988 {
989   const cond_t *x = a;
990   const cond_t *y = b;
991   return x->cond != y->cond;
992 }
993
994 /**
995  * Information about conds which can be made to muxes.
996  * Instances of this struct are attached to the link field of
997  * blocks in which phis are located.
998  */
999 typedef struct _cond_info_t {
1000   struct list_head list;      /**< Used to list all of these structs per class. */
1001
1002   struct list_head roots;     /**< A list of non-depending Conds. Two Conds are
1003                                 independent, if it's not possible not reach one from the
1004                                 other (all Conds in this list have to dominate the
1005                                 block this struct is attached to). */
1006
1007   ir_node *first_phi;         /**< The first phi node this cond info was made for. */
1008   set *cond_set;              /**< A set of all dominating reachable Conds. */
1009 } cond_info_t;
1010
1011 /**
1012  * @see find_conds.
1013  */
1014 static void _find_conds(ir_node *irn, unsigned long visited_nr,
1015     ir_node *dominator, cond_t *masked_by, int pos, int depth, cond_info_t *ci)
1016 {
1017   ir_node *block;
1018   int saw_select_cond = 0;
1019
1020   block = get_nodes_block(irn);
1021
1022   /*
1023    * Only check this block if it is dominated by the specified
1024    * dominator or it has not been visited yet.
1025    */
1026   if (block_dominates(dominator, block) && get_Block_block_visited(block) < visited_nr) {
1027     cond_t *res = masked_by;
1028     int i, n;
1029
1030     /* check, if we're on a ProjX
1031      *
1032      * Further, the ProjX/Cond block must dominate the base block
1033      * (the block with the phi in it), otherwise, the Cond
1034      * is not affecting the phi so that a mux can be inserted.
1035      */
1036     if(is_Proj(irn) && get_irn_mode(irn) == mode_X) {
1037
1038       int proj = get_Proj_proj(irn);
1039       ir_node *cond = get_Proj_pred(irn);
1040
1041       /* true, if the mode is a mode_b cond _NO_ switch cond */
1042       int is_modeb_cond = get_irn_opcode(cond) == iro_Cond
1043         && get_irn_mode(get_Cond_selector(cond)) == mode_b;
1044
1045       saw_select_cond = !is_modeb_cond;
1046
1047       /* Check, if the pred of the proj is a Cond
1048        * with a Projb as selector.
1049        */
1050       if(is_modeb_cond) {
1051         cond_t c;
1052
1053         memset(&c, 0, sizeof(c));
1054         c.cond = cond;
1055         c.is_new = 1;
1056         c.cases[0].pos = -1;
1057         c.cases[1].pos = -1;
1058
1059         /* get or insert the cond info into the set. */
1060         res = set_insert(ci->cond_set, &c, sizeof(c), HASH_PTR(cond));
1061
1062         /*
1063          * If this cond is already masked by the masked_by cond
1064          * return immediately, since we don't have anything to add.
1065          */
1066         if(masked_by && res->cases[proj].masked_by == masked_by)
1067           return;
1068
1069         if(res->is_new) {
1070           res->is_new = 0;
1071           list_add(&res->list, &ci->roots);
1072         }
1073
1074         /*
1075          * Set masked by (either NULL or another cond node.
1076          * If this cond is truly masked by another one, set
1077          * the position of the actually investigated branch
1078          * to -1. Since the cond is masked by another one,
1079          * there could be more ways from the start block
1080          * to this branch, so we choose -1.
1081          */
1082         res->cases[proj].masked_by = masked_by;
1083
1084         if(!masked_by)
1085           res->cases[proj].pos = pos;
1086
1087         /*
1088          * Since the masked_by nodes masks a cond, remove it from the
1089          * root list of the conf trees.
1090          */
1091         else {
1092           assert(res->cases[proj].pos < 0);
1093           list_del_init(&masked_by->list);
1094         }
1095
1096         DBG((dbg, LEVEL_2, "%n (%s branch) "
1097               "for pos %d in block %n reached by %n\n",
1098               cond, proj ? "true" : "false", pos,
1099               block, masked_by ? masked_by->cond : NULL));
1100       }
1101     }
1102
1103     if(get_Block_block_visited(block) < visited_nr && !saw_select_cond) {
1104
1105       set_Block_block_visited(block, visited_nr);
1106
1107       /* Search recursively from this cond. */
1108       for(i = 0, n = get_irn_arity(block); i < n; ++i) {
1109         ir_node *pred = get_irn_n(block, i);
1110
1111         /*
1112          * If the depth is 0 (the first recursion), we set the pos to
1113          * the current viewed predecessor, else we adopt the position
1114          * as given by the caller. We also increase the depth for the
1115          * recursively called functions.
1116          */
1117         _find_conds(pred, visited_nr, dominator, res, pos, depth + (res != masked_by), ci);
1118       }
1119     }
1120   }
1121 }
1122
1123
1124 /**
1125  * A convenience function for _find_conds.
1126  * It sets some parameters needed for recursion to appropriate start
1127  * values. Always use this function.
1128  *
1129  * @param irn   The node to start looking for Conds from. This might
1130  *              be the phi node we are investigating.
1131  * @param conds The set to record the found Conds in.
1132  */
1133 static INLINE void find_conds(ir_node *irn, cond_info_t *ci)
1134 {
1135   int i, n;
1136   unsigned long visited_nr;
1137   ir_node *block = get_nodes_block(irn);
1138   ir_node *dom = get_Block_idom(block);
1139
1140   for(i = 0, n = get_irn_arity(block); i < n; ++i) {
1141     ir_node *pred = get_irn_n(block, i);
1142
1143     inc_irg_block_visited(current_ir_graph);
1144     visited_nr = get_irg_block_visited(current_ir_graph);
1145     set_Block_block_visited(block, visited_nr);
1146
1147     DBG((dbg, LEVEL_2, "find conds at pred %d (%n) and idom %n\n", i, pred, dom));
1148     _find_conds(pred, visited_nr, dom, NULL, i, 0, ci);
1149   }
1150 }
1151
1152 /**
1153  * Make the mux for a given cond.
1154  *
1155  * @param phi       The phi node which shall be replaced by a mux.
1156  * @param dom       The block where the muxes shall be placed.
1157  * @param cond      The cond information.
1158  * @param info      The options for createing Mux nodes.
1159  * @return The mux node made for this cond.
1160  */
1161 static ir_node *make_mux_on_demand(ir_node *phi, ir_node *dom, cond_t *cond,
1162     const opt_if_conv_info_t *info, ir_node **mux, bitset_t *positions,
1163     int *muxes_made, long visited_nr)
1164 {
1165   int i, can_move[2];
1166   ir_node *projb = get_Cond_selector(cond->cond);
1167   ir_node *bl = get_nodes_block(cond->cond);
1168   ir_node *operands[2];
1169   int set[2];
1170
1171   cond->visited_nr = visited_nr;
1172   DBG((dbg, LEVEL_2, "%n\n", cond->cond));
1173   for(i = 0; i < 2; ++i) {
1174     cond_t *masked_by = cond->cases[i].masked_by;
1175     int pos = cond->cases[i].pos;
1176
1177     operands[i] = NULL;
1178     set[i] = -1;
1179
1180     /*
1181      * If this Cond branch is masked by another cond, make the mux
1182      * for that Cond first, since the Mux for this cond takes
1183      * it as an operand.
1184      */
1185     if(masked_by) {
1186       assert(pos < 0);
1187       DBG((dbg, LEVEL_2, "\tmasked by: %n\n", masked_by->cond));
1188       if(masked_by->visited_nr < visited_nr)
1189         operands[i] = make_mux_on_demand(phi, dom, masked_by, info, mux, positions, muxes_made, visited_nr);
1190     }
1191
1192     /*
1193      * If this cond branch is not masked by another cond, take
1194      * the corresponding phi operand as an operand to the mux.
1195      */
1196     else if(pos >= 0) {
1197       operands[i] = get_irn_n(phi, pos);
1198       set[i] = pos;
1199     }
1200   }
1201
1202   /*
1203    * Move the operands to the dominator block if the cond
1204    * made sense. Some Conds found are not suitable for making a mux
1205    * out of them, since one of their branches cannot be reached from
1206    * the phi block. In that case we do not make a mux and return NULL.
1207    */
1208   if(operands[0] && operands[1]) {
1209     if (operands[0] == operands[1]) {
1210       /* there is no gain in using mux in this case, as
1211          it will be optimized away. We will NOT move the
1212          content of the blocks either
1213         */
1214       for (i = 0; i < 2; ++i)
1215         if(set[i] >= 0)
1216           bitset_set(positions, set[i]);
1217
1218       *mux = operands[0];
1219       return *mux;
1220     }
1221
1222     can_move[0] = can_move_to(operands[0], bl, info);
1223     can_move[1] = can_move_to(operands[1], bl, info);
1224
1225     if (can_move[0] == SUCCESS && can_move[1] == SUCCESS) {
1226       if (info->allow_mux(projb, operands[0], operands[1])) {
1227         move_to(operands[0], bl);
1228         move_to(operands[1], bl);
1229
1230         /* Make the mux. */
1231         *mux = new_r_Mux(current_ir_graph, bl, projb,
1232             operands[0], operands[1], get_irn_mode(operands[0]));
1233
1234         *muxes_made += 1;
1235
1236         DBG((dbg, LEVEL_2, "\t%n(%n, %n, %n)[%d, %d]\n",
1237               *mux, projb, operands[0], operands[1], set[0], set[1]));
1238
1239         for(i = 0; i < 2; ++i)
1240           if(set[i] >= 0) {
1241             bitset_set(positions, set[i]);
1242
1243             /* we have done one */
1244             hook_if_conversion(current_ir_graph, phi, set[i], *mux, IF_RESULT_SUCCESS);
1245           }
1246       }
1247       else {
1248         hook_if_conversion(current_ir_graph, phi, set[i], *mux, IF_RESULT_DENIED);
1249       }
1250     }
1251     else {
1252       if(can_move[0] != SUCCESS)
1253         hook_if_conversion(current_ir_graph, phi, set[0], NULL, can_move[0]);
1254       if(can_move[1] != SUCCESS)
1255         hook_if_conversion(current_ir_graph, phi, set[1], NULL, can_move[1]);
1256     }
1257   }
1258   else {
1259     if(operands[0])
1260       hook_if_conversion(current_ir_graph, phi, set[0], NULL, IF_RESULT_BAD_CF);
1261     if(operands[1])
1262       hook_if_conversion(current_ir_graph, phi, set[1], NULL, IF_RESULT_BAD_CF);
1263   }
1264
1265   return *mux;
1266 }
1267
1268 typedef struct _phi_info_t {
1269   struct list_head list;
1270   cond_info_t *cond_info;
1271   ir_node *irn;
1272 } phi_info_t;
1273
1274
1275 /**
1276  * Examine a phi node if it can be replaced by some muxes.
1277  * @param irn A phi node.
1278  * @param info Parameters for the if conversion algorithm.
1279  */
1280 static int check_out_phi(phi_info_t *phi_info, const opt_if_conv_info_t *info)
1281 {
1282   ir_node *irn = phi_info->irn;
1283   ir_node *block, *nw;
1284   cond_info_t *cond_info = phi_info->cond_info;
1285   cond_t *cond;
1286   int i, arity;
1287   int muxes_made = 0;
1288   bitset_t *positions;
1289
1290   block = get_nodes_block(irn);
1291   arity = get_irn_arity(irn);
1292   positions = bitset_alloca(arity);
1293
1294   assert(is_Phi(irn));
1295   assert(get_irn_arity(irn) == get_irn_arity(block));
1296   assert(arity > 0);
1297
1298   DBG((dbg, LEVEL_2, "phi candidate: %n\n", irn));
1299
1300   list_for_each_entry(cond_t, cond, &cond_info->roots, list) {
1301     ir_node *cidom = block;
1302     ir_node *mux = NULL;
1303     cond_t *p, *head = NULL;
1304     long pos;
1305
1306     bitset_clear_all(positions);
1307
1308     DBG((dbg, LEVEL_2, "\tcond root: %n\n", cond->cond));
1309     /*
1310      * Link all conds which are in the subtree of
1311      * the current cond in the list together.
1312      */
1313     walk_conds(cond, link_conds, NULL, &head);
1314
1315     cidom = block;
1316     for(p = head; p; p = p->link) {
1317       for(i = 0; i < 2; ++i) {
1318         int pos = p->cases[i].pos;
1319         if(pos != -1)
1320           cidom = common_idom(cidom, get_nodes_block(get_irn_n(block, pos)));
1321       }
1322     }
1323
1324     DBG((dbg, LEVEL_2, "\tcommon idom: %n\n", cidom));
1325     make_mux_on_demand(irn, cidom, cond, info, &mux, positions, &muxes_made, ++cond_visited_nr);
1326
1327     if(mux) {
1328       bitset_foreach(positions, pos)
1329         set_irn_n(irn, (int) pos, mux);
1330     }
1331   }
1332
1333   /*
1334    * optimize the phi away. This can anable further runs of this
1335    * function. Look at _can_move. phis cannot be moved there.
1336    */
1337   nw = optimize_in_place_2(irn);
1338   if(nw != irn)
1339     exchange(irn, nw);
1340
1341   return muxes_made;
1342 }
1343
1344 typedef struct _cond_walk_info_t {
1345   struct obstack *obst;
1346   struct list_head cond_info_head;
1347   struct list_head phi_head;
1348 } cond_walk_info_t;
1349
1350
1351 static void annotate_cond_info_pre(ir_node *irn, void *data)
1352 {
1353   set_irn_link(irn, NULL);
1354 }
1355
1356 static void annotate_cond_info_post(ir_node *irn, void *data)
1357 {
1358   cond_walk_info_t *cwi = data;
1359
1360   /*
1361    * Check, if the node is a phi
1362    * we then compute a set of conds which are reachable from this
1363    * phi's block up to its dominator.
1364    * The set is attached to the blocks link field.
1365    */
1366   if(is_Phi(irn) && mode_is_datab(get_irn_mode(irn))) {
1367     ir_node *block = get_nodes_block(irn);
1368
1369     cond_info_t *ci = get_irn_link(block);
1370
1371     /* If the set is not yet computed, do it now. */
1372     if(!ci) {
1373       ci = obstack_alloc(cwi->obst, sizeof(*ci));
1374       ci->cond_set = new_set(cond_cmp, log2_ceil(get_irn_arity(block)));
1375       ci->first_phi = irn;
1376
1377       INIT_LIST_HEAD(&ci->roots);
1378       INIT_LIST_HEAD(&ci->list);
1379
1380       /*
1381        * Add this cond info to the list of all cond infos
1382        * in this graph. This is just done to xfree the
1383        * set easier afterwards (we save an irg_walk_graph).
1384        */
1385       list_add(&cwi->cond_info_head, &ci->list);
1386
1387       DBG((dbg, LEVEL_2, "searching conds at %n\n", irn));
1388
1389       /*
1390        * Fill the set with conds we find on the way from
1391        * the block to its dominator.
1392        */
1393       find_conds(irn, ci);
1394
1395       /*
1396        * If there where no suitable conds, delete the set
1397        * immediately and reset the set pointer to NULL
1398        */
1399       if(set_count(ci->cond_set) == 0) {
1400         del_set(ci->cond_set);
1401         list_del(&ci->list);
1402         obstack_free(cwi->obst, ci);
1403         ci = NULL;
1404       }
1405     }
1406
1407     else
1408       DBG((dbg, LEVEL_2, "conds already computed for %n (look at %n)\n", irn, ci->first_phi));
1409
1410     set_irn_link(block, ci);
1411
1412     if(ci) {
1413       phi_info_t *pi = obstack_alloc(cwi->obst, sizeof(*pi));
1414       pi->irn = irn;
1415       pi->cond_info = ci;
1416       INIT_LIST_HEAD(&pi->list);
1417       list_add(&pi->list, &cwi->phi_head);
1418     }
1419
1420   }
1421 }
1422
1423 static void dump_conds(cond_t *cond, void *env)
1424 {
1425   int i;
1426   FILE *f = env;
1427
1428   ir_fprintf(f, "node:{title:\"n%p\" label:\"%n(%d, %d)\n%n\"}\n",
1429       cond, cond->cond, cond->cases[0].pos, cond->cases[1].pos,
1430       get_nodes_block(cond->cond));
1431
1432   for(i = 0; i < 2; ++i)
1433     if(cond->cases[i].masked_by)
1434       ir_fprintf(f, "edge:{sourcename:\"n%p\" targetname:\"n%p\" label:\"%d\"}\n",
1435           cond, cond->cases[i].masked_by, i);
1436 }
1437
1438 static void vcg_dump_conds(ir_graph *irg, cond_walk_info_t *cwi)
1439 {
1440   char buf[512];
1441   FILE *f;
1442
1443   snprintf(buf, sizeof(buf), "%s-conds.vcg", get_entity_name(get_irg_entity(irg)));
1444
1445   if((f = fopen(buf, "wt")) != NULL) {
1446     cond_info_t *ci;
1447     phi_info_t *phi;
1448     cond_t *cond;
1449
1450     ir_fprintf(f, "graph:{\ndisplay_edge_labels:yes\n");
1451     list_for_each_entry(cond_info_t, ci, &cwi->cond_info_head, list) {
1452       ir_fprintf(f, "node:{title:\"n%p\" label:\"cond info\"}\n", ci);
1453       list_for_each_entry(cond_t, cond, &ci->roots, list) {
1454         walk_conds(cond, NULL, dump_conds, f);
1455         ir_fprintf(f, "edge:{sourcename:\"n%p\" targetname:\"n%p\"}\n", ci, cond);
1456       }
1457     }
1458
1459     list_for_each_entry(phi_info_t, phi, &cwi->phi_head, list) {
1460       ir_fprintf(f, "node:{title:\"n%p\" label:\"%n\n%n\"}\n",
1461           phi->irn, phi->irn, get_nodes_block(phi->irn));
1462       ir_fprintf(f, "edge:{sourcename:\"n%p\" targetname:\"n%p\"}\n", phi->irn, phi->cond_info);
1463     }
1464     fprintf(f, "}\n");
1465   }
1466 }
1467
1468 void opt_if_conv(ir_graph *irg, const opt_if_conv_info_t *params)
1469 {
1470   int muxes_made = 0;
1471   struct obstack obst;
1472   phi_info_t *phi_info;
1473   cond_info_t *cond_info;
1474   cond_walk_info_t cwi;
1475
1476   opt_if_conv_info_t p;
1477
1478   if(!get_opt_if_conversion())
1479     return;
1480
1481   /* get the parameters */
1482   if (params)
1483     memcpy(&p, params, sizeof(p));
1484   else
1485     memcpy(&p, &default_info, sizeof(p));
1486
1487   if (! p.allow_mux)
1488     p.allow_mux = default_info.allow_mux;
1489
1490   obstack_init(&obst);
1491
1492   cwi.obst = &obst;
1493   INIT_LIST_HEAD(&cwi.cond_info_head);
1494   INIT_LIST_HEAD(&cwi.phi_head);
1495
1496   /* Init the debug stuff. */
1497   FIRM_DBG_REGISTER(dbg, "firm.opt.ifconv");
1498 #if 0
1499   firm_dbg_set_mask(dbg, LEVEL_1|LEVEL_2|LEVEL_3);
1500 #endif
1501
1502   /* if-conversion works better with normalized returns */
1503   normalize_one_return(irg);
1504
1505   /* Ensure, that the dominators are computed. */
1506   assure_doms(irg);
1507
1508   DBG((dbg, LEVEL_1, "if conversion for irg %s(%p)\n",
1509         get_entity_name(get_irg_entity(irg)), irg));
1510
1511   /*
1512    * Collect information about the conds pu the phis on an obstack.
1513    * It is important that phi nodes which are 'higher' (with a
1514    * lower dfs pre order) are in front of the obstack. Since they are
1515    * possibly turned in to muxes this can enable the optimization
1516    * of 'lower' ones.
1517    */
1518   irg_walk_graph(irg, annotate_cond_info_pre, annotate_cond_info_post, &cwi);
1519
1520 #if 0
1521   vcg_dump_conds(irg, &cwi);
1522 #endif
1523
1524   /* Process each suitable phi found. */
1525   list_for_each_entry(phi_info_t, phi_info, &cwi.phi_head, list) {
1526     DBG((dbg, LEVEL_2, "phi node %n\n", phi_info->irn));
1527     muxes_made += check_out_phi(phi_info, &p);
1528   }
1529
1530   list_for_each_entry(cond_info_t, cond_info, &cwi.cond_info_head, list) {
1531     del_set(cond_info->cond_set);
1532   }
1533
1534   DBG((dbg, LEVEL_1, "muxes made: %d\n", muxes_made));
1535
1536   obstack_free(&obst, NULL);
1537
1538         dump_ir_block_graph(irg, "_ifconv_hack");
1539 }
1540
1541 #endif