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