cleanup vrp
[libfirm] / ir / be / arm / arm_new_nodes.c
1 /*
2  * Copyright (C) 1995-2011 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  This file implements the creation of the architecture specific firm
23  *         opcodes and the corresponding node constructors for the arm
24  *         assembler irg.
25  * @author Oliver Richter, Tobias Gneist
26  */
27 #include "config.h"
28
29 #include <stdlib.h>
30 #include <stdbool.h>
31
32 #include "irprog_t.h"
33 #include "irgraph_t.h"
34 #include "irnode_t.h"
35 #include "irmode_t.h"
36 #include "ircons_t.h"
37 #include "iropt_t.h"
38 #include "irop.h"
39 #include "irprintf.h"
40 #include "xmalloc.h"
41
42 #include "bearch.h"
43
44 #include "arm_nodes_attr.h"
45 #include "arm_new_nodes.h"
46 #include "arm_optimize.h"
47
48 #include "beabi.h"
49 #include "bearch_arm_t.h"
50
51 static bool arm_has_symconst_attr(const ir_node *node)
52 {
53         return is_arm_SymConst(node) || is_arm_FrameAddr(node) || is_arm_Bl(node);
54 }
55
56 static bool has_load_store_attr(const ir_node *node)
57 {
58         return is_arm_Ldr(node) || is_arm_Str(node) || is_arm_LinkLdrPC(node)
59                 || is_arm_Ldf(node) || is_arm_Stf(node);
60 }
61
62 static bool has_shifter_operand(const ir_node *node)
63 {
64         return is_arm_Add(node) || is_arm_And(node) || is_arm_Or(node)
65                 || is_arm_Eor(node) || is_arm_Bic(node) || is_arm_Sub(node)
66                 || is_arm_Rsb(node) || is_arm_Mov(node) || is_arm_Mvn(node)
67                 || is_arm_Cmp(node) || is_arm_Tst(node) || is_arm_LinkMovPC(node);
68 }
69
70 static bool has_cmp_attr(const ir_node *node)
71 {
72         return is_arm_Cmp(node) || is_arm_Tst(node);
73 }
74
75 static bool has_farith_attr(const ir_node *node)
76 {
77         return is_arm_Adf(node) || is_arm_Muf(node) || is_arm_Suf(node)
78             || is_arm_Dvf(node) || is_arm_Mvf(node) || is_arm_FltX(node);
79 }
80
81 /**
82  * Dumper interface for dumping arm nodes in vcg.
83  * @param F        the output file
84  * @param n        the node to dump
85  * @param reason   indicates which kind of information should be dumped
86  */
87 static void arm_dump_node(FILE *F, const ir_node *n, dump_reason_t reason)
88 {
89         switch (reason) {
90         case dump_node_opcode_txt:
91                 fprintf(F, "%s", get_irn_opname(n));
92
93                 if (arm_has_symconst_attr(n)) {
94                         const arm_SymConst_attr_t *attr = get_arm_SymConst_attr_const(n);
95                         if (attr->entity != NULL) {
96                                 fputc(' ', F);
97                                 fputs(get_entity_name(attr->entity), F);
98                         }
99                 }
100                 break;
101
102         case dump_node_mode_txt:
103                 /* mode isn't relevant in the backend */
104                 break;
105
106         case dump_node_nodeattr_txt:
107                 /* TODO: dump shift modifiers */
108                 break;
109
110         case dump_node_info_txt:
111                 arch_dump_reqs_and_registers(F, n);
112
113                 if (has_load_store_attr(n)) {
114                         const arm_load_store_attr_t *attr
115                                 = get_arm_load_store_attr_const(n);
116                         ir_fprintf(F, "load_store_mode = %+F\n", attr->load_store_mode);
117                         ir_fprintf(F, "entity = %+F\n", attr->entity);
118                         fprintf(F, "offset = %ld\n", attr->offset);
119                         fprintf(F, "is_frame_entity = %s\n",
120                                         attr->is_frame_entity ? "yes" : "no");
121                         fprintf(F, "entity_sign = %s\n",
122                                         attr->entity_sign ? "yes" : "no");
123                 }
124                 if (has_shifter_operand(n)) {
125                         const arm_shifter_operand_t *attr
126                                 = get_arm_shifter_operand_attr_const(n);
127                         switch (attr->shift_modifier) {
128                         case ARM_SHF_REG:
129                                 break;
130                         case ARM_SHF_IMM:
131                                 fprintf(F, "modifier = imm %d ror %d\n",
132                                                 attr->immediate_value, attr->shift_immediate);
133                                 break;
134                         case ARM_SHF_ASR_IMM:
135                                 fprintf(F, "modifier = V >>s %d\n", attr->shift_immediate);
136                                 break;
137                         case ARM_SHF_ASR_REG:
138                                 fprintf(F, "modifier = V >>s R\n");
139                                 break;
140                         case ARM_SHF_LSL_IMM:
141                                 fprintf(F, "modifier = V << %d\n", attr->shift_immediate);
142                                 break;
143                         case ARM_SHF_LSL_REG:
144                                 fprintf(F, "modifier = V << R\n");
145                                 break;
146                         case ARM_SHF_LSR_IMM:
147                                 fprintf(F, "modifier = V >> %d\n", attr->shift_immediate);
148                                 break;
149                         case ARM_SHF_LSR_REG:
150                                 fprintf(F, "modifier = V >> R\n");
151                                 break;
152                         case ARM_SHF_ROR_IMM:
153                                 fprintf(F, "modifier = V ROR %d\n", attr->shift_immediate);
154                                 break;
155                         case ARM_SHF_ROR_REG:
156                                 fprintf(F, "modifier = V ROR R\n");
157                                 break;
158                         case ARM_SHF_RRX:
159                                 fprintf(F, "modifier = RRX\n");
160                                 break;
161                         default:
162                         case ARM_SHF_INVALID:
163                                 fprintf(F, "modifier = INVALID SHIFT MODIFIER\n");
164                                 break;
165                         }
166                 }
167                 if (has_cmp_attr(n)) {
168                         const arm_cmp_attr_t *attr = get_arm_cmp_attr_const(n);
169                         fprintf(F, "cmp_attr =");
170                         if (attr->is_unsigned) {
171                                 fprintf(F, " unsigned");
172                         }
173                         if (attr->ins_permuted) {
174                                 fprintf(F, " inputs swapped");
175                         }
176                         fputc('\n', F);
177                 }
178                 if (arm_has_symconst_attr(n)) {
179                         const arm_SymConst_attr_t *attr = get_arm_SymConst_attr_const(n);
180
181                         fprintf(F, "entity = ");
182                         if (attr->entity != NULL) {
183                                 fprintf(F, "'%s'", get_entity_name(attr->entity));
184                         } else {
185                                 fputs("NULL", F);
186                         }
187                         fputc('\n', F);
188                         fprintf(F, "frame offset = %d\n", attr->fp_offset);
189                 }
190                 if (has_farith_attr(n)) {
191                         const arm_farith_attr_t *attr = get_arm_farith_attr_const(n);
192                         ir_fprintf(F, "arithmetic mode = %+F\n", attr->mode);
193                 }
194                 break;
195         }
196 }
197
198 arm_attr_t *get_arm_attr(ir_node *node)
199 {
200         assert(is_arm_irn(node) && "need arm node to get attributes");
201         return (arm_attr_t*)get_irn_generic_attr(node);
202 }
203
204 const arm_attr_t *get_arm_attr_const(const ir_node *node)
205 {
206         assert(is_arm_irn(node) && "need arm node to get attributes");
207         return (const arm_attr_t*)get_irn_generic_attr_const(node);
208 }
209
210 static bool has_symconst_attr(const ir_node *node)
211 {
212         return is_arm_SymConst(node) || is_arm_FrameAddr(node) || is_arm_Bl(node);
213 }
214
215 arm_SymConst_attr_t *get_arm_SymConst_attr(ir_node *node)
216 {
217         assert(has_symconst_attr(node));
218         return (arm_SymConst_attr_t*)get_irn_generic_attr(node);
219 }
220
221 const arm_SymConst_attr_t *get_arm_SymConst_attr_const(const ir_node *node)
222 {
223         assert(has_symconst_attr(node));
224         return (const arm_SymConst_attr_t*)get_irn_generic_attr_const(node);
225 }
226
227 static const arm_fConst_attr_t *get_arm_fConst_attr_const(const ir_node *node)
228 {
229         assert(is_arm_fConst(node));
230         return (const arm_fConst_attr_t*)get_irn_generic_attr_const(node);
231 }
232
233 static arm_fConst_attr_t *get_arm_fConst_attr(ir_node *node)
234 {
235         assert(is_arm_fConst(node));
236         return (arm_fConst_attr_t*)get_irn_generic_attr(node);
237 }
238
239 arm_farith_attr_t *get_arm_farith_attr(ir_node *node)
240 {
241         assert(has_farith_attr(node));
242         return (arm_farith_attr_t*)get_irn_generic_attr(node);
243 }
244
245 const arm_farith_attr_t *get_arm_farith_attr_const(const ir_node *node)
246 {
247         assert(has_farith_attr(node));
248         return (const arm_farith_attr_t*)get_irn_generic_attr_const(node);
249 }
250
251 arm_CondJmp_attr_t *get_arm_CondJmp_attr(ir_node *node)
252 {
253         assert(is_arm_B(node));
254         return (arm_CondJmp_attr_t*)get_irn_generic_attr(node);
255 }
256
257 const arm_CondJmp_attr_t *get_arm_CondJmp_attr_const(const ir_node *node)
258 {
259         assert(is_arm_B(node));
260         return (const arm_CondJmp_attr_t*)get_irn_generic_attr_const(node);
261 }
262
263 arm_SwitchJmp_attr_t *get_arm_SwitchJmp_attr(ir_node *node)
264 {
265         assert(is_arm_SwitchJmp(node));
266         return (arm_SwitchJmp_attr_t*)get_irn_generic_attr(node);
267 }
268
269 const arm_SwitchJmp_attr_t *get_arm_SwitchJmp_attr_const(const ir_node *node)
270 {
271         assert(is_arm_SwitchJmp(node));
272         return (const arm_SwitchJmp_attr_t*)get_irn_generic_attr_const(node);
273 }
274
275 arm_CopyB_attr_t *get_arm_CopyB_attr(ir_node *node)
276 {
277         assert(is_arm_CopyB(node));
278         return (arm_CopyB_attr_t*)get_irn_generic_attr(node);
279 }
280
281 const arm_CopyB_attr_t *get_arm_CopyB_attr_const(const ir_node *node)
282 {
283         assert(is_arm_CopyB(node));
284         return (const arm_CopyB_attr_t*)get_irn_generic_attr_const(node);
285 }
286
287 ir_tarval *get_fConst_value(const ir_node *node)
288 {
289         const arm_fConst_attr_t *attr = get_arm_fConst_attr_const(node);
290         return attr->tv;
291 }
292
293 void set_fConst_value(ir_node *node, ir_tarval *tv)
294 {
295         arm_fConst_attr_t *attr = get_arm_fConst_attr(node);
296         attr->tv = tv;
297 }
298
299 ir_relation get_arm_CondJmp_relation(const ir_node *node)
300 {
301         const arm_CondJmp_attr_t *attr = get_arm_CondJmp_attr_const(node);
302         return attr->relation;
303 }
304
305 void set_arm_CondJmp_relation(ir_node *node, ir_relation relation)
306 {
307         arm_CondJmp_attr_t *attr = get_arm_CondJmp_attr(node);
308         attr->relation = relation;
309 }
310
311 /* Set the ARM machine node attributes to default values. */
312 static void init_arm_attributes(ir_node *node, arch_irn_flags_t flags,
313                          const arch_register_req_t ** in_reqs,
314                                                  int n_res)
315 {
316         ir_graph       *irg  = get_irn_irg(node);
317         struct obstack *obst = get_irg_obstack(irg);
318         arm_attr_t     *attr = get_arm_attr(node);
319         backend_info_t *info;
320
321         arch_set_irn_flags(node, flags);
322         arch_set_irn_register_reqs_in(node, in_reqs);
323         attr->is_load_store    = false;
324
325         info            = be_get_info(node);
326         info->out_infos = NEW_ARR_DZ(reg_out_info_t, obst, n_res);
327 }
328
329 static void init_arm_load_store_attributes(ir_node *res, ir_mode *ls_mode,
330                                            ir_entity *entity,
331                                            int entity_sign, long offset,
332                                            bool is_frame_entity)
333 {
334         arm_load_store_attr_t *attr = get_arm_load_store_attr(res);
335         attr->load_store_mode    = ls_mode;
336         attr->entity             = entity;
337         attr->entity_sign        = entity_sign;
338         attr->is_frame_entity    = is_frame_entity;
339         attr->offset             = offset;
340         attr->base.is_load_store = true;
341 }
342
343 static void init_arm_shifter_operand(ir_node *res, unsigned immediate_value,
344                                      arm_shift_modifier_t shift_modifier,
345                                      unsigned shift_immediate)
346 {
347         arm_shifter_operand_t *attr = get_arm_shifter_operand_attr(res);
348         attr->immediate_value = immediate_value;
349         attr->shift_modifier  = shift_modifier;
350         attr->shift_immediate = shift_immediate;
351 }
352
353 static void init_arm_cmp_attr(ir_node *res, bool ins_permuted, bool is_unsigned)
354 {
355         arm_cmp_attr_t *attr = get_arm_cmp_attr(res);
356         attr->ins_permuted = ins_permuted;
357         attr->is_unsigned  = is_unsigned;
358 }
359
360 static void init_arm_SymConst_attributes(ir_node *res, ir_entity *entity,
361                                          int symconst_offset)
362 {
363         arm_SymConst_attr_t *attr = get_arm_SymConst_attr(res);
364         attr->entity    = entity;
365         attr->fp_offset = symconst_offset;
366 }
367
368 static void init_arm_farith_attributes(ir_node *res, ir_mode *mode)
369 {
370         arm_farith_attr_t *attr = get_arm_farith_attr(res);
371         attr->mode = mode;
372 }
373
374 static void init_arm_CopyB_attributes(ir_node *res, unsigned size)
375 {
376         arm_CopyB_attr_t *attr = get_arm_CopyB_attr(res);
377         attr->size = size;
378 }
379
380 static void init_arm_SwitchJmp_attributes(ir_node *res,
381                                           const ir_switch_table *table)
382 {
383         arm_SwitchJmp_attr_t *attr = get_arm_SwitchJmp_attr(res);
384         attr->table = table;
385
386         be_foreach_out(res, o) {
387                 arch_set_irn_register_req_out(res, o, arch_no_register_req);
388         }
389 }
390
391 static int cmp_attr_arm(const ir_node *a, const ir_node *b)
392 {
393         (void) a;
394         (void) b;
395         return 0;
396 }
397
398 static int cmp_attr_arm_SymConst(const ir_node *a, const ir_node *b)
399 {
400         const arm_SymConst_attr_t *attr_a;
401         const arm_SymConst_attr_t *attr_b;
402
403         if (cmp_attr_arm(a, b))
404                 return 1;
405
406         attr_a = get_arm_SymConst_attr_const(a);
407         attr_b = get_arm_SymConst_attr_const(b);
408         return attr_a->entity != attr_b->entity
409                 || attr_a->fp_offset != attr_b->fp_offset;
410 }
411
412 static int cmp_attr_arm_CopyB(const ir_node *a, const ir_node *b)
413 {
414         const arm_CopyB_attr_t *attr_a;
415         const arm_CopyB_attr_t *attr_b;
416
417         if (cmp_attr_arm(a, b))
418                 return 1;
419
420         attr_a = get_arm_CopyB_attr_const(a);
421         attr_b = get_arm_CopyB_attr_const(b);
422         return attr_a->size != attr_b->size;
423 }
424
425 static int cmp_attr_arm_CondJmp(const ir_node *a, const ir_node *b)
426 {
427         (void) a;
428         (void) b;
429         /* never identical */
430         return 1;
431 }
432
433 static int cmp_attr_arm_SwitchJmp(const ir_node *a, const ir_node *b)
434 {
435         (void) a;
436         (void) b;
437         /* never identical */
438         return 1;
439 }
440
441 static int cmp_attr_arm_fConst(const ir_node *a, const ir_node *b)
442 {
443         const arm_fConst_attr_t *attr_a;
444         const arm_fConst_attr_t *attr_b;
445
446         if (cmp_attr_arm(a, b))
447                 return 1;
448
449         attr_a = get_arm_fConst_attr_const(a);
450         attr_b = get_arm_fConst_attr_const(b);
451
452         return attr_a->tv != attr_b->tv;
453 }
454
455
456 arm_load_store_attr_t *get_arm_load_store_attr(ir_node *node)
457 {
458         return (arm_load_store_attr_t*) get_irn_generic_attr(node);
459 }
460
461 const arm_load_store_attr_t *get_arm_load_store_attr_const(const ir_node *node)
462 {
463         return (const arm_load_store_attr_t*) get_irn_generic_attr_const(node);
464 }
465
466 arm_shifter_operand_t *get_arm_shifter_operand_attr(ir_node *node)
467 {
468         return (arm_shifter_operand_t*) get_irn_generic_attr(node);
469 }
470
471 const arm_shifter_operand_t *get_arm_shifter_operand_attr_const(
472                 const ir_node *node)
473 {
474         return (const arm_shifter_operand_t*) get_irn_generic_attr_const(node);
475 }
476
477 arm_cmp_attr_t *get_arm_cmp_attr(ir_node *node)
478 {
479         return (arm_cmp_attr_t*) get_irn_generic_attr(node);
480 }
481
482 const arm_cmp_attr_t *get_arm_cmp_attr_const(const ir_node *node)
483 {
484         return (const arm_cmp_attr_t*) get_irn_generic_attr_const(node);
485 }
486
487 static int cmp_attr_arm_load_store(const ir_node *a, const ir_node *b)
488 {
489         const arm_load_store_attr_t *attr_a;
490         const arm_load_store_attr_t *attr_b;
491
492         if (cmp_attr_arm(a, b))
493                 return 1;
494
495         attr_a = get_arm_load_store_attr_const(a);
496         attr_b = get_arm_load_store_attr_const(b);
497         if (attr_a->entity != attr_b->entity
498                         || attr_a->entity_sign != attr_b->entity_sign
499                         || attr_a->offset != attr_b->offset)
500                 return 1;
501
502         return 0;
503 }
504
505 static int cmp_attr_arm_shifter_operand(const ir_node *a, const ir_node *b)
506 {
507         const arm_shifter_operand_t *attr_a;
508         const arm_shifter_operand_t *attr_b;
509
510         if (cmp_attr_arm(a, b))
511                 return 1;
512
513         attr_a = get_arm_shifter_operand_attr_const(a);
514         attr_b = get_arm_shifter_operand_attr_const(b);
515         if (attr_a->shift_modifier != attr_b->shift_modifier
516                         || attr_a->immediate_value != attr_b->immediate_value
517                         || attr_a->shift_immediate != attr_b->shift_immediate)
518                 return 1;
519
520         return 0;
521 }
522
523 static int cmp_attr_arm_cmp(const ir_node *a, const ir_node *b)
524 {
525         const arm_cmp_attr_t *attr_a;
526         const arm_cmp_attr_t *attr_b;
527
528         if (cmp_attr_arm(a, b))
529                 return 1;
530
531         attr_a = get_arm_cmp_attr_const(a);
532         attr_b = get_arm_cmp_attr_const(b);
533         if (attr_a->ins_permuted != attr_b->ins_permuted
534                         || attr_a->is_unsigned != attr_b->is_unsigned)
535                 return 1;
536         return 0;
537 }
538
539 static int cmp_attr_arm_farith(const ir_node *a, const ir_node *b)
540 {
541         const arm_farith_attr_t *attr_a;
542         const arm_farith_attr_t *attr_b;
543
544         if (cmp_attr_arm(a, b))
545                 return 1;
546
547         attr_a = get_arm_farith_attr_const(a);
548         attr_b = get_arm_farith_attr_const(b);
549         return attr_a->mode != attr_b->mode;
550 }
551
552 /** copies the ARM attributes of a node. */
553 static void arm_copy_attr(ir_graph *irg, const ir_node *old_node,
554                           ir_node *new_node)
555 {
556         struct obstack   *obst    = get_irg_obstack(irg);
557         const arm_attr_t *attr_old = get_arm_attr_const(old_node);
558         arm_attr_t       *attr_new = get_arm_attr(new_node);
559         backend_info_t   *old_info = be_get_info(old_node);
560         backend_info_t   *new_info = be_get_info(new_node);
561
562         /* copy the attributes */
563         memcpy(attr_new, attr_old, get_op_attr_size(get_irn_op(old_node)));
564
565         /* copy out flags */
566         new_info->flags = old_info->flags;
567         new_info->out_infos =
568                 DUP_ARR_D(reg_out_info_t, obst, old_info->out_infos);
569         new_info->in_reqs = old_info->in_reqs;
570 }
571
572
573 /* Include the generated constructor functions */
574 #include "gen_arm_new_nodes.c.inl"