beuses: Remove stale start loop test.
[libfirm] / ir / be / amd64 / amd64_transform.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   code selection (transform FIRM into amd64 FIRM)
23  */
24 #include "config.h"
25
26 #include "irnode_t.h"
27 #include "irgraph_t.h"
28 #include "irmode_t.h"
29 #include "irgmod.h"
30 #include "iredges.h"
31 #include "ircons.h"
32 #include "iropt_t.h"
33 #include "error.h"
34 #include "debug.h"
35
36 #include "benode.h"
37 #include "betranshlp.h"
38 #include "beutil.h"
39 #include "bearch_amd64_t.h"
40
41 #include "amd64_nodes_attr.h"
42 #include "amd64_transform.h"
43 #include "amd64_new_nodes.h"
44
45 #include "gen_amd64_regalloc_if.h"
46
47 DEBUG_ONLY(static firm_dbg_module_t *dbg = NULL;)
48
49 /* Some support functions: */
50
51 static inline int mode_needs_gp_reg(ir_mode *mode)
52 {
53         return mode_is_int(mode) || mode_is_reference(mode);
54 }
55
56 /**
57  * Create a DAG constructing a given Const.
58  *
59  * @param irn  a Firm const
60  */
61 static ir_node *create_const_graph(ir_node *irn, ir_node *block)
62 {
63         ir_tarval *tv   = get_Const_tarval(irn);
64         ir_mode   *mode = get_tarval_mode(tv);
65         dbg_info  *dbgi = get_irn_dbg_info(irn);
66         unsigned   value;
67
68         if (mode_is_reference(mode)) {
69                 /* AMD64 is 64bit, so we can safely convert a reference tarval into Iu */
70                 assert(get_mode_size_bits(mode) == get_mode_size_bits(mode_Lu));
71                 tv = tarval_convert_to(tv, mode_Lu);
72         }
73
74         value = get_tarval_long(tv);
75
76         return new_bd_amd64_Immediate(dbgi, block, value);
77 }
78
79 /* Op transformers: */
80
81 /**
82  * Transforms a Const node.
83  *
84  * @return The transformed AMD64 node.
85  */
86 static ir_node *gen_Const(ir_node *node) {
87         ir_node  *block = be_transform_node(get_nodes_block(node));
88         ir_mode  *mode  = get_irn_mode(node);
89         ir_node *res = create_const_graph(node, block);
90         (void) mode;
91
92         return res;
93 }
94
95 /**
96  * Transforms a SymConst node.
97  *
98  * @return The transformed ARM node.
99  */
100 static ir_node *gen_SymConst(ir_node *node)
101 {
102         ir_node   *block  = be_transform_node(get_nodes_block(node));
103         ir_entity *entity = get_SymConst_entity(node);
104         dbg_info  *dbgi   = get_irn_dbg_info(node);
105         ir_node   *new_node;
106
107         new_node = new_bd_amd64_SymConst(dbgi, block, entity);
108         return new_node;
109 }
110
111 /**
112  * Transforms an Add node.
113  *
114  * @return The transformed AMD64 node.
115  */
116 static ir_node *gen_Add(ir_node *node) {
117         ir_node  *block = be_transform_node(get_nodes_block(node));
118         ir_node  *op1   = get_Add_left(node);
119         ir_node  *op2   = get_Add_right(node);
120         dbg_info *dbgi  = get_irn_dbg_info(node);
121         ir_node  *new_op1 = be_transform_node(op1);
122         ir_node  *new_op2 = be_transform_node(op2);
123
124         ir_node *res = new_bd_amd64_Add(dbgi, block, new_op1, new_op2);
125         return res;
126 }
127
128 /**
129  * Transforms an Sub node.
130  *
131  * @return The transformed AMD64 node.
132  */
133 static ir_node *gen_Sub(ir_node *node) {
134         ir_node  *block = be_transform_node(get_nodes_block(node));
135         ir_node  *op1   = get_Sub_left(node);
136         ir_node  *op2   = get_Sub_right(node);
137         dbg_info *dbgi  = get_irn_dbg_info(node);
138         ir_node  *new_op1 = be_transform_node(op1);
139         ir_node  *new_op2 = be_transform_node(op2);
140
141         ir_node *res = new_bd_amd64_Sub(dbgi, block, new_op1, new_op2);
142         return res;
143 }
144
145 static ir_node *gen_Mul(ir_node *node) {
146         ir_node  *block = be_transform_node(get_nodes_block(node));
147         ir_node  *op1   = get_Mul_left(node);
148         ir_node  *op2   = get_Mul_right(node);
149         dbg_info *dbgi  = get_irn_dbg_info(node);
150         ir_node  *new_op1 = be_transform_node(op1);
151         ir_node  *new_op2 = be_transform_node(op2);
152
153         ir_node *res = new_bd_amd64_Mul(dbgi, block, new_op1, new_op2);
154         return res;
155 }
156
157 static ir_node *gen_Minus(ir_node *node)
158 {
159         ir_node  *block    = be_transform_node(get_nodes_block(node));
160         ir_node  *val      = be_transform_node(get_Minus_op(node));
161         dbg_info *dbgi     = get_irn_dbg_info(node);
162
163         return new_bd_amd64_Neg(dbgi, block, val);
164 }
165
166 static ir_node *gen_Jmp(ir_node *node)
167 {
168         ir_node  *block     = get_nodes_block(node);
169         ir_node  *new_block = be_transform_node(block);
170         dbg_info *dbgi      = get_irn_dbg_info(node);
171
172         return new_bd_amd64_Jmp(dbgi, new_block);
173 }
174
175 static ir_node *gen_be_Call(ir_node *node)
176 {
177         ir_node *res = be_duplicate_node(node);
178         arch_add_irn_flags(res, arch_irn_flags_modify_flags);
179
180         return res;
181 }
182
183 static ir_node *gen_Cmp(ir_node *node)
184 {
185         ir_node  *block    = be_transform_node(get_nodes_block(node));
186         ir_node  *op1      = get_Cmp_left(node);
187         ir_node  *op2      = get_Cmp_right(node);
188         ir_mode  *cmp_mode = get_irn_mode(op1);
189         dbg_info *dbgi     = get_irn_dbg_info(node);
190         ir_node  *new_op1;
191         ir_node  *new_op2;
192         bool      is_unsigned;
193
194         if (mode_is_float(cmp_mode)) {
195                 panic("Floating point not implemented yet!");
196         }
197
198         assert(get_irn_mode(op2) == cmp_mode);
199         is_unsigned = !mode_is_signed(cmp_mode);
200
201         new_op1 = be_transform_node(op1);
202         /* new_op1 = gen_extension(dbgi, block, new_op1, cmp_mode); */
203         new_op2 = be_transform_node(op2);
204         /* new_op2 = gen_extension(dbgi, block, new_op2, cmp_mode); */
205         return new_bd_amd64_Cmp(dbgi, block, new_op1, new_op2, false,
206                                 is_unsigned);
207 }
208
209 /**
210  * Transforms a Cond.
211  *
212  * @return the created ARM Cond node
213  */
214 static ir_node *gen_Cond(ir_node *node)
215 {
216         ir_node    *const block     = be_transform_node(get_nodes_block(node));
217         dbg_info   *const dbgi      = get_irn_dbg_info(node);
218         ir_node    *const selector  = get_Cond_selector(node);
219         ir_node    *const flag_node = be_transform_node(selector);
220         ir_relation const relation  = get_Cmp_relation(selector);
221         return new_bd_amd64_Jcc(dbgi, block, flag_node, relation);
222 }
223
224 static ir_node *gen_Phi(ir_node *node)
225 {
226         ir_mode                   *mode = get_irn_mode(node);
227         const arch_register_req_t *req;
228         if (mode_needs_gp_reg(mode)) {
229                 /* all integer operations are on 64bit registers now */
230                 mode = mode_Lu;
231                 req  = amd64_reg_classes[CLASS_amd64_gp].class_req;
232         } else {
233                 req = arch_no_register_req;
234         }
235
236         return be_transform_phi(node, req);
237 }
238
239 /**
240  * Transforms a Conv node.
241  *
242  * @return The created ia32 Conv node
243  */
244 static ir_node *gen_Conv(ir_node *node)
245 {
246         ir_node  *block    = be_transform_node(get_nodes_block(node));
247         ir_node  *op       = get_Conv_op(node);
248         ir_node  *new_op   = be_transform_node(op);
249         ir_mode  *src_mode = get_irn_mode(op);
250         ir_mode  *dst_mode = get_irn_mode(node);
251         dbg_info *dbgi     = get_irn_dbg_info(node);
252
253         if (src_mode == dst_mode)
254                 return new_op;
255
256         if (mode_is_float(src_mode) || mode_is_float(dst_mode)) {
257                 panic("float not supported yet");
258         } else { /* complete in gp registers */
259                 int src_bits = get_mode_size_bits(src_mode);
260                 int dst_bits = get_mode_size_bits(dst_mode);
261                 ir_mode *min_mode;
262
263                 if (src_bits == dst_bits) {
264                         /* kill unnecessary conv */
265                         return new_op;
266                 }
267
268                 if (src_bits < dst_bits) {
269                         min_mode = src_mode;
270                 } else {
271                         min_mode = dst_mode;
272                 }
273
274
275                 return new_bd_amd64_Conv(dbgi, block, new_op, min_mode);
276         }
277 }
278
279 /**
280  * Transforms a Store.
281  *
282  * @return the created AMD64 Store node
283  */
284 static ir_node *gen_Store(ir_node *node)
285 {
286         ir_node  *block    = be_transform_node(get_nodes_block(node));
287         ir_node  *ptr      = get_Store_ptr(node);
288         ir_node  *new_ptr  = be_transform_node(ptr);
289         ir_node  *mem      = get_Store_mem(node);
290         ir_node  *new_mem  = be_transform_node(mem);
291         ir_node  *val      = get_Store_value(node);
292         ir_node  *new_val  = be_transform_node(val);
293         ir_mode  *mode     = get_irn_mode(val);
294         dbg_info *dbgi     = get_irn_dbg_info(node);
295         ir_node *new_store = NULL;
296
297         if (mode_is_float(mode)) {
298                 panic("Float not supported yet");
299         } else {
300                 assert(mode_is_data(mode) && "unsupported mode for Store");
301                 new_store = new_bd_amd64_Store(dbgi, block, new_ptr, new_val, new_mem, 0);
302         }
303         set_irn_pinned(new_store, get_irn_pinned(node));
304         return new_store;
305 }
306
307 /**
308  * Transforms a Load.
309  *
310  * @return the created AMD64 Load node
311  */
312 static ir_node *gen_Load(ir_node *node)
313 {
314         ir_node  *block    = be_transform_node(get_nodes_block(node));
315         ir_node  *ptr      = get_Load_ptr(node);
316         ir_node  *new_ptr  = be_transform_node(ptr);
317         ir_node  *mem      = get_Load_mem(node);
318         ir_node  *new_mem  = be_transform_node(mem);
319         ir_mode  *mode     = get_Load_mode(node);
320         dbg_info *dbgi     = get_irn_dbg_info(node);
321         ir_node  *new_load = NULL;
322
323         if (mode_is_float(mode)) {
324                 panic("Float not supported yet");
325         } else {
326                 assert(mode_is_data(mode) && "unsupported mode for Load");
327                 new_load = new_bd_amd64_Load(dbgi, block, new_ptr, new_mem, 0);
328         }
329         set_irn_pinned(new_load, get_irn_pinned(node));
330
331         return new_load;
332 }
333
334 /**
335  * Transform a Proj from a Load.
336  */
337 static ir_node *gen_Proj_Load(ir_node *node)
338 {
339         ir_node  *load     = get_Proj_pred(node);
340         ir_node  *new_load = be_transform_node(load);
341         dbg_info *dbgi     = get_irn_dbg_info(node);
342         long     proj      = get_Proj_proj(node);
343
344         /* renumber the proj */
345         switch (get_amd64_irn_opcode(new_load)) {
346                 case iro_amd64_Load:
347                         /* handle all gp loads equal: they have the same proj numbers. */
348                         if (proj == pn_Load_res) {
349                                 return new_rd_Proj(dbgi, new_load, mode_Lu, pn_amd64_Load_res);
350                         } else if (proj == pn_Load_M) {
351                                 return new_rd_Proj(dbgi, new_load, mode_M, pn_amd64_Load_M);
352                         }
353                 break;
354                 default:
355                         panic("Unsupported Proj from Load");
356         }
357
358     return be_duplicate_node(node);
359 }
360
361 /**
362  * Transform a Proj node.
363  */
364 static ir_node *gen_Proj(ir_node *node)
365 {
366         dbg_info *dbgi = get_irn_dbg_info(node);
367         ir_node  *pred = get_Proj_pred(node);
368         long     proj  = get_Proj_proj(node);
369
370     (void) dbgi;
371
372         if (is_Store(pred)) {
373                 if (proj == pn_Store_M) {
374                         return be_transform_node(pred);
375                 } else {
376                         panic("Unsupported Proj from Store");
377                 }
378         } else if (is_Load(pred)) {
379                 return gen_Proj_Load(node);
380         } else if (is_Start(pred)) {
381         }
382
383     return be_duplicate_node(node);
384 }
385
386 /**
387  * Transforms a FrameAddr into an AMD64 Add.
388  */
389 static ir_node *gen_be_FrameAddr(ir_node *node)
390 {
391         ir_node   *block  = be_transform_node(get_nodes_block(node));
392         ir_entity *ent    = be_get_frame_entity(node);
393         ir_node   *fp     = be_get_FrameAddr_frame(node);
394         ir_node   *new_fp = be_transform_node(fp);
395         dbg_info  *dbgi   = get_irn_dbg_info(node);
396         ir_node   *new_node;
397
398         new_node = new_bd_amd64_FrameAddr(dbgi, block, new_fp, ent);
399         return new_node;
400 }
401
402 /* Boilerplate code for transformation: */
403
404 static void amd64_register_transformers(void)
405 {
406         be_start_transform_setup();
407
408         be_set_transform_function(op_Const,        gen_Const);
409         be_set_transform_function(op_SymConst,     gen_SymConst);
410         be_set_transform_function(op_Add,          gen_Add);
411         be_set_transform_function(op_Sub,          gen_Sub);
412         be_set_transform_function(op_Mul,          gen_Mul);
413         be_set_transform_function(op_be_Call,      gen_be_Call);
414         be_set_transform_function(op_be_FrameAddr, gen_be_FrameAddr);
415         be_set_transform_function(op_Conv,         gen_Conv);
416         be_set_transform_function(op_Jmp,          gen_Jmp);
417         be_set_transform_function(op_Cmp,          gen_Cmp);
418         be_set_transform_function(op_Cond,         gen_Cond);
419         be_set_transform_function(op_Phi,          gen_Phi);
420         be_set_transform_function(op_Load,         gen_Load);
421         be_set_transform_function(op_Store,        gen_Store);
422         be_set_transform_function(op_Proj,         gen_Proj);
423         be_set_transform_function(op_Minus,        gen_Minus);
424 }
425
426 void amd64_transform_graph(ir_graph *irg)
427 {
428         amd64_register_transformers();
429         be_transform_graph(irg, NULL);
430 }
431
432 void amd64_init_transform(void)
433 {
434         FIRM_DBG_REGISTER(dbg, "firm.be.amd64.transform");
435 }