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