X-Git-Url: http://nsz.repo.hu/git/?a=blobdiff_plain;f=ir%2Fbe%2Fia32%2Fbearch_ia32.c;h=5b97324fe2aa5824d4b568b6a2e8b061f9956b69;hb=bd31a5350ce9e110c058b4ad2223d460c9eb5c4e;hp=8aef2c70a9b774ffcf4fe2b65720547cec809386;hpb=13f415de8399c17e4297eacf3c4003a54ff23dfc;p=libfirm diff --git a/ir/be/ia32/bearch_ia32.c b/ir/be/ia32/bearch_ia32.c index 8aef2c70a..5b97324fe 100644 --- a/ir/be/ia32/bearch_ia32.c +++ b/ir/be/ia32/bearch_ia32.c @@ -91,6 +91,24 @@ static set *cur_reg_set = NULL; ir_mode *mode_fpcw = NULL; ia32_code_gen_t *ia32_current_cg = NULL; +/** + * The environment for the intrinsic mapping. + */ +static ia32_intrinsic_env_t intrinsic_env = { + NULL, /* the isa */ + NULL, /* the irg, these entities belong to */ + NULL, /* entity for first div operand (move into FPU) */ + NULL, /* entity for second div operand (move into FPU) */ + NULL, /* entity for converts ll -> d */ + NULL, /* entity for converts d -> ll */ + NULL, /* entity for __divdi3 library call */ + NULL, /* entity for __moddi3 library call */ + NULL, /* entity for __udivdi3 library call */ + NULL, /* entity for __umoddi3 library call */ + NULL, /* bias value for conversion from float to unsigned 64 */ +}; + + typedef ir_node *(*create_const_node_func) (dbg_info *dbg, ir_graph *irg, ir_node *block); static INLINE ir_node *create_const(ia32_code_gen_t *cg, ir_node **place, @@ -476,31 +494,37 @@ static void ia32_abi_epilogue(void *self, ir_node *bl, ir_node **mem, pmap *reg_ } else { const ia32_isa_t *isa = (ia32_isa_t *)env->isa; ia32_code_gen_t *cg = isa->cg; - ir_mode *mode_bp = env->isa->bp->reg_class->mode; + ir_mode *mode_bp = env->isa->bp->reg_class->mode; + ir_graph *irg = current_ir_graph; - /* gcc always emits a leave at the end of a routine */ - if (1 || ARCH_AMD(isa->opt_arch)) { + if (ARCH_AMD(isa->opt_arch)) { ir_node *leave; /* leave */ - leave = new_rd_ia32_Leave(NULL, env->irg, bl, curr_sp, curr_bp); + leave = new_rd_ia32_Leave(NULL, irg, bl, curr_sp, curr_bp); set_ia32_flags(leave, arch_irn_flags_ignore); - curr_bp = new_r_Proj(current_ir_graph, bl, leave, mode_bp, pn_ia32_Leave_frame); - curr_sp = new_r_Proj(current_ir_graph, bl, leave, get_irn_mode(curr_sp), pn_ia32_Leave_stack); + curr_bp = new_r_Proj(irg, bl, leave, mode_bp, pn_ia32_Leave_frame); + curr_sp = new_r_Proj(irg, bl, leave, get_irn_mode(curr_sp), pn_ia32_Leave_stack); } else { ir_node *noreg = ia32_new_NoReg_gp(cg); ir_node *pop; + /* the old SP is not needed anymore (kill the proj) */ + assert(is_Proj(curr_sp)); + be_kill_node(curr_sp); + /* copy ebp to esp */ - curr_sp = be_new_SetSP(env->isa->sp, env->irg, bl, curr_sp, curr_bp, *mem); + curr_sp = be_new_Copy(&ia32_reg_classes[CLASS_ia32_gp], irg, bl, curr_bp); + arch_set_irn_register(env->aenv, curr_sp, env->isa->sp); + be_node_set_flags(curr_sp, BE_OUT_POS(0), arch_irn_flags_ignore); /* pop ebp */ pop = new_rd_ia32_Pop(NULL, env->irg, bl, noreg, noreg, *mem, curr_sp); set_ia32_flags(pop, arch_irn_flags_ignore); - curr_bp = new_r_Proj(current_ir_graph, bl, pop, mode_bp, pn_ia32_Pop_res); - curr_sp = new_r_Proj(current_ir_graph, bl, pop, get_irn_mode(curr_sp), pn_ia32_Pop_stack); + curr_bp = new_r_Proj(irg, bl, pop, mode_bp, pn_ia32_Pop_res); + curr_sp = new_r_Proj(irg, bl, pop, get_irn_mode(curr_sp), pn_ia32_Pop_stack); - *mem = new_r_Proj(current_ir_graph, bl, pop, mode_M, pn_ia32_Pop_M); + *mem = new_r_Proj(irg, bl, pop, mode_M, pn_ia32_Pop_M); } arch_set_irn_register(env->aenv, curr_sp, env->isa->sp); arch_set_irn_register(env->aenv, curr_bp, env->isa->bp); @@ -899,6 +923,14 @@ ia32_irn_ops_t ia32_irn_ops = { * |___/ **************************************************/ +static void ia32_before_abi(void *self) { + ia32_code_gen_t *cg = self; + + ir_lower_mode_b(cg->irg, mode_Iu, 0); + if(cg->dump) + be_dump(cg->irg, "-lower_modeb", dump_ir_block_graph_sched); +} + /** * Transforms the standard firm graph into * an ia32 firm graph @@ -906,11 +938,19 @@ ia32_irn_ops_t ia32_irn_ops = { static void ia32_prepare_graph(void *self) { ia32_code_gen_t *cg = self; - ir_lower_mode_b(cg->irg, mode_Iu, 0); /* do local optimisations */ optimize_graph_df(cg->irg); + + /* TODO: we often have dead code reachable through out-edges here. So for + * now we rebuild edges (as we need correct user count for code selection) + */ +#if 1 + edges_deactivate(cg->irg); + edges_activate(cg->irg); +#endif + if(cg->dump) - be_dump(cg->irg, "-lower_modeb", dump_ir_block_graph_sched); + be_dump(cg->irg, "-pre_transform", dump_ir_block_graph_sched); /* transform nodes into assembler instructions */ ia32_transform_graph(cg); @@ -949,13 +989,12 @@ static void turn_back_am(ir_node *node) ir_node *base = get_irn_n(node, n_ia32_base); ir_node *index = get_irn_n(node, n_ia32_index); ir_node *mem = get_irn_n(node, n_ia32_mem); + ir_node *noreg = ia32_new_NoReg_gp(ia32_current_cg); ir_node *load; ir_node *load_res; ir_node *mem_proj; const ir_edge_t *edge; - ir_fprintf(stderr, "truning back AM in %+F\n", node); - load = new_rd_ia32_Load(dbgi, irg, block, base, index, mem); load_res = new_rd_Proj(dbgi, irg, block, load, mode_Iu, pn_ia32_Load_res); @@ -965,10 +1004,22 @@ static void turn_back_am(ir_node *node) if(get_ia32_am_arity(node) == ia32_am_unary) { set_irn_n(node, n_ia32_unary_op, load_res); } else if(get_ia32_am_arity(node) == ia32_am_binary) { - set_irn_n(node, n_ia32_binary_right, load_res); + if(is_ia32_Immediate(get_irn_n(node, n_ia32_Cmp_right))) { + assert(is_ia32_Cmp(node) || is_ia32_Cmp8Bit(node) + || is_ia32_Test(node) || is_ia32_Test8Bit(node)); + set_irn_n(node, n_ia32_binary_left, load_res); + } else { + set_irn_n(node, n_ia32_binary_right, load_res); + } } else if(get_ia32_am_arity(node) == ia32_am_ternary) { set_irn_n(node, n_ia32_binary_right, load_res); } + set_irn_n(node, n_ia32_base, noreg); + set_irn_n(node, n_ia32_index, noreg); + set_ia32_am_offs_int(node, 0); + set_ia32_am_sc(node, NULL); + set_ia32_am_scale(node, 0); + clear_ia32_am_sc_sign(node); /* rewire mem-proj */ if(get_irn_mode(node) == mode_T) { @@ -995,17 +1046,27 @@ static void turn_back_am(ir_node *node) static ir_node *flags_remat(ir_node *node, ir_node *after) { /* we should turn back source address mode when rematerializing nodes */ - ia32_op_type_t type = get_ia32_op_type(node); - if(type == ia32_AddrModeS) { + ia32_op_type_t type = get_ia32_op_type(node); + ir_node *block; + ir_node *copy; + + if(is_Block(after)) { + block = after; + } else { + block = get_nodes_block(after); + } + + if (type == ia32_AddrModeS) { turn_back_am(node); - } else if(type == ia32_AddrModeD) { + } else if (type == ia32_AddrModeD) { /* TODO implement this later... */ panic("found DestAM with flag user %+F this should not happen", node); } else { assert(type == ia32_Normal); } - ir_node *copy = exact_copy(node); + copy = exact_copy(node); + set_nodes_block(copy, block); sched_add_after(after, copy); return copy; @@ -1431,7 +1492,7 @@ static void *ia32_cg_init(be_irg_t *birg); static const arch_code_generator_if_t ia32_code_gen_if = { ia32_cg_init, - NULL, /* before abi introduce hook */ + ia32_before_abi, /* before abi introduce hook */ ia32_prepare_graph, NULL, /* spill */ ia32_before_sched, /* before scheduling hook */ @@ -1536,7 +1597,6 @@ static ia32_isa_t ia32_isa_template = { 7, /* costs for a spill instruction */ 5, /* costs for a reload instruction */ }, - NULL_EMITTER, /* emitter environment */ NULL, /* 16bit register names */ NULL, /* 8bit register names */ NULL, /* 8bit register names high */ @@ -1596,7 +1656,7 @@ static void *ia32_init(FILE *file_handle) { isa->opt &= ~IA32_OPT_INCDEC; } - be_emit_init_env(&isa->emit, file_handle); + be_emit_init(file_handle); isa->regs_16bit = pmap_create(); isa->regs_8bit = pmap_create(); isa->regs_8bit_high = pmap_create(); @@ -1613,12 +1673,14 @@ static void *ia32_init(FILE *file_handle) { obstack_init(isa->name_obst); #endif /* NDEBUG */ + /* enter the ISA object into the intrinsic environment */ + intrinsic_env.isa = isa; ia32_handle_intrinsics(); /* needed for the debug support */ - be_gas_emit_switch_section(&isa->emit, GAS_SECTION_TEXT); - be_emit_cstring(&isa->emit, ".Ltext0:\n"); - be_emit_write_line(&isa->emit); + be_gas_emit_switch_section(GAS_SECTION_TEXT); + be_emit_cstring(".Ltext0:\n"); + be_emit_write_line(); /* we mark referenced global entities, so we can only emit those which * are actually referenced. (Note: you mustn't use the type visited flag @@ -1638,7 +1700,7 @@ static void ia32_done(void *self) { ia32_isa_t *isa = self; /* emit now all global declarations */ - be_gas_emit_decls(&isa->emit, isa->arch_isa.main_env, 1); + be_gas_emit_decls(isa->arch_isa.main_env, 1); pmap_destroy(isa->regs_16bit); pmap_destroy(isa->regs_8bit); @@ -1650,7 +1712,7 @@ static void ia32_done(void *self) { obstack_free(isa->name_obst, NULL); #endif /* NDEBUG */ - be_emit_destroy_env(&isa->emit); + be_emit_exit(); free(self); } @@ -1708,11 +1770,9 @@ static void ia32_get_call_abi(const void *self, ir_type *method_type, be_abi_cal int n, i, regnum; be_abi_call_flags_t call_flags = be_abi_call_get_flags(abi); - unsigned use_push = !IS_P6_ARCH(isa->opt_arch); - /* set abi flags for calls */ call_flags.bits.left_to_right = 0; /* always last arg first on stack */ - call_flags.bits.store_args_sequential = use_push; + call_flags.bits.store_args_sequential = 0; /* call_flags.bits.try_omit_fp not changed: can handle both settings */ call_flags.bits.fp_free = 0; /* the frame pointer is fixed in IA32 */ call_flags.bits.call_has_imm = 1; /* IA32 calls can have immediate address */ @@ -2147,18 +2207,6 @@ static int ia32_evaluate_insn(insn_kind kind, tarval *tv) { } } -static ia32_intrinsic_env_t intrinsic_env = { - NULL, /**< the irg, these entities belong to */ - NULL, /**< entity for first div operand (move into FPU) */ - NULL, /**< entity for second div operand (move into FPU) */ - NULL, /**< entity for converts ll -> d */ - NULL, /**< entity for converts d -> ll */ - NULL, /**< entity for __divdi3 library call */ - NULL, /**< entity for __moddi3 library call */ - NULL, /**< entity for __udivdi3 library call */ - NULL, /**< entity for __umoddi3 library call */ -}; - /** * Returns the libFirm configuration parameter for this backend. */