add config.h to allow Win32 compile
[libfirm] / ir / opt / condeval.c
1 #ifdef HAVE_CONFIG_H
2 #include "config.h"
3 #endif
4
5 #ifdef HAVE_ALLOCA_H
6 #include <alloca.h>
7 #endif
8 #ifdef HAVE_MALLOC_H
9 #include <malloc.h>
10 #endif
11
12 #include <assert.h>
13 #include "array.h"
14 #include "debug.h"
15 #include "ircons.h"
16 #include "irgwalk.h"
17 #include "irnode.h"
18 #include "tv.h"
19
20 DEBUG_ONLY(static firm_dbg_module_t *dbg);
21
22 /**
23  * Block-walker:
24  */
25 static void cond_eval(ir_node* block, void* env)
26 {
27         int n_block = get_Block_n_cfgpreds(block);
28         int i;
29
30         for (i = 0; i < n_block; i++) {
31                 ir_node* pred;
32                 ir_node* projx;
33                 ir_node* cond;
34                 ir_node* cmp;
35                 ir_node* left;
36                 ir_node* right;
37                 ir_node* cond_block;
38                 ir_node* phi;
39                 ir_node* cnst;
40                 pn_Cmp pnc;
41                 int n_phi;
42                 int j;
43
44                 pred = get_Block_cfgpred(block, i);
45                 if (!is_Proj(pred)) continue;
46                 projx = pred;
47
48                 pred = get_Proj_pred(projx);
49                 if (!is_Cond(pred)) continue;
50                 cond = pred;
51
52                 pred = get_Cond_selector(cond);
53                 assert(is_Proj(pred));
54                 // TODO handle switches
55                 if (get_irn_mode(pred) != mode_b) continue;
56                 pnc = get_Proj_proj(pred);
57
58                 cmp = get_Proj_pred(pred);
59                 assert(is_Cmp(cmp));
60
61                 left  = get_Cmp_left(cmp);
62                 right = get_Cmp_right(cmp);
63
64                 // TODO handle Const-Const and Phi-Phi
65                 if (is_Phi(left)) {
66                         if (!is_Const(right)) continue;
67                         phi  = left;
68                         cnst = right;
69                 } else if (is_Phi(right)) {
70                         if (!is_Const(left)) continue;
71                         phi  = right;
72                         cnst = left;
73                         pnc = get_inversed_pnc(pnc);
74                 } else {
75                         continue;
76                 }
77
78                 cond_block = get_nodes_block(cond);
79                 if (get_nodes_block(phi) != cond_block) continue;
80
81                 if (get_Proj_proj(projx) == 0) pnc = get_negated_pnc(pnc, get_irn_mode(cnst));
82
83                 n_phi = get_Phi_n_preds(phi);
84                 for (j = 0; j < n_phi; j++) {
85                         tarval* tv_phi;
86                         tarval* tv_cnst;
87                         ir_node** ins;
88                         int k;
89                         pn_Cmp cmp_val;
90
91                         pred = get_Phi_pred(phi, j);
92                         // TODO handle Phi cascades
93                         if (!is_Const(pred)) continue;
94
95                         tv_phi  = get_Const_tarval(pred);
96                         tv_cnst = get_Const_tarval(cnst);
97
98                         cmp_val = tarval_cmp(tv_phi, tv_cnst);
99                         if (cmp_val == pn_Cmp_False)
100                                 continue;
101                         if ((cmp_val & pnc) != cmp_val)
102                                 continue;
103
104                         DB((
105                                 dbg, LEVEL_1,
106                                 "> Found condition evaluation candidate %+F->%+F predecessor %d\n",
107                                 block, cond_block, j
108                         ));
109
110 #if 0 // TODO repair data flow and dominance
111                         NEW_ARR_A(ir_node*, ins, n_block + 1);
112                         for (k = 0; k < n_block; k++) ins[k] = get_Block_cfgpred(block, k);
113                         ins[k] = get_Block_cfgpred(cond_block, j);
114                         set_irn_in(block, n_block + 1, ins);
115
116                         set_Block_cfgpred(cond_block, j, new_Bad());
117                         set_Phi_pred(phi, j, new_Bad());
118 #endif
119                 }
120         }
121 }
122
123
124 void opt_cond_eval(ir_graph* irg)
125 {
126         FIRM_DBG_REGISTER(dbg, "firm.opt.condeval");
127     firm_dbg_set_mask(dbg, SET_LEVEL_5);
128
129         DB((dbg, LEVEL_1, "===> Performing condition evaluation on %+F\n", irg));
130
131         irg_block_walk_graph(irg, NULL, cond_eval, NULL);
132 }