From: Matthias Braun Date: Mon, 15 Oct 2007 19:31:46 +0000 (+0000) Subject: move lea_to_add into the peephole phase X-Git-Url: http://nsz.repo.hu/git/?a=commitdiff_plain;h=ae3dce180880d08e70c80c9216dabf586f9547d9;p=libfirm move lea_to_add into the peephole phase [r16212] --- diff --git a/ir/be/ia32/bearch_ia32.c b/ir/be/ia32/bearch_ia32.c index 9d0ccda1d..edd26f187 100644 --- a/ir/be/ia32/bearch_ia32.c +++ b/ir/be/ia32/bearch_ia32.c @@ -1469,7 +1469,7 @@ static void ia32_finish(void *self) { } /* do peephole optimisations */ - ia32_peephole_optimization(irg, cg); + ia32_peephole_optimization(cg); /* create block schedule, this also removes empty blocks which might * produce critical edges */ diff --git a/ir/be/ia32/ia32_finish.c b/ir/be/ia32/ia32_finish.c index 81a63d142..5306d62a5 100644 --- a/ir/be/ia32/ia32_finish.c +++ b/ir/be/ia32/ia32_finish.c @@ -141,214 +141,6 @@ static void ia32_transform_sub_to_neg_add(ir_node *irn, ia32_code_gen_t *cg) { DBG_OPT_SUB2NEGADD(irn, res); } -static INLINE int is_noreg(ia32_code_gen_t *cg, const ir_node *node) -{ - return node == cg->noreg_gp; -} - -static ir_node *create_immediate_from_int(ia32_code_gen_t *cg, int val) -{ - ir_graph *irg = current_ir_graph; - ir_node *start_block = get_irg_start_block(irg); - ir_node *immediate = new_rd_ia32_Immediate(NULL, irg, start_block, NULL, - 0, val); - arch_set_irn_register(cg->arch_env, immediate, &ia32_gp_regs[REG_GP_NOREG]); - - return immediate; -} - -static ir_node *create_immediate_from_am(ia32_code_gen_t *cg, - const ir_node *node) -{ - ir_graph *irg = get_irn_irg(node); - ir_node *block = get_nodes_block(node); - int offset = get_ia32_am_offs_int(node); - int sc_sign = is_ia32_am_sc_sign(node); - ir_entity *entity = get_ia32_am_sc(node); - ir_node *res; - - res = new_rd_ia32_Immediate(NULL, irg, block, entity, sc_sign, offset); - arch_set_irn_register(cg->arch_env, res, &ia32_gp_regs[REG_GP_NOREG]); - return res; -} - -static int is_am_one(const ir_node *node) -{ - int offset = get_ia32_am_offs_int(node); - ir_entity *entity = get_ia32_am_sc(node); - - return offset == 1 && entity == NULL; -} - -static int is_am_minus_one(const ir_node *node) -{ - int offset = get_ia32_am_offs_int(node); - ir_entity *entity = get_ia32_am_sc(node); - - return offset == -1 && entity == NULL; -} - -/** - * Transforms a LEA into an Add or SHL if possible. - * THIS FUNCTIONS MUST BE CALLED AFTER REGISTER ALLOCATION. - */ -static void ia32_transform_lea_to_add_or_shl(ir_node *node, ia32_code_gen_t *cg) -{ - const arch_env_t *arch_env = cg->arch_env; - ir_graph *irg = current_ir_graph; - ir_node *base; - ir_node *index; - const arch_register_t *base_reg; - const arch_register_t *index_reg; - const arch_register_t *out_reg; - int scale; - int has_immediates; - ir_node *op1; - ir_node *op2; - dbg_info *dbgi; - ir_node *block; - ir_node *res; - ir_node *noreg; - ir_node *nomem; - - if(!is_ia32_Lea(node)) - return; - - base = get_irn_n(node, n_ia32_Lea_base); - index = get_irn_n(node, n_ia32_Lea_index); - - if(is_noreg(cg, base)) { - base = NULL; - base_reg = NULL; - } else { - base_reg = arch_get_irn_register(arch_env, base); - } - if(is_noreg(cg, index)) { - index = NULL; - index_reg = NULL; - } else { - index_reg = arch_get_irn_register(arch_env, index); - } - - if(base == NULL && index == NULL) { - /* we shouldn't construct these in the first place... */ -#ifdef DEBUG_libfirm - ir_fprintf(stderr, "Optimisation warning: found immediate only lea\n"); -#endif - return; - } - - out_reg = arch_get_irn_register(arch_env, node); - scale = get_ia32_am_scale(node); - assert(!is_ia32_need_stackent(node) || get_ia32_frame_ent(node) != NULL); - /* check if we have immediates values (frame entities should already be - * expressed in the offsets) */ - if(get_ia32_am_offs_int(node) != 0 || get_ia32_am_sc(node) != NULL) { - has_immediates = 1; - } else { - has_immediates = 0; - } - - /* we can transform leas where the out register is the same as either the - * base or index register back to an Add or Shl */ - if(out_reg == base_reg) { - if(index == NULL) { -#ifdef DEBUG_libfirm - if(!has_immediates) { - ir_fprintf(stderr, "Optimisation warning: found lea which is " - "just a copy\n"); - } -#endif - op1 = base; - goto make_add_immediate; - } - if(scale == 0 && !has_immediates) { - op1 = base; - op2 = index; - goto make_add; - } - /* can't create an add */ - return; - } else if(out_reg == index_reg) { - if(base == NULL) { - if(has_immediates && scale == 0) { - op1 = index; - goto make_add_immediate; - } else if(!has_immediates && scale > 0) { - op1 = index; - op2 = create_immediate_from_int(cg, scale); - goto make_shl; - } else if(!has_immediates) { -#ifdef DEBUG_libfirm - ir_fprintf(stderr, "Optimisation warning: found lea which is " - "just a copy\n"); -#endif - } - } else if(scale == 0 && !has_immediates) { - op1 = index; - op2 = base; - goto make_add; - } - /* can't create an add */ - return; - } else { - /* can't create an add */ - return; - } - -make_add_immediate: - if(cg->isa->opt & IA32_OPT_INCDEC) { - if(is_am_one(node)) { - dbgi = get_irn_dbg_info(node); - block = get_nodes_block(node); - res = new_rd_ia32_Inc(dbgi, irg, block, op1); - arch_set_irn_register(arch_env, res, out_reg); - goto exchange; - } - if(is_am_minus_one(node)) { - dbgi = get_irn_dbg_info(node); - block = get_nodes_block(node); - res = new_rd_ia32_Dec(dbgi, irg, block, op1); - arch_set_irn_register(arch_env, res, out_reg); - goto exchange; - } - } - op2 = create_immediate_from_am(cg, node); - -make_add: - dbgi = get_irn_dbg_info(node); - block = get_nodes_block(node); - noreg = ia32_new_NoReg_gp(cg); - nomem = new_NoMem(); - res = new_rd_ia32_Add(dbgi, irg, block, noreg, noreg, nomem, op1, op2); - arch_set_irn_register(arch_env, res, out_reg); - set_ia32_commutative(res); - goto exchange; - -make_shl: - dbgi = get_irn_dbg_info(node); - block = get_nodes_block(node); - noreg = ia32_new_NoReg_gp(cg); - nomem = new_NoMem(); - res = new_rd_ia32_Shl(dbgi, irg, block, op1, op2); - arch_set_irn_register(arch_env, res, out_reg); - goto exchange; - -exchange: - SET_IA32_ORIG_NODE(res, ia32_get_old_node_name(cg, node)); - - /* add new ADD/SHL to schedule */ - sched_add_before(node, res); - - DBG_OPT_LEA2ADD(node, res); - - /* remove the old LEA */ - sched_remove(node); - - /* exchange the Add and the LEA */ - exchange(node, res); -} - static INLINE int need_constraint_copy(ir_node *irn) { return ! is_ia32_Lea(irn) && ! is_ia32_Conv_I2I(irn) && @@ -646,9 +438,6 @@ static void ia32_finish_irg_walker(ir_node *block, void *env) { /* check if there is a sub which need to be transformed */ ia32_transform_sub_to_neg_add(irn, cg); - - /* transform a LEA into an Add if possible */ - ia32_transform_lea_to_add_or_shl(irn, cg); } /* second: insert copies and finish irg */ diff --git a/ir/be/ia32/ia32_optimize.c b/ir/be/ia32/ia32_optimize.c index ba52e083b..daecdbd52 100644 --- a/ir/be/ia32/ia32_optimize.c +++ b/ir/be/ia32/ia32_optimize.c @@ -38,6 +38,7 @@ #include "irgwalk.h" #include "height.h" #include "irbitset.h" +#include "irprintf.h" #include "../be_t.h" #include "../beabi.h" @@ -46,6 +47,7 @@ #include "../bepeephole.h" #include "ia32_new_nodes.h" +#include "ia32_optimize.h" #include "bearch_ia32_t.h" #include "gen_ia32_regalloc_if.h" #include "ia32_transform.h" @@ -88,7 +90,7 @@ static INLINE int be_is_NoReg(ia32_code_gen_t *cg, const ir_node *irn) { /** * Tries to create pushs from IncSP,Store combinations */ -static void ia32_create_Pushs(ir_node *irn) +static void peephole_IncSP_Store_to_push(ir_node *irn) { int i; int offset; @@ -198,34 +200,8 @@ static void ia32_create_Pushs(ir_node *irn) } be_set_IncSP_offset(irn, offset); - - // can we remove the IncSP now? - if(offset == 0) { - const ir_edge_t *edge, *next; - - foreach_out_edge_safe(irn, edge, next) { - ir_node *arg = get_edge_src_irn(edge); - int pos = get_edge_src_pos(edge); - - set_irn_n(arg, pos, curr_sp); - } - - set_irn_n(irn, 0, new_Bad()); - sched_remove(irn); - } else { - set_irn_n(irn, 0, curr_sp); - } -} - -/** - * Performs Peephole Optimizations for IncSP nodes. - */ -static void ia32_peephole_optimize_node(ir_node *node, void *env) -{ - (void) env; - if (be_is_IncSP(node)) { - ia32_create_Pushs(node); - } + be_set_IncSP_pred(irn, curr_sp); + be_peephole_node_replaced(irn, irn); } /** @@ -309,6 +285,9 @@ static void peephole_be_IncSP(ir_node *node) ir_node *stack; int offset; + /* transform IncSP->Store combinations to Push where possible */ + peephole_IncSP_Store_to_push(node); + /* first optimize incsp->incsp combinations */ peephole_IncSP_IncSP(node); @@ -397,6 +376,217 @@ static void peephole_ia32_Const(ir_node *node) sched_remove(node); } +static INLINE int is_noreg(ia32_code_gen_t *cg, const ir_node *node) +{ + return node == cg->noreg_gp; +} + +static ir_node *create_immediate_from_int(ia32_code_gen_t *cg, int val) +{ + ir_graph *irg = current_ir_graph; + ir_node *start_block = get_irg_start_block(irg); + ir_node *immediate = new_rd_ia32_Immediate(NULL, irg, start_block, NULL, + 0, val); + arch_set_irn_register(cg->arch_env, immediate, &ia32_gp_regs[REG_GP_NOREG]); + + return immediate; +} + +static ir_node *create_immediate_from_am(ia32_code_gen_t *cg, + const ir_node *node) +{ + ir_graph *irg = get_irn_irg(node); + ir_node *block = get_nodes_block(node); + int offset = get_ia32_am_offs_int(node); + int sc_sign = is_ia32_am_sc_sign(node); + ir_entity *entity = get_ia32_am_sc(node); + ir_node *res; + + res = new_rd_ia32_Immediate(NULL, irg, block, entity, sc_sign, offset); + arch_set_irn_register(cg->arch_env, res, &ia32_gp_regs[REG_GP_NOREG]); + return res; +} + +static int is_am_one(const ir_node *node) +{ + int offset = get_ia32_am_offs_int(node); + ir_entity *entity = get_ia32_am_sc(node); + + return offset == 1 && entity == NULL; +} + +static int is_am_minus_one(const ir_node *node) +{ + int offset = get_ia32_am_offs_int(node); + ir_entity *entity = get_ia32_am_sc(node); + + return offset == -1 && entity == NULL; +} + +/** + * Transforms a LEA into an Add or SHL if possible. + */ +static void peephole_ia32_Lea(ir_node *node) +{ + const arch_env_t *arch_env = cg->arch_env; + ir_graph *irg = current_ir_graph; + ir_node *base; + ir_node *index; + const arch_register_t *base_reg; + const arch_register_t *index_reg; + const arch_register_t *out_reg; + int scale; + int has_immediates; + ir_node *op1; + ir_node *op2; + dbg_info *dbgi; + ir_node *block; + ir_node *res; + ir_node *noreg; + ir_node *nomem; + + assert(is_ia32_Lea(node)); + + /* we can only do this if are allowed to globber the flags */ + if(be_peephole_get_value(CLASS_ia32_flags, REG_EFLAGS) != NULL) + return; + + base = get_irn_n(node, n_ia32_Lea_base); + index = get_irn_n(node, n_ia32_Lea_index); + + if(is_noreg(cg, base)) { + base = NULL; + base_reg = NULL; + } else { + base_reg = arch_get_irn_register(arch_env, base); + } + if(is_noreg(cg, index)) { + index = NULL; + index_reg = NULL; + } else { + index_reg = arch_get_irn_register(arch_env, index); + } + + if(base == NULL && index == NULL) { + /* we shouldn't construct these in the first place... */ +#ifdef DEBUG_libfirm + ir_fprintf(stderr, "Optimisation warning: found immediate only lea\n"); +#endif + return; + } + + out_reg = arch_get_irn_register(arch_env, node); + scale = get_ia32_am_scale(node); + assert(!is_ia32_need_stackent(node) || get_ia32_frame_ent(node) != NULL); + /* check if we have immediates values (frame entities should already be + * expressed in the offsets) */ + if(get_ia32_am_offs_int(node) != 0 || get_ia32_am_sc(node) != NULL) { + has_immediates = 1; + } else { + has_immediates = 0; + } + + /* we can transform leas where the out register is the same as either the + * base or index register back to an Add or Shl */ + if(out_reg == base_reg) { + if(index == NULL) { +#ifdef DEBUG_libfirm + if(!has_immediates) { + ir_fprintf(stderr, "Optimisation warning: found lea which is " + "just a copy\n"); + } +#endif + op1 = base; + goto make_add_immediate; + } + if(scale == 0 && !has_immediates) { + op1 = base; + op2 = index; + goto make_add; + } + /* can't create an add */ + return; + } else if(out_reg == index_reg) { + if(base == NULL) { + if(has_immediates && scale == 0) { + op1 = index; + goto make_add_immediate; + } else if(!has_immediates && scale > 0) { + op1 = index; + op2 = create_immediate_from_int(cg, scale); + goto make_shl; + } else if(!has_immediates) { +#ifdef DEBUG_libfirm + ir_fprintf(stderr, "Optimisation warning: found lea which is " + "just a copy\n"); +#endif + } + } else if(scale == 0 && !has_immediates) { + op1 = index; + op2 = base; + goto make_add; + } + /* can't create an add */ + return; + } else { + /* can't create an add */ + return; + } + +make_add_immediate: + if(cg->isa->opt & IA32_OPT_INCDEC) { + if(is_am_one(node)) { + dbgi = get_irn_dbg_info(node); + block = get_nodes_block(node); + res = new_rd_ia32_Inc(dbgi, irg, block, op1); + arch_set_irn_register(arch_env, res, out_reg); + goto exchange; + } + if(is_am_minus_one(node)) { + dbgi = get_irn_dbg_info(node); + block = get_nodes_block(node); + res = new_rd_ia32_Dec(dbgi, irg, block, op1); + arch_set_irn_register(arch_env, res, out_reg); + goto exchange; + } + } + op2 = create_immediate_from_am(cg, node); + +make_add: + dbgi = get_irn_dbg_info(node); + block = get_nodes_block(node); + noreg = ia32_new_NoReg_gp(cg); + nomem = new_NoMem(); + res = new_rd_ia32_Add(dbgi, irg, block, noreg, noreg, nomem, op1, op2); + arch_set_irn_register(arch_env, res, out_reg); + set_ia32_commutative(res); + goto exchange; + +make_shl: + dbgi = get_irn_dbg_info(node); + block = get_nodes_block(node); + noreg = ia32_new_NoReg_gp(cg); + nomem = new_NoMem(); + res = new_rd_ia32_Shl(dbgi, irg, block, op1, op2); + arch_set_irn_register(arch_env, res, out_reg); + goto exchange; + +exchange: + SET_IA32_ORIG_NODE(res, ia32_get_old_node_name(cg, node)); + + /* add new ADD/SHL to schedule */ + sched_add_before(node, res); + + DBG_OPT_LEA2ADD(node, res); + + /* remove the old LEA */ + sched_remove(node); + + /* exchange the Add and the LEA */ + be_peephole_node_replaced(node, res); + exchange(node, res); +} + /** * Register a peephole optimisation function. */ @@ -406,7 +596,7 @@ static void register_peephole_optimisation(ir_op *op, peephole_opt_func func) { } /* Perform peephole-optimizations. */ -void ia32_peephole_optimization(ir_graph *irg, ia32_code_gen_t *new_cg) +void ia32_peephole_optimization(ia32_code_gen_t *new_cg) { cg = new_cg; arch_env = cg->arch_env; @@ -415,9 +605,9 @@ void ia32_peephole_optimization(ir_graph *irg, ia32_code_gen_t *new_cg) clear_irp_opcodes_generic_func(); register_peephole_optimisation(op_ia32_Const, peephole_ia32_Const); register_peephole_optimisation(op_be_IncSP, peephole_be_IncSP); + register_peephole_optimisation(op_ia32_Lea, peephole_ia32_Lea); be_peephole_opt(cg->birg); - irg_walk_graph(irg, ia32_peephole_optimize_node, NULL, NULL); } /** diff --git a/ir/be/ia32/ia32_optimize.h b/ir/be/ia32/ia32_optimize.h index 37a43c913..2b220718a 100644 --- a/ir/be/ia32/ia32_optimize.h +++ b/ir/be/ia32/ia32_optimize.h @@ -48,6 +48,6 @@ void ia32_optimize_graph(ia32_code_gen_t *cg); * @param irg the graph * @param cg the code generator object */ -void ia32_peephole_optimization(ir_graph *irg, ia32_code_gen_t *cg); +void ia32_peephole_optimization(ia32_code_gen_t *cg); #endif /* FIRM_BE_IA32_IA32_OPTIMIZE_H */ diff --git a/ir/be/ia32/ia32_spec.pl b/ir/be/ia32/ia32_spec.pl index 983d4ad96..eec664986 100644 --- a/ir/be/ia32/ia32_spec.pl +++ b/ir/be/ia32/ia32_spec.pl @@ -1237,8 +1237,8 @@ Lea => { latency => 2, units => [ "GP" ], mode => $mode_gp, -# well this isn't true for Lea, but we often transform Lea back to Add, Inc -# or Dec, so we set the flag +# lea doesn't modify the flags, but setting this seems advantageous since it +# increases chances that the Lea is transformed back to an Add modified_flags => 1, },