X-Git-Url: http://nsz.repo.hu/git/?a=blobdiff_plain;f=ir%2Fbe%2Fia32%2Fbearch_ia32.c;h=9a2f9df993664acbd61bfdc2cbefdbd61be931e9;hb=fc81b817119d8635eaeb345c8623255fc51bdb22;hp=9e760c6e2dc4b4422bfb78a09c4f4211cc90be47;hpb=438580abed840c55e82a03b47daeacfe2da8040f;p=libfirm diff --git a/ir/be/ia32/bearch_ia32.c b/ir/be/ia32/bearch_ia32.c index 9e760c6e2..9a2f9df99 100644 --- a/ir/be/ia32/bearch_ia32.c +++ b/ir/be/ia32/bearch_ia32.c @@ -51,6 +51,7 @@ #include "iroptimize.h" #include "instrument.h" #include "iropt_t.h" +#include "lower_dw.h" #include "../beabi.h" #include "../beirg.h" @@ -93,9 +94,7 @@ transformer_t be_transformer = TRANSFORMER_DEFAULT; #endif -DEBUG_ONLY(static firm_dbg_module_t *dbg = NULL;) - -ir_mode *ia32_mode_fpcw = NULL; +ir_mode *ia32_mode_fpcw = NULL; /** The current omit-fp state */ static ir_type *omit_fp_between_type = NULL; @@ -117,7 +116,7 @@ static ia32_intrinsic_env_t intrinsic_env = { }; -typedef ir_node *(*create_const_node_func) (dbg_info *dbg, ir_node *block); +typedef ir_node *(*create_const_node_func) (dbg_info *dbgi, ir_node *block); /** * Used to create per-graph unique pseudo nodes. @@ -395,7 +394,7 @@ static arch_inverse_t *ia32_get_inverse(const ir_node *irn, int i, arch_inverse_ ir_mode *mode; ir_mode *irn_mode; ir_node *block, *noreg, *nomem; - dbg_info *dbg; + dbg_info *dbgi; /* we cannot invert non-ia32 irns */ if (! is_ia32_irn(irn)) @@ -419,7 +418,7 @@ static arch_inverse_t *ia32_get_inverse(const ir_node *irn, int i, arch_inverse_ irn_mode = get_irn_mode(irn); noreg = get_irn_n(irn, 0); nomem = get_irg_no_mem(irg); - dbg = get_irn_dbg_info(irn); + dbgi = get_irn_dbg_info(irn); /* initialize structure */ inverse->nodes = obstack_alloc(obst, 2 * sizeof(inverse->nodes[0])); @@ -431,7 +430,7 @@ static arch_inverse_t *ia32_get_inverse(const ir_node *irn, int i, arch_inverse_ if (get_ia32_immop_type(irn) == ia32_ImmConst) { /* we have an add with a const here */ /* invers == add with negated const */ - inverse->nodes[0] = new_bd_ia32_Add(dbg, block, noreg, noreg, nomem, get_irn_n(irn, i), noreg); + inverse->nodes[0] = new_bd_ia32_Add(dbgi, block, noreg, noreg, nomem, get_irn_n(irn, i), noreg); inverse->costs += 1; copy_ia32_Immop_attr(inverse->nodes[0], (ir_node *)irn); set_ia32_Immop_tarval(inverse->nodes[0], tarval_neg(get_ia32_Immop_tarval(irn))); @@ -440,13 +439,13 @@ static arch_inverse_t *ia32_get_inverse(const ir_node *irn, int i, arch_inverse_ else if (get_ia32_immop_type(irn) == ia32_ImmSymConst) { /* we have an add with a symconst here */ /* invers == sub with const */ - inverse->nodes[0] = new_bd_ia32_Sub(dbg, block, noreg, noreg, nomem, get_irn_n(irn, i), noreg); + inverse->nodes[0] = new_bd_ia32_Sub(dbgi, block, noreg, noreg, nomem, get_irn_n(irn, i), noreg); inverse->costs += 2; copy_ia32_Immop_attr(inverse->nodes[0], (ir_node *)irn); } else { /* normal add: inverse == sub */ - inverse->nodes[0] = new_bd_ia32_Sub(dbg, block, noreg, noreg, nomem, (ir_node*) irn, get_irn_n(irn, i ^ 1)); + inverse->nodes[0] = new_bd_ia32_Sub(dbgi, block, noreg, noreg, nomem, (ir_node*) irn, get_irn_n(irn, i ^ 1)); inverse->costs += 2; } break; @@ -454,17 +453,17 @@ static arch_inverse_t *ia32_get_inverse(const ir_node *irn, int i, arch_inverse_ if (get_ia32_immop_type(irn) != ia32_ImmNone) { /* we have a sub with a const/symconst here */ /* invers == add with this const */ - inverse->nodes[0] = new_bd_ia32_Add(dbg, block, noreg, noreg, nomem, get_irn_n(irn, i), noreg); + inverse->nodes[0] = new_bd_ia32_Add(dbgi, block, noreg, noreg, nomem, get_irn_n(irn, i), noreg); inverse->costs += (get_ia32_immop_type(irn) == ia32_ImmSymConst) ? 5 : 1; copy_ia32_Immop_attr(inverse->nodes[0], (ir_node *)irn); } else { /* normal sub */ if (i == n_ia32_binary_left) { - inverse->nodes[0] = new_bd_ia32_Add(dbg, block, noreg, noreg, nomem, (ir_node*) irn, get_irn_n(irn, 3)); + inverse->nodes[0] = new_bd_ia32_Add(dbgi, block, noreg, noreg, nomem, (ir_node*) irn, get_irn_n(irn, 3)); } else { - inverse->nodes[0] = new_bd_ia32_Sub(dbg, block, noreg, noreg, nomem, get_irn_n(irn, n_ia32_binary_left), (ir_node*) irn); + inverse->nodes[0] = new_bd_ia32_Sub(dbgi, block, noreg, noreg, nomem, get_irn_n(irn, n_ia32_binary_left), (ir_node*) irn); } inverse->costs += 1; } @@ -472,23 +471,23 @@ static arch_inverse_t *ia32_get_inverse(const ir_node *irn, int i, arch_inverse_ case iro_ia32_Xor: if (get_ia32_immop_type(irn) != ia32_ImmNone) { /* xor with const: inverse = xor */ - inverse->nodes[0] = new_bd_ia32_Xor(dbg, block, noreg, noreg, nomem, get_irn_n(irn, i), noreg); + inverse->nodes[0] = new_bd_ia32_Xor(dbgi, block, noreg, noreg, nomem, get_irn_n(irn, i), noreg); inverse->costs += (get_ia32_immop_type(irn) == ia32_ImmSymConst) ? 5 : 1; copy_ia32_Immop_attr(inverse->nodes[0], (ir_node *)irn); } else { /* normal xor */ - inverse->nodes[0] = new_bd_ia32_Xor(dbg, block, noreg, noreg, nomem, (ir_node *) irn, get_irn_n(irn, i)); + inverse->nodes[0] = new_bd_ia32_Xor(dbgi, block, noreg, noreg, nomem, (ir_node *) irn, get_irn_n(irn, i)); inverse->costs += 1; } break; case iro_ia32_Not: { - inverse->nodes[0] = new_bd_ia32_Not(dbg, block, (ir_node*) irn); + inverse->nodes[0] = new_bd_ia32_Not(dbgi, block, (ir_node*) irn); inverse->costs += 1; break; } case iro_ia32_Neg: { - inverse->nodes[0] = new_bd_ia32_Neg(dbg, block, (ir_node*) irn); + inverse->nodes[0] = new_bd_ia32_Neg(dbgi, block, (ir_node*) irn); inverse->costs += 1; break; } @@ -708,11 +707,11 @@ ir_node *ia32_turn_back_am(ir_node *node) ir_graph *irg = get_irn_irg(node); ir_node *block = get_nodes_block(node); ir_node *base = get_irn_n(node, n_ia32_base); - ir_node *index = get_irn_n(node, n_ia32_index); + ir_node *idx = get_irn_n(node, n_ia32_index); ir_node *mem = get_irn_n(node, n_ia32_mem); ir_node *noreg; - ir_node *load = new_bd_ia32_Load(dbgi, block, base, index, mem); + ir_node *load = new_bd_ia32_Load(dbgi, block, base, idx, mem); ir_node *load_res = new_rd_Proj(dbgi, load, mode_Iu, pn_ia32_Load_res); ia32_copy_am_attrs(load, node); @@ -786,7 +785,6 @@ static ir_node *flags_remat(ir_node *node, ir_node *after) case ia32_AddrModeD: /* TODO implement this later... */ panic("found DestAM with flag user %+F this should not happen", node); - break; default: assert(type == ia32_Normal); break; } @@ -820,7 +818,7 @@ static void ia32_before_ra(ir_graph *irg) static void transform_to_Load(ir_node *node) { ir_graph *irg = get_irn_irg(node); - dbg_info *dbg = get_irn_dbg_info(node); + dbg_info *dbgi = get_irn_dbg_info(node); ir_node *block = get_nodes_block(node); ir_entity *ent = be_get_frame_entity(node); ir_mode *mode = get_irn_mode(node); @@ -838,16 +836,16 @@ static void transform_to_Load(ir_node *node) if (mode_is_float(spillmode)) { if (ia32_cg_config.use_sse2) - new_op = new_bd_ia32_xLoad(dbg, block, ptr, noreg, mem, spillmode); + new_op = new_bd_ia32_xLoad(dbgi, block, ptr, noreg, mem, spillmode); else - new_op = new_bd_ia32_vfld(dbg, block, ptr, noreg, mem, spillmode); + new_op = new_bd_ia32_vfld(dbgi, block, ptr, noreg, mem, spillmode); } else if (get_mode_size_bits(spillmode) == 128) { /* Reload 128 bit SSE registers */ - new_op = new_bd_ia32_xxLoad(dbg, block, ptr, noreg, mem); + new_op = new_bd_ia32_xxLoad(dbgi, block, ptr, noreg, mem); } else - new_op = new_bd_ia32_Load(dbg, block, ptr, noreg, mem); + new_op = new_bd_ia32_Load(dbgi, block, ptr, noreg, mem); set_ia32_op_type(new_op, ia32_AddrModeS); set_ia32_ls_mode(new_op, spillmode); @@ -857,7 +855,7 @@ static void transform_to_Load(ir_node *node) DBG_OPT_RELOAD2LD(node, new_op); - proj = new_rd_Proj(dbg, new_op, mode, pn_ia32_Load_res); + proj = new_rd_Proj(dbgi, new_op, mode, pn_ia32_Load_res); if (sched_point) { sched_add_after(sched_point, new_op); @@ -879,7 +877,7 @@ static void transform_to_Load(ir_node *node) static void transform_to_Store(ir_node *node) { ir_graph *irg = get_irn_irg(node); - dbg_info *dbg = get_irn_dbg_info(node); + dbg_info *dbgi = get_irn_dbg_info(node); ir_node *block = get_nodes_block(node); ir_entity *ent = be_get_frame_entity(node); const ir_node *spillval = get_irn_n(node, n_be_Spill_val); @@ -888,6 +886,7 @@ static void transform_to_Store(ir_node *node) ir_node *nomem = get_irg_no_mem(irg); ir_node *ptr = get_irg_frame(irg); ir_node *val = get_irn_n(node, n_be_Spill_val); + ir_node *res; ir_node *store; ir_node *sched_point = NULL; @@ -896,17 +895,23 @@ static void transform_to_Store(ir_node *node) } if (mode_is_float(mode)) { - if (ia32_cg_config.use_sse2) - store = new_bd_ia32_xStore(dbg, block, ptr, noreg, nomem, val); - else - store = new_bd_ia32_vfst(dbg, block, ptr, noreg, nomem, val, mode); + if (ia32_cg_config.use_sse2) { + store = new_bd_ia32_xStore(dbgi, block, ptr, noreg, nomem, val); + res = new_r_Proj(store, mode_M, pn_ia32_xStore_M); + } else { + store = new_bd_ia32_vfst(dbgi, block, ptr, noreg, nomem, val, mode); + res = new_r_Proj(store, mode_M, pn_ia32_vfst_M); + } } else if (get_mode_size_bits(mode) == 128) { /* Spill 128 bit SSE registers */ - store = new_bd_ia32_xxStore(dbg, block, ptr, noreg, nomem, val); + store = new_bd_ia32_xxStore(dbgi, block, ptr, noreg, nomem, val); + res = new_r_Proj(store, mode_M, pn_ia32_xxStore_M); } else if (get_mode_size_bits(mode) == 8) { - store = new_bd_ia32_Store8Bit(dbg, block, ptr, noreg, nomem, val); + store = new_bd_ia32_Store8Bit(dbgi, block, ptr, noreg, nomem, val); + res = new_r_Proj(store, mode_M, pn_ia32_Store8Bit_M); } else { - store = new_bd_ia32_Store(dbg, block, ptr, noreg, nomem, val); + store = new_bd_ia32_Store(dbgi, block, ptr, noreg, nomem, val); + res = new_r_Proj(store, mode_M, pn_ia32_Store_M); } set_ia32_op_type(store, ia32_AddrModeD); @@ -922,18 +927,18 @@ static void transform_to_Store(ir_node *node) sched_remove(node); } - exchange(node, store); + exchange(node, res); } static ir_node *create_push(ir_node *node, ir_node *schedpoint, ir_node *sp, ir_node *mem, ir_entity *ent) { - dbg_info *dbg = get_irn_dbg_info(node); - ir_node *block = get_nodes_block(node); - ir_graph *irg = get_irn_irg(node); - ir_node *noreg = ia32_new_NoReg_gp(irg); - ir_node *frame = get_irg_frame(irg); + dbg_info *dbgi = get_irn_dbg_info(node); + ir_node *block = get_nodes_block(node); + ir_graph *irg = get_irn_irg(node); + ir_node *noreg = ia32_new_NoReg_gp(irg); + ir_node *frame = get_irg_frame(irg); - ir_node *push = new_bd_ia32_Push(dbg, block, frame, noreg, mem, noreg, sp); + ir_node *push = new_bd_ia32_Push(dbgi, block, frame, noreg, mem, noreg, sp); set_ia32_frame_ent(push, ent); set_ia32_use_frame(push); @@ -947,13 +952,13 @@ static ir_node *create_push(ir_node *node, ir_node *schedpoint, ir_node *sp, ir_ static ir_node *create_pop(ir_node *node, ir_node *schedpoint, ir_node *sp, ir_entity *ent) { - dbg_info *dbg = get_irn_dbg_info(node); + dbg_info *dbgi = get_irn_dbg_info(node); ir_node *block = get_nodes_block(node); ir_graph *irg = get_irn_irg(node); ir_node *noreg = ia32_new_NoReg_gp(irg); ir_node *frame = get_irg_frame(irg); - ir_node *pop = new_bd_ia32_PopMem(dbg, block, frame, noreg, + ir_node *pop = new_bd_ia32_PopMem(dbgi, block, frame, noreg, get_irg_no_mem(irg), sp); set_ia32_frame_ent(pop, ent); @@ -969,12 +974,12 @@ static ir_node *create_pop(ir_node *node, ir_node *schedpoint, ir_node *sp, ir_e static ir_node* create_spproj(ir_node *node, ir_node *pred, int pos) { - dbg_info *dbg = get_irn_dbg_info(node); - ir_mode *spmode = mode_Iu; + dbg_info *dbgi = get_irn_dbg_info(node); + ir_mode *spmode = mode_Iu; const arch_register_t *spreg = &ia32_registers[REG_ESP]; ir_node *sp; - sp = new_rd_Proj(dbg, pred, spmode, pos); + sp = new_rd_Proj(dbgi, pred, spmode, pos); arch_set_irn_register(sp, spreg); return sp; @@ -1654,8 +1659,6 @@ static const arch_register_t *ia32_get_RegParam_reg(unsigned cc, unsigned nr, static void ia32_get_call_abi(const void *self, ir_type *method_type, be_abi_call_t *abi) { - ir_type *tp; - ir_mode *mode; unsigned cc; int n, i, regnum; int pop_amount = 0; @@ -1693,11 +1696,10 @@ static void ia32_get_call_abi(const void *self, ir_type *method_type, n = get_method_n_params(method_type); for (i = regnum = 0; i < n; i++) { - ir_mode *mode; - const arch_register_t *reg = NULL; + const arch_register_t *reg = NULL; + ir_type *tp = get_method_param_type(method_type, i); + ir_mode *mode = get_type_mode(tp); - tp = get_method_param_type(method_type, i); - mode = get_type_mode(tp); if (mode != NULL) { reg = ia32_get_RegParam_reg(cc, regnum, mode); } @@ -1732,8 +1734,8 @@ static void ia32_get_call_abi(const void *self, ir_type *method_type, /* In case of 64bit returns, we will have two 32bit values */ if (n == 2) { - tp = get_method_res_type(method_type, 0); - mode = get_type_mode(tp); + ir_type *tp = get_method_res_type(method_type, 0); + ir_mode *mode = get_type_mode(tp); assert(!mode_is_float(mode) && "two FP results not supported"); @@ -1746,11 +1748,10 @@ static void ia32_get_call_abi(const void *self, ir_type *method_type, be_abi_call_res_reg(abi, 1, &ia32_registers[REG_EDX], ABI_CONTEXT_BOTH); } else if (n == 1) { + ir_type *tp = get_method_res_type(method_type, 0); + ir_mode *mode = get_type_mode(tp); const arch_register_t *reg; - - tp = get_method_res_type(method_type, 0); assert(is_atomic_type(tp)); - mode = get_type_mode(tp); reg = mode_is_float(mode) ? &ia32_registers[REG_VF0] : &ia32_registers[REG_EAX]; @@ -1951,7 +1952,7 @@ static int ia32_is_mux_allowed(ir_node *sel, ir_node *mux_false, if (get_mode_size_bits(mode) > 32) return false; /* we can handle Abs for all modes and compares (except 64bit) */ - if (be_mux_is_abs(sel, mux_true, mux_false) != 0) + if (ir_mux_is_abs(sel, mux_true, mux_false) != 0) return true; /* we can't handle MuxF yet */ if (mode_is_float(mode)) @@ -2030,14 +2031,15 @@ static void ia32_lower_for_target(void) /* lower compound param handling */ lower_calls_with_compounds(¶ms); - lower_dw_ops(&lower_dw_params); + ir_prepare_dw_lowering(&lower_dw_params); + ir_lower_dw_ops(); for (i = 0; i < n_irgs; ++i) { ir_graph *irg = get_irp_irg(i); /* lower for mode_b stuff */ ir_lower_mode_b(irg, &lower_mode_b_config); /* break up switches with wide ranges */ - lower_switch(irg, 256, true); + lower_switch(irg, 4, 256, false); } } @@ -2109,6 +2111,46 @@ static const backend_params *ia32_get_libfirm_params(void) return &p; } +/** + * Check if the given register is callee or caller save. + */ +static int ia32_register_saved_by(const arch_register_t *reg, int callee) +{ + if (callee) { + /* check for callee saved */ + if (reg->reg_class == &ia32_reg_classes[CLASS_ia32_gp]) { + switch (reg->index) { + case REG_GP_EBX: + case REG_GP_ESI: + case REG_GP_EDI: + case REG_GP_EBP: + return 1; + default: + return 0; + } + } + } else { + /* check for caller saved */ + if (reg->reg_class == &ia32_reg_classes[CLASS_ia32_gp]) { + switch (reg->index) { + case REG_GP_EDX: + case REG_GP_ECX: + case REG_GP_EAX: + return 1; + default: + return 0; + } + } else if (reg->reg_class == &ia32_reg_classes[CLASS_ia32_xmm]) { + /* all XMM registers are caller save */ + return reg->index != REG_XMM_NOREG; + } else if (reg->reg_class == &ia32_reg_classes[CLASS_ia32_vfp]) { + /* all VFP registers are caller save */ + return reg->index != REG_VFP_NOREG; + } + } + return 0; +} + static const lc_opt_enum_int_items_t gas_items[] = { { "elf", OBJECT_FILE_FORMAT_ELF }, { "mingw", OBJECT_FILE_FORMAT_COFF }, @@ -2166,6 +2208,7 @@ const arch_isa_if_t ia32_isa_if = { ia32_after_ra, /* after register allocation hook */ ia32_finish, /* called before codegen */ ia32_emit, /* emit && done */ + ia32_register_saved_by, }; BE_REGISTER_MODULE_CONSTRUCTOR(be_init_arch_ia32) @@ -2177,8 +2220,6 @@ void be_init_arch_ia32(void) lc_opt_add_table(ia32_grp, ia32_options); be_register_isa_if("ia32", &ia32_isa_if); - FIRM_DBG_REGISTER(dbg, "firm.be.ia32.cg"); - ia32_init_emitter(); ia32_init_finish(); ia32_init_optimize();