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