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