besched: Add and use sched_replace().
[libfirm] / ir / be / arm / bearch_arm.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   The main arm backend driver file.
23  * @author  Matthias Braun, Oliver Richter, Tobias Gneist
24  */
25 #include "config.h"
26
27 #include "lc_opts.h"
28 #include "lc_opts_enum.h"
29
30 #include "irgwalk.h"
31 #include "irprog.h"
32 #include "irprintf.h"
33 #include "ircons.h"
34 #include "irgmod.h"
35 #include "irgopt.h"
36 #include "iroptimize.h"
37 #include "irdump.h"
38 #include "lower_calls.h"
39 #include "error.h"
40
41 #include "bitset.h"
42 #include "debug.h"
43 #include "array_t.h"
44 #include "irtools.h"
45
46 #include "bearch.h"
47 #include "benode.h"
48 #include "belower.h"
49 #include "besched.h"
50 #include "be.h"
51 #include "bemodule.h"
52 #include "beirg.h"
53 #include "bespillslots.h"
54 #include "bespillutil.h"
55 #include "begnuas.h"
56 #include "belistsched.h"
57 #include "beflags.h"
58 #include "bestack.h"
59
60 #include "bearch_arm_t.h"
61
62 #include "arm_new_nodes.h"
63 #include "gen_arm_regalloc_if.h"
64 #include "arm_transform.h"
65 #include "arm_optimize.h"
66 #include "arm_emitter.h"
67 #include "arm_map_regs.h"
68
69 static ir_entity *arm_get_frame_entity(const ir_node *irn)
70 {
71         const arm_attr_t *attr = get_arm_attr_const(irn);
72
73         if (is_arm_FrameAddr(irn)) {
74                 const arm_SymConst_attr_t *frame_attr = get_arm_SymConst_attr_const(irn);
75                 return frame_attr->entity;
76         }
77         if (attr->is_load_store) {
78                 const arm_load_store_attr_t *load_store_attr
79                         = get_arm_load_store_attr_const(irn);
80                 if (load_store_attr->is_frame_entity) {
81                         return load_store_attr->entity;
82                 }
83         }
84         return NULL;
85 }
86
87 /**
88  * This function is called by the generic backend to correct offsets for
89  * nodes accessing the stack.
90  */
91 static void arm_set_stack_bias(ir_node *irn, int bias)
92 {
93         if (is_arm_FrameAddr(irn)) {
94                 arm_SymConst_attr_t *attr = get_arm_SymConst_attr(irn);
95                 attr->fp_offset += bias;
96         } else {
97                 arm_load_store_attr_t *attr = get_arm_load_store_attr(irn);
98                 assert(attr->base.is_load_store);
99                 attr->offset += bias;
100         }
101 }
102
103 static int arm_get_sp_bias(const ir_node *irn)
104 {
105         /* We don't have any nodes changing the stack pointer.
106            We probably want to support post-/pre increment/decrement later */
107         (void) irn;
108         return 0;
109 }
110
111 /* fill register allocator interface */
112
113 static const arch_irn_ops_t arm_irn_ops = {
114         arm_get_frame_entity,
115         arm_set_stack_bias,
116         arm_get_sp_bias,
117         NULL,    /* get_op_estimated_cost   */
118         NULL,    /* possible_memory_operand */
119         NULL,    /* perform_memory_operand  */
120 };
121
122 /**
123  * Transforms the standard Firm graph into
124  * a ARM firm graph.
125  */
126 static void arm_prepare_graph(ir_graph *irg)
127 {
128         /* transform nodes into assembler instructions */
129         arm_transform_graph(irg);
130
131         /* do local optimizations (mainly CSE) */
132         local_optimize_graph(irg);
133
134         /* do code placement, to optimize the position of constants */
135         place_code(irg);
136 }
137
138 static void arm_collect_frame_entity_nodes(ir_node *node, void *data)
139 {
140         be_fec_env_t  *env = (be_fec_env_t*)data;
141         const ir_mode *mode;
142         int            align;
143         ir_entity     *entity;
144         const arm_load_store_attr_t *attr;
145
146         if (be_is_Reload(node) && be_get_frame_entity(node) == NULL) {
147                 mode  = get_irn_mode(node);
148                 align = get_mode_size_bytes(mode);
149                 be_node_needs_frame_entity(env, node, mode, align);
150                 return;
151         }
152
153         switch (get_arm_irn_opcode(node)) {
154         case iro_arm_Ldf:
155         case iro_arm_Ldr:
156                 break;
157         default:
158                 return;
159         }
160
161         attr   = get_arm_load_store_attr_const(node);
162         entity = attr->entity;
163         mode   = attr->load_store_mode;
164         align  = get_mode_size_bytes(mode);
165         if (entity != NULL)
166                 return;
167         if (!attr->is_frame_entity)
168                 return;
169         be_node_needs_frame_entity(env, node, mode, align);
170 }
171
172 static void arm_set_frame_entity(ir_node *node, ir_entity *entity)
173 {
174         if (is_be_node(node)) {
175                 be_node_set_frame_entity(node, entity);
176         } else {
177                 arm_load_store_attr_t *attr = get_arm_load_store_attr(node);
178                 attr->entity = entity;
179         }
180 }
181
182 static void transform_Reload(ir_node *node)
183 {
184         ir_node   *block  = get_nodes_block(node);
185         dbg_info  *dbgi   = get_irn_dbg_info(node);
186         ir_node   *ptr    = get_irn_n(node, n_be_Reload_frame);
187         ir_node   *mem    = get_irn_n(node, n_be_Reload_mem);
188         ir_mode   *mode   = get_irn_mode(node);
189         ir_entity *entity = be_get_frame_entity(node);
190         const arch_register_t *reg;
191         ir_node   *proj;
192         ir_node   *load;
193
194         load = new_bd_arm_Ldr(dbgi, block, ptr, mem, mode, entity, false, 0, true);
195         sched_replace(node, load);
196
197         proj = new_rd_Proj(dbgi, load, mode, pn_arm_Ldr_res);
198
199         reg = arch_get_irn_register(node);
200         arch_set_irn_register(proj, reg);
201
202         exchange(node, proj);
203 }
204
205 static void transform_Spill(ir_node *node)
206 {
207         ir_node   *block  = get_nodes_block(node);
208         dbg_info  *dbgi   = get_irn_dbg_info(node);
209         ir_node   *ptr    = get_irn_n(node, n_be_Spill_frame);
210         ir_graph  *irg    = get_irn_irg(node);
211         ir_node   *mem    = get_irg_no_mem(irg);
212         ir_node   *val    = get_irn_n(node, n_be_Spill_val);
213         ir_mode   *mode   = get_irn_mode(val);
214         ir_entity *entity = be_get_frame_entity(node);
215         ir_node   *store;
216
217         store = new_bd_arm_Str(dbgi, block, ptr, val, mem, mode, entity, false, 0,
218                                true);
219         sched_replace(node, store);
220
221         exchange(node, store);
222 }
223
224 static void arm_after_ra_walker(ir_node *block, void *data)
225 {
226         ir_node *node, *prev;
227         (void) data;
228
229         for (node = sched_last(block); !sched_is_begin(node); node = prev) {
230                 prev = sched_prev(node);
231
232                 if (be_is_Reload(node)) {
233                         transform_Reload(node);
234                 } else if (be_is_Spill(node)) {
235                         transform_Spill(node);
236                 }
237         }
238 }
239
240 /**
241  * Called immediately before emit phase.
242  */
243 static void arm_finish_irg(ir_graph *irg)
244 {
245         be_stack_layout_t *stack_layout = be_get_irg_stack_layout(irg);
246         bool               at_begin     = stack_layout->sp_relative ? true : false;
247         be_fec_env_t      *fec_env      = be_new_frame_entity_coalescer(irg);
248
249         irg_walk_graph(irg, NULL, arm_collect_frame_entity_nodes, fec_env);
250         be_assign_entities(fec_env, arm_set_frame_entity, at_begin);
251         be_free_frame_entity_coalescer(fec_env);
252
253         irg_block_walk_graph(irg, NULL, arm_after_ra_walker, NULL);
254
255         /* fix stack entity offsets */
256         be_abi_fix_stack_nodes(irg);
257         be_abi_fix_stack_bias(irg);
258
259         /* do peephole optimizations and fix stack offsets */
260         arm_peephole_optimization(irg);
261 }
262
263 static void arm_before_ra(ir_graph *irg)
264 {
265         be_sched_fix_flags(irg, &arm_reg_classes[CLASS_arm_flags], NULL, NULL);
266 }
267
268 /**
269  * Maps all intrinsic calls that the backend support
270  * and map all instructions the backend did not support
271  * to runtime calls.
272  */
273 static void arm_handle_intrinsics(void)
274 {
275         ir_type *tp, *int_tp, *uint_tp;
276         i_record records[8];
277         int n_records = 0;
278
279         runtime_rt rt_iDiv, rt_uDiv, rt_iMod, rt_uMod;
280
281 #define ID(x) new_id_from_chars(x, sizeof(x)-1)
282
283         int_tp  = get_type_for_mode(mode_Is);
284         uint_tp = get_type_for_mode(mode_Iu);
285
286         /* ARM has neither a signed div instruction ... */
287         {
288                 i_instr_record *map_Div = &records[n_records++].i_instr;
289
290                 tp = new_type_method(2, 1);
291                 set_method_param_type(tp, 0, int_tp);
292                 set_method_param_type(tp, 1, int_tp);
293                 set_method_res_type(tp, 0, int_tp);
294
295                 rt_iDiv.ent             = new_entity(get_glob_type(), ID("__divsi3"), tp);
296                 set_entity_ld_ident(rt_iDiv.ent, ID("__divsi3"));
297                 rt_iDiv.mode            = mode_T;
298                 rt_iDiv.res_mode        = mode_Is;
299                 rt_iDiv.mem_proj_nr     = pn_Div_M;
300                 rt_iDiv.regular_proj_nr = pn_Div_X_regular;
301                 rt_iDiv.exc_proj_nr     = pn_Div_X_except;
302                 rt_iDiv.res_proj_nr     = pn_Div_res;
303
304                 add_entity_linkage(rt_iDiv.ent, IR_LINKAGE_CONSTANT);
305                 set_entity_visibility(rt_iDiv.ent, ir_visibility_external);
306
307                 map_Div->kind     = INTRINSIC_INSTR;
308                 map_Div->op       = op_Div;
309                 map_Div->i_mapper = (i_mapper_func)i_mapper_RuntimeCall;
310                 map_Div->ctx      = &rt_iDiv;
311         }
312         /* ... nor an unsigned div instruction ... */
313         {
314                 i_instr_record *map_Div = &records[n_records++].i_instr;
315
316                 tp = new_type_method(2, 1);
317                 set_method_param_type(tp, 0, uint_tp);
318                 set_method_param_type(tp, 1, uint_tp);
319                 set_method_res_type(tp, 0, uint_tp);
320
321                 rt_uDiv.ent             = new_entity(get_glob_type(), ID("__udivsi3"), tp);
322                 set_entity_ld_ident(rt_uDiv.ent, ID("__udivsi3"));
323                 rt_uDiv.mode            = mode_T;
324                 rt_uDiv.res_mode        = mode_Iu;
325                 rt_uDiv.mem_proj_nr     = pn_Div_M;
326                 rt_uDiv.regular_proj_nr = pn_Div_X_regular;
327                 rt_uDiv.exc_proj_nr     = pn_Div_X_except;
328                 rt_uDiv.res_proj_nr     = pn_Div_res;
329
330                 set_entity_visibility(rt_uDiv.ent, ir_visibility_external);
331
332                 map_Div->kind     = INTRINSIC_INSTR;
333                 map_Div->op       = op_Div;
334                 map_Div->i_mapper = (i_mapper_func)i_mapper_RuntimeCall;
335                 map_Div->ctx      = &rt_uDiv;
336         }
337         /* ... nor a signed mod instruction ... */
338         {
339                 i_instr_record *map_Mod = &records[n_records++].i_instr;
340
341                 tp = new_type_method(2, 1);
342                 set_method_param_type(tp, 0, int_tp);
343                 set_method_param_type(tp, 1, int_tp);
344                 set_method_res_type(tp, 0, int_tp);
345
346                 rt_iMod.ent             = new_entity(get_glob_type(), ID("__modsi3"), tp);
347                 set_entity_ld_ident(rt_iMod.ent, ID("__modsi3"));
348                 rt_iMod.mode            = mode_T;
349                 rt_iMod.res_mode        = mode_Is;
350                 rt_iMod.mem_proj_nr     = pn_Mod_M;
351                 rt_iMod.regular_proj_nr = pn_Mod_X_regular;
352                 rt_iMod.exc_proj_nr     = pn_Mod_X_except;
353                 rt_iMod.res_proj_nr     = pn_Mod_res;
354
355                 set_entity_visibility(rt_iMod.ent, ir_visibility_external);
356
357                 map_Mod->kind     = INTRINSIC_INSTR;
358                 map_Mod->op       = op_Mod;
359                 map_Mod->i_mapper = (i_mapper_func)i_mapper_RuntimeCall;
360                 map_Mod->ctx      = &rt_iMod;
361         }
362         /* ... nor an unsigned mod. */
363         {
364                 i_instr_record *map_Mod = &records[n_records++].i_instr;
365
366                 tp = new_type_method(2, 1);
367                 set_method_param_type(tp, 0, uint_tp);
368                 set_method_param_type(tp, 1, uint_tp);
369                 set_method_res_type(tp, 0, uint_tp);
370
371                 rt_uMod.ent             = new_entity(get_glob_type(), ID("__umodsi3"), tp);
372                 set_entity_ld_ident(rt_uMod.ent, ID("__umodsi3"));
373                 rt_uMod.mode            = mode_T;
374                 rt_uMod.res_mode        = mode_Iu;
375                 rt_uMod.mem_proj_nr     = pn_Mod_M;
376                 rt_uMod.regular_proj_nr = pn_Mod_X_regular;
377                 rt_uMod.exc_proj_nr     = pn_Mod_X_except;
378                 rt_uMod.res_proj_nr     = pn_Mod_res;
379
380                 set_entity_visibility(rt_uMod.ent, ir_visibility_external);
381
382                 map_Mod->kind     = INTRINSIC_INSTR;
383                 map_Mod->op       = op_Mod;
384                 map_Mod->i_mapper = (i_mapper_func)i_mapper_RuntimeCall;
385                 map_Mod->ctx      = &rt_uMod;
386         }
387
388         if (n_records > 0)
389                 lower_intrinsics(records, n_records, /*part_block_used=*/0);
390 }
391
392 extern const arch_isa_if_t arm_isa_if;
393 static arm_isa_t arm_isa_template = {
394         {
395                 &arm_isa_if,             /* isa interface */
396                 N_ARM_REGISTERS,
397                 arm_registers,
398                 N_ARM_CLASSES,
399                 arm_reg_classes,
400                 &arm_registers[REG_SP],  /* stack pointer */
401                 &arm_registers[REG_R11], /* base pointer */
402                 2,                       /* power of two stack alignment for calls, 2^2 == 4 */
403                 7,                       /* spill costs */
404                 5,                       /* reload costs */
405                 true,                    /* we do have custom abi handling */
406         },
407         ARM_FPU_ARCH_FPE,          /* FPU architecture */
408 };
409
410 static void arm_init(void)
411 {
412         arm_register_init();
413
414         arm_create_opcodes(&arm_irn_ops);
415 }
416
417 static void arm_finish(void)
418 {
419         arm_free_opcodes();
420 }
421
422 static arch_env_t *arm_begin_codegeneration(void)
423 {
424         arm_isa_t *isa = XMALLOC(arm_isa_t);
425         *isa = arm_isa_template;
426
427         be_gas_emit_types = false;
428
429         return &isa->base;
430 }
431
432 /**
433  * Closes the output file and frees the ISA structure.
434  */
435 static void arm_end_codegeneration(void *self)
436 {
437         free(self);
438 }
439
440 /**
441  * Allows or disallows the creation of Psi nodes for the given Phi nodes.
442  * @return 1 if allowed, 0 otherwise
443  */
444 static int arm_is_mux_allowed(ir_node *sel, ir_node *mux_false,
445                               ir_node *mux_true)
446 {
447         (void) sel;
448         (void) mux_false;
449         (void) mux_true;
450         return false;
451 }
452
453 static asm_constraint_flags_t arm_parse_asm_constraint(const char **c)
454 {
455         /* asm not supported */
456         (void) c;
457         return ASM_CONSTRAINT_FLAG_INVALID;
458 }
459
460 static int arm_is_valid_clobber(const char *clobber)
461 {
462         (void) clobber;
463         return 0;
464 }
465
466 static void arm_lower_for_target(void)
467 {
468         ir_mode *mode_gp = arm_reg_classes[CLASS_arm_gp].mode;
469         size_t i, n_irgs = get_irp_n_irgs();
470
471         /* lower compound param handling */
472         lower_calls_with_compounds(LF_RETURN_HIDDEN);
473
474         for (i = 0; i < n_irgs; ++i) {
475                 ir_graph *irg = get_irp_irg(i);
476                 lower_switch(irg, 4, 256, mode_gp);
477         }
478
479         for (i = 0; i < n_irgs; ++i) {
480                 ir_graph *irg = get_irp_irg(i);
481                 /* Turn all small CopyBs into loads/stores and all bigger CopyBs into
482                  * memcpy calls.
483                  * TODO:  These constants need arm-specific tuning. */
484                 lower_CopyB(irg, 31, 32, false);
485         }
486 }
487
488 /**
489  * Returns the libFirm configuration parameter for this backend.
490  */
491 static const backend_params *arm_get_libfirm_params(void)
492 {
493         static ir_settings_arch_dep_t ad = {
494                 1,    /* allow subs */
495                 1,    /* Muls are fast enough on ARM but ... */
496                 31,   /* ... one shift would be possible better */
497                 NULL, /* no evaluator function */
498                 0,    /* SMUL is needed, only in Arch M */
499                 0,    /* UMUL is needed, only in Arch M */
500                 32,   /* SMUL & UMUL available for 32 bit */
501         };
502         static backend_params p = {
503                 0,     /* don't support inline assembler yet */
504                 1,     /* support Rotl nodes */
505                 1,     /* big endian */
506                 1,     /* modulo shift efficient */
507                 0,     /* non-modulo shift not efficient */
508                 &ad,   /* will be set later */
509                 arm_is_mux_allowed, /* allow_ifconv function */
510                 32,    /* machine size */
511                 NULL,  /* float arithmetic mode (TODO) */
512                 NULL,  /* long long type */
513                 NULL,  /* unsigned long long type */
514                 NULL,  /* long double type */
515                 0,     /* no trampoline support: size 0 */
516                 0,     /* no trampoline support: align 0 */
517                 NULL,  /* no trampoline support: no trampoline builder */
518                 4      /* alignment of stack parameter */
519         };
520
521         return &p;
522 }
523
524 /* fpu set architectures. */
525 static const lc_opt_enum_int_items_t arm_fpu_items[] = {
526         { "softfloat", ARM_FPU_ARCH_SOFTFLOAT },
527         { "fpe",       ARM_FPU_ARCH_FPE },
528         { "fpa",       ARM_FPU_ARCH_FPA },
529         { "vfp1xd",    ARM_FPU_ARCH_VFP_V1xD },
530         { "vfp1",      ARM_FPU_ARCH_VFP_V1 },
531         { "vfp2",      ARM_FPU_ARCH_VFP_V2 },
532         { NULL,        0 }
533 };
534
535 static lc_opt_enum_int_var_t arch_fpu_var = {
536         &arm_isa_template.fpu_arch, arm_fpu_items
537 };
538
539 static const lc_opt_table_entry_t arm_options[] = {
540         LC_OPT_ENT_ENUM_INT("fpunit",    "select the floating point unit", &arch_fpu_var),
541         LC_OPT_LAST
542 };
543
544 const arch_isa_if_t arm_isa_if = {
545         arm_init,
546         arm_finish,
547         arm_get_libfirm_params,
548         arm_lower_for_target,
549         arm_parse_asm_constraint,
550         arm_is_valid_clobber,
551
552         arm_begin_codegeneration,
553         arm_end_codegeneration,
554         NULL,
555         NULL,  /* get call abi */
556         NULL,  /* mark remat */
557         NULL,  /* get_pic_base */
558         be_new_spill,
559         be_new_reload,
560         NULL,  /* register_saved_by */
561
562         arm_handle_intrinsics, /* handle_intrinsics */
563         NULL,  /* before_abi */
564         arm_prepare_graph,
565         arm_before_ra,
566         arm_finish_irg,
567         arm_gen_routine,
568 };
569
570 BE_REGISTER_MODULE_CONSTRUCTOR(be_init_arch_arm)
571 void be_init_arch_arm(void)
572 {
573         lc_opt_entry_t *be_grp = lc_opt_get_grp(firm_opt_get_root(), "be");
574         lc_opt_entry_t *arm_grp = lc_opt_get_grp(be_grp, "arm");
575
576         lc_opt_add_table(arm_grp, arm_options);
577
578         be_register_isa_if("arm", &arm_isa_if);
579
580         arm_init_transform();
581         arm_init_emitter();
582 }