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