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