- made default opcodes for Min, Max
[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
44 /* when we need verifying */
45 #ifdef NDEBUG
46 # define IRN_VRFY_IRG(res, irg)
47 #else
48 # define IRN_VRFY_IRG(res, irg)  irn_vrfy_irg(res, irg)
49 #endif
50
51 /** current settings */
52 static arch_ops_info settings;
53
54 /** default settings */
55 static const arch_ops_info default_settings = {
56         ARCH_OPS_NONE,
57         0
58 };
59
60 /** The Min operation */
61 ir_op *op_Min = NULL;
62
63 /** The Max operation */
64 ir_op *op_Max = NULL;
65
66 ir_op *get_op_Min(void)  { return op_Min; }
67 ir_op *get_op_Max(void)  { return op_Max; }
68
69 /*
70  * construct a Min: Min(a,b) = a < b ? a : b
71  */
72 ir_node *
73 new_rd_Min(dbg_info *db, ir_graph *irg, ir_node *block,
74            ir_node *op1, ir_node *op2, ir_mode *mode)
75 {
76         ir_node *in[2];
77         ir_node *res;
78
79         if (! op_Min) {
80                 assert(0);
81                 return NULL;
82         }
83
84         in[0] = op1;
85         in[1] = op2;
86         res = new_ir_node(db, irg, block, op_Min, mode, 2, in);
87         res = optimize_node(res);
88         IRN_VRFY_IRG(res, irg);
89         return res;
90 }
91
92 /*
93  * construct a Max: Max(a,b) = a > b ? a : b
94  */
95 ir_node *
96 new_rd_Max(dbg_info *db, ir_graph *irg, ir_node *block,
97            ir_node *op1, ir_node *op2, ir_mode *mode)
98 {
99         ir_node *in[2];
100         ir_node *res;
101
102         if (! op_Max) {
103                 assert(0);
104                 return NULL;
105         }
106
107         in[0] = op1;
108         in[1] = op2;
109         res = new_ir_node(db, irg, block, op_Max, mode, 2, in);
110         res = optimize_node(res);
111         IRN_VRFY_IRG(res, irg);
112         return res;
113 }
114
115 ir_node *
116 new_r_Min(ir_graph *irg, ir_node *block,
117           ir_node *op1, ir_node *op2, ir_mode *mode) {
118         return new_rd_Min(NULL, irg, block, op1, op2, mode);
119 }
120
121 ir_node *
122 new_r_Max(ir_graph *irg, ir_node *block,
123        ir_node *op1, ir_node *op2, ir_mode *mode) {
124   return new_rd_Max(NULL, irg, block, op1, op2, mode);
125 }
126
127 ir_node *
128 new_d_Min(dbg_info *db, ir_node *op1, ir_node *op2, ir_mode *mode) {
129         return new_rd_Min(db, current_ir_graph, current_ir_graph->current_block,
130                           op1, op2, mode);
131 }
132
133 ir_node *
134 new_d_Max(dbg_info *db, ir_node *op1, ir_node *op2, ir_mode *mode) {
135         return new_rd_Max(db, current_ir_graph, current_ir_graph->current_block,
136                           op1, op2, mode);
137 }
138
139 ir_node *
140 new_Min(ir_node *op1, ir_node *op2, ir_mode *mode) {
141         return new_d_Min(NULL, op1, op2, mode);
142 }
143
144 ir_node *
145 new_Max(ir_node *op1, ir_node *op2, ir_mode *mode) {
146   return new_d_Max(NULL, op1, op2, mode);
147 }
148
149 /* optimizations */
150
151 /**
152  * return the value of a Min
153  */
154 static tarval *computed_value_Min(const ir_node *n) {
155         ir_node *a = get_binop_left(n);
156         ir_node *b = get_binop_right(n);
157
158         tarval *ta = value_of(a);
159         tarval *tb = value_of(b);
160
161         if ((ta != tarval_bad) && (tb != tarval_bad) && (get_irn_mode(a) == get_irn_mode(b))) {
162                 pn_Cmp res = tarval_cmp(ta, tb);
163
164                 /* beware: there might be Unordered tarvals here, in that
165                 * case let the backend decide, do NOT optimize */
166                 if (res == pn_Cmp_Lt)
167                         return ta;
168                 if (res == pn_Cmp_Gt || res == pn_Cmp_Eq)
169                         return tb;
170         }
171         return tarval_bad;
172 }
173
174 /**
175  * return the value of a Max
176  */
177 static tarval *computed_value_Max(const ir_node *n) {
178         ir_node *a      = get_binop_left(n);
179         ir_node *b      = get_binop_right(n);
180
181         tarval *tb = value_of(b);
182         tarval *ta = value_of(a);
183
184         if ((ta != tarval_bad) && (tb != tarval_bad) && (get_irn_mode(a) == get_irn_mode(b))) {
185                 pn_Cmp res = tarval_cmp(ta, tb);
186
187                 /* beware: there might be Unordered tarvals here, in that
188                  * case let the backend decide, do NOT optimize */
189                 if (res == pn_Cmp_Gt)
190                         return ta;
191                 if (res == pn_Cmp_Lt || res == pn_Cmp_Eq)
192                         return tb;
193         }
194         return tarval_bad;
195 }
196
197 /**
198  * Returns an equivalent node for a Min/Max node.
199  * We do not allow Exceptions in our Min/Max, so there will be always
200  * an result.
201  * The problem is Min(NaN, NaN) == NaN ???.
202  */
203 static ir_node *equivalent_node_MinMax(ir_node *n)
204 {
205         ir_node *a, *b;
206         ir_mode *mode;
207         tarval *tv;
208
209         if (settings.minmax_handle_NaN == 0 && mode_is_float(get_irn_mode(n)))
210                 return n;
211
212         a = get_binop_left(n);
213         b = get_binop_right(n);
214
215         if (a == b) {
216                 DBG_OPT_ALGSIM0(n, a, FS_OPT_MIN_MAX_EQ);
217                 return a;
218         }
219
220         mode = get_irn_mode(n);
221         tv   = n->op == op_Max ? get_mode_min(mode) : get_mode_max(mode);
222
223         if (value_of(b) == tv) {
224                 DBG_OPT_ALGSIM0(n, a, FS_OPT_MIN_MAX_EQ);
225                 return a;
226         }
227         if (value_of(a) == tv) {
228                 DBG_OPT_ALGSIM0(n, b, FS_OPT_MIN_MAX_EQ);
229                 return b;
230         }
231
232         return n;
233 }
234
235 #define equivalent_node_Min equivalent_node_MinMax
236 #define equivalent_node_Max equivalent_node_MinMax
237
238 /*
239  * Create Min and Max from Mux nodes
240  */
241 ir_node *arch_transform_node_Mux(ir_node *n)
242 {
243         if (settings.enabled_ops & ARCH_OPS_MINMAX) {
244                 ir_node *oldn = n, *cmp, *proj = get_Mux_sel(n);
245                 long proj_nr;
246
247                 if (get_irn_op(proj) != op_Proj)
248                         return n;
249
250                 cmp = get_Proj_pred(proj);
251                 if (get_irn_op(cmp) == op_Cmp) {
252                         ir_node *a = get_Cmp_left(cmp);
253                         ir_node *b = get_Cmp_right(cmp);
254                         ir_node *t = get_Mux_true(n);
255                         ir_node *f = get_Mux_false(n);
256
257                         proj_nr = get_Proj_proj(proj);
258
259                         if (proj_nr == pn_Cmp_Lt || proj_nr == pn_Cmp_Le) {
260                                 if (a == t && b == f) {
261                                         /* a </<= b ? a : b  ==>  Min(a,b) */
262                                         n = new_rd_Min(get_irn_dbg_info(n),
263                                                 current_ir_graph,
264                                                 get_nodes_block(n),
265                                                 a, b,
266                                                 get_irn_mode(n));
267
268                                         DBG_OPT_ALGSIM1(oldn, cmp, proj, n, FS_OPT_MUX_TO_MIN);
269                                         return n;
270                                 }
271                                 else if (a == f && b == t) {
272                                         /* a </<= b ? b : a  ==>  Max(a,b) */
273                                         n = new_rd_Max(get_irn_dbg_info(n),
274                                                 current_ir_graph,
275                                                 get_nodes_block(n),
276                                                 a, b,
277                                                 get_irn_mode(n));
278
279                                         DBG_OPT_ALGSIM1(oldn, cmp, proj, n, FS_OPT_MUX_TO_MAX);
280                                         return n;
281                                 }
282                         }
283                         else if (proj_nr == pn_Cmp_Gt || proj_nr == pn_Cmp_Ge) {
284                                 if (a == t && b == f) {
285                                         /* a >/>= b ? a : b  ==>  Max(a,b) */
286                                         n = new_rd_Max(get_irn_dbg_info(n),
287                                                 current_ir_graph,
288                                                 get_nodes_block(n),
289                                                 a, b,
290                                                 get_irn_mode(n));
291
292                                         DBG_OPT_ALGSIM1(oldn, cmp, proj, n, FS_OPT_MUX_TO_MAX);
293                                         return n;
294                                 }
295                                 else if (a == f && b == t) {
296                                         /* a >/>= b ? b : a  ==>  Min(a,b) */
297                                         n = new_rd_Min(get_irn_dbg_info(n),
298                                                 current_ir_graph,
299                                                 get_nodes_block(n),
300                                                 a, b,
301                                                 get_irn_mode(n));
302
303                                         DBG_OPT_ALGSIM1(oldn, cmp, proj, n, FS_OPT_MUX_TO_MIN);
304                                         return n;
305                                 }
306                         }
307                 }
308         }
309         return n;
310 }
311
312 /**
313  * verify a MinMax node
314  */
315 static int verify_node_MinMax(ir_node *n, ir_graph *irg) {
316         ir_mode *mymode  = get_irn_mode(n);
317         ir_mode *op1mode = get_irn_mode(get_binop_left(n));
318         ir_mode *op2mode = get_irn_mode(get_binop_right(n));
319         (void) irg;
320
321         ASSERT_AND_RET(
322                 /* MinMax: BB x numP x numP --> numP */
323                 op1mode == mymode &&
324                 op2mode == mymode &&
325                 mode_is_data(mymode),
326                 "Min or Max node", 0
327                 );
328         return 1;
329 }
330
331 /*
332  * initialize the ops.
333  */
334 void firm_archops_init(const arch_ops_info *info)
335 {
336         ir_op_ops ops;
337
338         if (! info)
339                 info = &default_settings;
340
341         memcpy(&settings, info, sizeof(settings));
342
343         if (info->enabled_ops & ARCH_OPS_MINMAX) {
344                 memset(&ops, 0, sizeof(ops));
345
346                 ops.computed_value  = computed_value_Min;
347                 ops.equivalent_node = equivalent_node_Min;
348                 ops.verify_node     = verify_node_MinMax;
349
350                 op_Min = new_ir_op(iro_Min, "Min",  op_pin_state_floats, irop_flag_commutative, oparity_binary, 0, 0, &ops);
351
352                 ops.computed_value  = computed_value_Max;
353                 ops.equivalent_node = equivalent_node_Max;
354                 ops.verify_node     = verify_node_MinMax;
355
356                 op_Max = new_ir_op(iro_Max, "Max",  op_pin_state_floats, irop_flag_commutative, oparity_binary, 0, 0, &ops);
357         }
358 }