convert bitfield initializer tarvals before using them
[libfirm] / ir / arch / archop.c
1 /*
2  * Copyright (C) 1995-2008 University of Karlsruhe.  All right reserved.
3  *
4  * This file is part of libFirm.
5  *
6  * This file may be distributed and/or modified under the terms of the
7  * GNU General Public License version 2 as published by the Free Software
8  * Foundation and appearing in the file LICENSE.GPL included in the
9  * packaging of this file.
10  *
11  * Licensees holding valid libFirm Professional Edition licenses may use
12  * this file in accordance with the libFirm Commercial License.
13  * Agreement provided with the Software.
14  *
15  * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
16  * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
17  * PURPOSE.
18  */
19
20 /**
21  * @file
22  * @brief     architecture dependent IR operations
23  * @version   $Id$
24  */
25 #ifdef HAVE_CONFIG_H
26 #include "config.h"
27 #endif
28
29 #ifdef HAVE_STRING_H
30 #include <string.h>
31 #endif
32
33 #include "irprog_t.h"
34 #include "irgraph_t.h"
35 #include "irnode_t.h"
36 #include "irmode_t.h"
37 #include "ircons_t.h"
38 #include "iropt_t.h"
39 #include "firm_common_t.h"
40 #include "irvrfy_t.h"
41 #include "iropt_dbg.h"
42 #include "archop.h"
43 #include "irop.h"
44 #include "error.h"
45
46 /* when we need verifying */
47 #ifdef NDEBUG
48 # define IRN_VRFY_IRG(res, irg)
49 #else
50 # define IRN_VRFY_IRG(res, irg)  irn_vrfy_irg(res, irg)
51 #endif
52
53 /** current settings */
54 static arch_ops_info settings;
55
56 /** default settings */
57 static const arch_ops_info default_settings = {
58         ARCH_OPS_NONE,
59         0
60 };
61
62 /*
63  * construct a Min: Min(a,b) = a < b ? a : b
64  */
65 ir_node *
66 new_rd_Min(dbg_info *db, ir_graph *irg, ir_node *block,
67            ir_node *op1, ir_node *op2, ir_mode *mode)
68 {
69         ir_node *in[2];
70         ir_node *res;
71
72         if (! op_Min) {
73                 panic("cannot create Min node, not allowed");
74         }
75
76         in[0] = op1;
77         in[1] = op2;
78         res = new_ir_node(db, irg, block, op_Min, mode, 2, in);
79         res = optimize_node(res);
80         IRN_VRFY_IRG(res, irg);
81         return res;
82 }
83
84 /*
85  * construct a Max: Max(a,b) = a > b ? a : b
86  */
87 ir_node *
88 new_rd_Max(dbg_info *db, ir_graph *irg, ir_node *block,
89            ir_node *op1, ir_node *op2, ir_mode *mode)
90 {
91         ir_node *in[2];
92         ir_node *res;
93
94         if (! op_Max) {
95                 panic("cannot create Max node, not allowed");
96         }
97
98         in[0] = op1;
99         in[1] = op2;
100         res = new_ir_node(db, irg, block, op_Max, mode, 2, in);
101         res = optimize_node(res);
102         IRN_VRFY_IRG(res, irg);
103         return res;
104 }
105
106 ir_node *
107 new_r_Min(ir_graph *irg, ir_node *block,
108           ir_node *op1, ir_node *op2, ir_mode *mode) {
109         return new_rd_Min(NULL, irg, block, op1, op2, mode);
110 }
111
112 ir_node *
113 new_r_Max(ir_graph *irg, ir_node *block,
114        ir_node *op1, ir_node *op2, ir_mode *mode) {
115   return new_rd_Max(NULL, irg, block, op1, op2, mode);
116 }
117
118 ir_node *
119 new_d_Min(dbg_info *db, ir_node *op1, ir_node *op2, ir_mode *mode) {
120         return new_rd_Min(db, current_ir_graph, current_ir_graph->current_block,
121                           op1, op2, mode);
122 }
123
124 ir_node *
125 new_d_Max(dbg_info *db, ir_node *op1, ir_node *op2, ir_mode *mode) {
126         return new_rd_Max(db, current_ir_graph, current_ir_graph->current_block,
127                           op1, op2, mode);
128 }
129
130 ir_node *
131 new_Min(ir_node *op1, ir_node *op2, ir_mode *mode) {
132         return new_d_Min(NULL, op1, op2, mode);
133 }
134
135 ir_node *
136 new_Max(ir_node *op1, ir_node *op2, ir_mode *mode) {
137   return new_d_Max(NULL, op1, op2, mode);
138 }
139
140 /* optimizations */
141
142 /**
143  * return the value of a Min
144  */
145 static tarval *computed_value_Min(const ir_node *n) {
146         ir_node *a = get_binop_left(n);
147         ir_node *b = get_binop_right(n);
148
149         tarval *ta = value_of(a);
150         tarval *tb = value_of(b);
151
152         if ((ta != tarval_bad) && (tb != tarval_bad) && (get_irn_mode(a) == get_irn_mode(b))) {
153                 pn_Cmp res = tarval_cmp(ta, tb);
154
155                 /* beware: there might be Unordered tarvals here, in that
156                 * case let the backend decide, do NOT optimize */
157                 if (res == pn_Cmp_Lt)
158                         return ta;
159                 if (res == pn_Cmp_Gt || res == pn_Cmp_Eq)
160                         return tb;
161         }
162         return tarval_bad;
163 }
164
165 /**
166  * return the value of a Max
167  */
168 static tarval *computed_value_Max(const ir_node *n) {
169         ir_node *a      = get_binop_left(n);
170         ir_node *b      = get_binop_right(n);
171
172         tarval *tb = value_of(b);
173         tarval *ta = value_of(a);
174
175         if ((ta != tarval_bad) && (tb != tarval_bad) && (get_irn_mode(a) == get_irn_mode(b))) {
176                 pn_Cmp res = tarval_cmp(ta, tb);
177
178                 /* beware: there might be Unordered tarvals here, in that
179                  * case let the backend decide, do NOT optimize */
180                 if (res == pn_Cmp_Gt)
181                         return ta;
182                 if (res == pn_Cmp_Lt || res == pn_Cmp_Eq)
183                         return tb;
184         }
185         return tarval_bad;
186 }
187
188 /**
189  * Returns an equivalent node for a Min/Max node.
190  * We do not allow Exceptions in our Min/Max, so there will be always
191  * an result.
192  * The problem is Min(NaN, NaN) == NaN ???.
193  */
194 static ir_node *equivalent_node_MinMax(ir_node *n)
195 {
196         ir_node *a, *b;
197         ir_mode *mode;
198         tarval *tv;
199
200         if (settings.minmax_handle_NaN == 0 && mode_is_float(get_irn_mode(n)))
201                 return n;
202
203         a = get_binop_left(n);
204         b = get_binop_right(n);
205
206         if (a == b) {
207                 DBG_OPT_ALGSIM0(n, a, FS_OPT_MIN_MAX_EQ);
208                 return a;
209         }
210
211         mode = get_irn_mode(n);
212         tv   = n->op == op_Max ? get_mode_min(mode) : get_mode_max(mode);
213
214         if (value_of(b) == tv) {
215                 DBG_OPT_ALGSIM0(n, a, FS_OPT_MIN_MAX_EQ);
216                 return a;
217         }
218         if (value_of(a) == tv) {
219                 DBG_OPT_ALGSIM0(n, b, FS_OPT_MIN_MAX_EQ);
220                 return b;
221         }
222
223         return n;
224 }
225
226 #define equivalent_node_Min equivalent_node_MinMax
227 #define equivalent_node_Max equivalent_node_MinMax
228
229 /*
230  * Create Min and Max from Mux nodes
231  */
232 ir_node *arch_transform_node_Mux(ir_node *n)
233 {
234         if (settings.enabled_ops & ARCH_OPS_MINMAX) {
235                 ir_node *oldn = n, *cmp, *proj = get_Mux_sel(n);
236                 long proj_nr;
237
238                 if (get_irn_op(proj) != op_Proj)
239                         return n;
240
241                 cmp = get_Proj_pred(proj);
242                 if (is_Cmp(cmp)) {
243                         ir_node *a = get_Cmp_left(cmp);
244                         ir_node *b = get_Cmp_right(cmp);
245                         ir_node *t = get_Mux_true(n);
246                         ir_node *f = get_Mux_false(n);
247
248                         proj_nr = get_Proj_proj(proj);
249
250                         if (proj_nr == pn_Cmp_Lt || proj_nr == pn_Cmp_Le) {
251                                 if (a == t && b == f) {
252                                         /* a </<= b ? a : b  ==>  Min(a,b) */
253                                         n = new_rd_Min(get_irn_dbg_info(n),
254                                                 current_ir_graph,
255                                                 get_nodes_block(n),
256                                                 a, b,
257                                                 get_irn_mode(n));
258
259                                         DBG_OPT_ALGSIM1(oldn, cmp, proj, n, FS_OPT_MUX_TO_MIN);
260                                         return n;
261                                 }
262                                 else if (a == f && b == t) {
263                                         /* a </<= b ? b : a  ==>  Max(a,b) */
264                                         n = new_rd_Max(get_irn_dbg_info(n),
265                                                 current_ir_graph,
266                                                 get_nodes_block(n),
267                                                 a, b,
268                                                 get_irn_mode(n));
269
270                                         DBG_OPT_ALGSIM1(oldn, cmp, proj, n, FS_OPT_MUX_TO_MAX);
271                                         return n;
272                                 }
273                         }
274                         else if (proj_nr == pn_Cmp_Gt || proj_nr == pn_Cmp_Ge) {
275                                 if (a == t && b == f) {
276                                         /* a >/>= b ? a : b  ==>  Max(a,b) */
277                                         n = new_rd_Max(get_irn_dbg_info(n),
278                                                 current_ir_graph,
279                                                 get_nodes_block(n),
280                                                 a, b,
281                                                 get_irn_mode(n));
282
283                                         DBG_OPT_ALGSIM1(oldn, cmp, proj, n, FS_OPT_MUX_TO_MAX);
284                                         return n;
285                                 }
286                                 else if (a == f && b == t) {
287                                         /* a >/>= b ? b : a  ==>  Min(a,b) */
288                                         n = new_rd_Min(get_irn_dbg_info(n),
289                                                 current_ir_graph,
290                                                 get_nodes_block(n),
291                                                 a, b,
292                                                 get_irn_mode(n));
293
294                                         DBG_OPT_ALGSIM1(oldn, cmp, proj, n, FS_OPT_MUX_TO_MIN);
295                                         return n;
296                                 }
297                         }
298                 }
299         }
300         return n;
301 }
302
303 /**
304  * verify a MinMax node
305  */
306 static int verify_node_MinMax(ir_node *n, ir_graph *irg) {
307         ir_mode *mymode  = get_irn_mode(n);
308         ir_mode *op1mode = get_irn_mode(get_binop_left(n));
309         ir_mode *op2mode = get_irn_mode(get_binop_right(n));
310         (void) irg;
311
312         ASSERT_AND_RET(
313                 /* MinMax: BB x numP x numP --> numP */
314                 op1mode == mymode &&
315                 op2mode == mymode &&
316                 mode_is_data(mymode),
317                 "Min or Max node", 0
318                 );
319         return 1;
320 }
321
322 /*
323  * initialize the ops.
324  */
325 void firm_archops_init(const arch_ops_info *info)
326 {
327         ir_op_ops ops;
328
329         if (! info)
330                 info = &default_settings;
331
332         memcpy(&settings, info, sizeof(settings));
333
334         if (info->enabled_ops & ARCH_OPS_MINMAX) {
335                 memset(&ops, 0, sizeof(ops));
336
337                 op_Min->ops.computed_value  = computed_value_Min;
338                 op_Min->ops.equivalent_node = equivalent_node_Min;
339                 op_Min->ops.verify_node     = verify_node_MinMax;
340
341                 op_Max->ops.computed_value  = computed_value_Max;
342                 op_Max->ops.equivalent_node = equivalent_node_Max;
343                 op_Max->ops.verify_node     = verify_node_MinMax;
344         }
345 }