X-Git-Url: http://nsz.repo.hu/git/?a=blobdiff_plain;f=ir%2Fbe%2Fia32%2Fbearch_ia32.c;h=fdf9abf0473b6ecd45776a093a77cf34fba6ab52;hb=d51bc5156f1a0c202be8b40c4dd7667bd3a6933e;hp=7a50ed64c472ad2b8739b2934f7cabcefe546d55;hpb=b9f50a478322430044a64f0cddc09b01c55b5bbd;p=libfirm diff --git a/ir/be/ia32/bearch_ia32.c b/ir/be/ia32/bearch_ia32.c index 7a50ed64c..fdf9abf04 100644 --- a/ir/be/ia32/bearch_ia32.c +++ b/ir/be/ia32/bearch_ia32.c @@ -410,15 +410,16 @@ static void ia32_abi_dont_save_regs(void *self, pset *s) /** * Generate the routine prologue. * - * @param self The callback object. - * @param mem A pointer to the mem node. Update this if you define new memory. - * @param reg_map A map mapping all callee_save/ignore/parameter registers to their defining nodes. + * @param self The callback object. + * @param mem A pointer to the mem node. Update this if you define new memory. + * @param reg_map A map mapping all callee_save/ignore/parameter registers to their defining nodes. + * @param stack_bias Points to the current stack bias, can be modified if needed. * - * @return The register which shall be used as a stack frame base. + * @return The register which shall be used as a stack frame base. * * All nodes which define registers in @p reg_map must keep @p reg_map current. */ -static const arch_register_t *ia32_abi_prologue(void *self, ir_node **mem, pmap *reg_map) +static const arch_register_t *ia32_abi_prologue(void *self, ir_node **mem, pmap *reg_map, int *stack_bias) { ia32_abi_env_t *env = self; ia32_code_gen_t *cg = ia32_current_cg; @@ -444,6 +445,9 @@ static const arch_register_t *ia32_abi_prologue(void *self, ir_node **mem, pmap arch_set_irn_register(arch_env, curr_sp, arch_env->sp); set_ia32_flags(push, arch_irn_flags_ignore); + /* this modifies the stack bias, because we pushed 32bit */ + *stack_bias -= 4; + /* move esp to ebp */ curr_bp = be_new_Copy(arch_env->bp->reg_class, irg, bl, curr_sp); be_set_constr_single_reg(curr_bp, BE_OUT_POS(0), arch_env->bp); @@ -486,7 +490,6 @@ static void ia32_abi_epilogue(void *self, ir_node *bl, ir_node **mem, pmap *reg_ if (env->flags.try_omit_fp) { /* simply remove the stack frame here */ curr_sp = be_new_IncSP(arch_env->sp, irg, bl, curr_sp, BE_STACK_FRAME_SIZE_SHRINK, 0); - add_irn_dep(curr_sp, *mem); } else { ir_mode *mode_bp = arch_env->bp->reg_class->mode; @@ -494,7 +497,7 @@ static void ia32_abi_epilogue(void *self, ir_node *bl, ir_node **mem, pmap *reg_ ir_node *leave; /* leave */ - leave = new_rd_ia32_Leave(NULL, irg, bl, curr_sp, curr_bp); + leave = new_rd_ia32_Leave(NULL, irg, bl, curr_bp); set_ia32_flags(leave, arch_irn_flags_ignore); 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); @@ -630,9 +633,10 @@ static int ia32_get_op_estimated_cost(const ir_node *irn) (we assume they are in cache), other memory operations cost 20 cycles. */ - if(is_ia32_use_frame(irn) || - (is_ia32_NoReg_GP(get_irn_n(irn, 0)) && - is_ia32_NoReg_GP(get_irn_n(irn, 1)))) { + if (is_ia32_use_frame(irn) || ( + is_ia32_NoReg_GP(get_irn_n(irn, n_ia32_base)) && + is_ia32_NoReg_GP(get_irn_n(irn, n_ia32_index)) + )) { cost += 5; } else { cost += 20; @@ -839,6 +843,9 @@ static int ia32_possible_memory_operand(const ir_node *irn, unsigned int i) { static void ia32_perform_memory_operand(ir_node *irn, ir_node *spill, unsigned int i) { + ir_mode *load_mode; + ir_mode *dest_op_mode; + ia32_code_gen_t *cg = ia32_current_cg; assert(ia32_possible_memory_operand(irn, i) && "Cannot perform memory operand change"); @@ -848,13 +855,19 @@ static void ia32_perform_memory_operand(ir_node *irn, ir_node *spill, } set_ia32_op_type(irn, ia32_AddrModeS); - set_ia32_ls_mode(irn, get_irn_mode(get_irn_n(irn, i))); + + load_mode = get_irn_mode(get_irn_n(irn, i)); + dest_op_mode = get_ia32_ls_mode(irn); + if (get_mode_size_bits(load_mode) <= get_mode_size_bits(dest_op_mode)) { + set_ia32_ls_mode(irn, load_mode); + } set_ia32_use_frame(irn); set_ia32_need_stackent(irn); set_irn_n(irn, n_ia32_base, get_irg_frame(get_irn_irg(irn))); set_irn_n(irn, n_ia32_binary_right, ia32_get_admissible_noreg(cg, irn, n_ia32_binary_right)); set_irn_n(irn, n_ia32_mem, spill); + set_ia32_is_reload(irn); /* immediates are only allowed on the right side */ if (i == n_ia32_binary_left && is_ia32_Immediate(get_irn_n(irn, n_ia32_binary_left))) { @@ -927,14 +940,7 @@ static void ia32_before_abi(void *self) { } } -typedef enum transformer_t { - TRANSFORMER_DEFAULT, -#ifdef FIRM_GRGEN_BE - TRANSFORMER_PBQP -#endif -} transformer_t; - -static transformer_t be_transformer = TRANSFORMER_DEFAULT; +transformer_t be_transformer = TRANSFORMER_DEFAULT; /** * Transforms the standard firm graph into @@ -965,19 +971,18 @@ static void ia32_prepare_graph(void *self) { #ifdef FIRM_GRGEN_BE case TRANSFORMER_PBQP: + case TRANSFORMER_RAND: // disable CSE, because of two-step node-construction set_opt_cse(0); /* transform nodes into assembler instructions by PBQP magic */ ia32_transform_graph_by_pbqp(cg); - if (cg->dump) - be_dump(cg->irg, "-after_pbqp_transform", dump_ir_block_graph_sched); set_opt_cse(1); break; #endif - default: panic("Invalid transformer"); + default: panic("invalid transformer"); } /* do local optimizations (mainly CSE) */ @@ -1024,6 +1029,8 @@ static void turn_back_am(ir_node *node) load_res = new_rd_Proj(dbgi, irg, block, load, mode_Iu, pn_ia32_Load_res); ia32_copy_am_attrs(load, node); + if (is_ia32_is_reload(node)) + set_ia32_is_reload(load); set_irn_n(node, n_ia32_mem, new_NoMem()); switch (get_ia32_am_arity(node)) { @@ -1112,8 +1119,6 @@ static ir_node *flags_remat(ir_node *node, ir_node *after) /** * Called before the register allocator. - * Calculate a block schedule here. We need it for the x87 - * simulator and the emitter. */ static void ia32_before_ra(void *self) { ia32_code_gen_t *cg = self; @@ -1167,6 +1172,7 @@ static void transform_to_Load(ia32_code_gen_t *cg, ir_node *node) { set_ia32_ls_mode(new_op, spillmode); set_ia32_frame_ent(new_op, ent); set_ia32_use_frame(new_op); + set_ia32_is_reload(new_op); DBG_OPT_RELOAD2LD(node, new_op); @@ -1237,6 +1243,7 @@ static void transform_to_Store(ia32_code_gen_t *cg, ir_node *node) { set_ia32_ls_mode(store, mode); set_ia32_frame_ent(store, ent); set_ia32_use_frame(store); + set_ia32_is_spill(store); SET_IA32_ORIG_NODE(store, ia32_get_old_node_name(cg, node)); DBG_OPT_SPILL2ST(node, store); @@ -1432,7 +1439,11 @@ static void ia32_collect_frame_entity_nodes(ir_node *node, void *data) if (is_ia32_need_stackent(node) || is_ia32_Load(node)) { const ir_mode *mode = get_ia32_ls_mode(node); const ia32_attr_t *attr = get_ia32_attr_const(node); - int align = get_mode_size_bytes(mode); + int align; + + if (is_ia32_is_reload(node)) { + mode = get_spill_mode_mode(mode); + } if(attr->data.need_64bit_stackent) { mode = mode_Ls; @@ -1440,6 +1451,7 @@ static void ia32_collect_frame_entity_nodes(ir_node *node, void *data) if(attr->data.need_32bit_stackent) { mode = mode_Is; } + align = get_mode_size_bytes(mode); be_node_needs_frame_entity(env, node, mode, align); } else if (is_ia32_vfild(node) || is_ia32_xLoad(node) || is_ia32_vfld(node)) { @@ -1651,7 +1663,7 @@ static ia32_isa_t ia32_isa_template = { &ia32_gp_regs[REG_ESP], /* stack pointer register */ &ia32_gp_regs[REG_EBP], /* base pointer register */ -1, /* stack direction */ - 4, /* power of two stack alignment, 2^4 == 16 */ + 2, /* power of two stack alignment, 2^2 == 4 */ NULL, /* main environment */ 7, /* costs for a spill instruction */ 5, /* costs for a reload instruction */ @@ -1884,8 +1896,7 @@ static void ia32_get_call_abi(const void *self, ir_type *method_type, cc = cc_cdecl_set; } else { cc = get_method_calling_convention(method_type); - if (!(cc & cc_fixed) && - get_method_additional_properties(method_type) & mtp_property_private && + if (get_method_additional_properties(method_type) & mtp_property_private && ia32_cg_config.optimize_cc) { /* set the calling conventions to register parameter */ cc = (cc & ~cc_bits) | cc_reg_param; @@ -2111,6 +2122,13 @@ static ir_graph **ia32_get_irg_list(const void *self, ir_graph ***irg_list) return NULL; } +static void ia32_mark_remat(const void *self, ir_node *node) { + (void) self; + if (is_ia32_irn(node)) { + set_ia32_is_remat(node); + } +} + /** * Allows or disallows the creation of Psi nodes for the given Phi nodes. * @return 1 if allowed, 0 otherwise @@ -2319,6 +2337,7 @@ static const lc_opt_enum_int_items_t transformer_items[] = { { "default", TRANSFORMER_DEFAULT }, #ifdef FIRM_GRGEN_BE { "pbqp", TRANSFORMER_PBQP }, + { "random", TRANSFORMER_RAND }, #endif { NULL, 0 } }; @@ -2350,6 +2369,7 @@ const arch_isa_if_t ia32_isa_if = { ia32_get_allowed_execution_units, ia32_get_machine, ia32_get_irg_list, + ia32_mark_remat, ia32_parse_asm_constraint, ia32_is_valid_clobber };