X-Git-Url: http://nsz.repo.hu/git/?a=blobdiff_plain;f=ir%2Fbe%2Fia32%2Fia32_optimize.c;h=d2d1c99021f9dbed0a1b121a5fea85d390ace13a;hb=3f807bf48426a29da4129ff29c44a4b4690c45f6;hp=ba73950036ad1c41cdb6ddbf69ba72c17f36d6a9;hpb=3619ae08c1d392ab6e88a0471bc9631bb20027c8;p=libfirm diff --git a/ir/be/ia32/ia32_optimize.c b/ir/be/ia32/ia32_optimize.c index ba7395003..d2d1c9902 100644 --- a/ir/be/ia32/ia32_optimize.c +++ b/ir/be/ia32/ia32_optimize.c @@ -51,6 +51,7 @@ #include "ia32_optimize.h" #include "bearch_ia32_t.h" #include "gen_ia32_regalloc_if.h" +#include "ia32_common_transform.h" #include "ia32_transform.h" #include "ia32_dbg_stat.h" #include "ia32_util.h" @@ -159,6 +160,71 @@ static ir_node *turn_into_mode_t(ir_node *node) return new_node; } +/** + * Replace Cmp(x, 0) by a Test(x, x) + */ +static void peephole_ia32_Cmp(ir_node *const node) +{ + ir_node *right; + ia32_immediate_attr_t const *imm; + dbg_info *dbgi; + ir_graph *irg; + ir_node *block; + ir_node *noreg; + ir_node *nomem; + ir_node *op; + ia32_attr_t const *attr; + int ins_permuted; + int cmp_unsigned; + ir_node *test; + arch_register_t const *reg; + ir_edge_t const *edge; + ir_edge_t const *tmp; + + if (get_ia32_op_type(node) != ia32_Normal) + return; + + right = get_irn_n(node, n_ia32_Cmp_right); + if (!is_ia32_Immediate(right)) + return; + + imm = get_ia32_immediate_attr_const(right); + if (imm->symconst != NULL || imm->offset != 0) + return; + + dbgi = get_irn_dbg_info(node); + irg = current_ir_graph; + block = get_nodes_block(node); + noreg = ia32_new_NoReg_gp(cg); + nomem = get_irg_no_mem(irg); + op = get_irn_n(node, n_ia32_Cmp_left); + attr = get_irn_generic_attr(node); + ins_permuted = attr->data.ins_permuted; + cmp_unsigned = attr->data.cmp_unsigned; + + if (is_ia32_Cmp(node)) { + test = new_rd_ia32_Test(dbgi, irg, block, noreg, noreg, nomem, + op, op, ins_permuted, cmp_unsigned); + } else { + test = new_rd_ia32_Test8Bit(dbgi, irg, block, noreg, noreg, nomem, + op, op, ins_permuted, cmp_unsigned); + } + set_ia32_ls_mode(test, get_ia32_ls_mode(node)); + + reg = arch_get_irn_register(arch_env, node); + arch_set_irn_register(arch_env, test, reg); + + foreach_out_edge_safe(node, edge, tmp) { + ir_node *const user = get_edge_src_irn(edge); + + if (is_Proj(user)) + exchange(user, test); + } + + sched_add_before(node, test); + be_peephole_exchange(node, test); +} + /** * Peephole optimization for Test instructions. * We can remove the Test, if a zero flags was produced which is still @@ -265,9 +331,7 @@ static void peephole_ia32_Return(ir_node *node) { } } - /* ensure, that the 3 byte return is generated - * actually the emitter tests again if the block beginning has a label and - * isn't just a fallthrough */ + /* ensure, that the 3 byte return is generated */ be_Return_set_emit_pop(node, 1); } @@ -281,13 +345,18 @@ static void peephole_ia32_Return(ir_node *node) { */ static void peephole_IncSP_Store_to_push(ir_node *irn) { - int i, maxslot, inc_ofs; - ir_node *node; - ir_node *stores[MAXPUSH_OPTIMIZE]; - ir_node *block; - ir_graph *irg; - ir_node *curr_sp; - ir_mode *spmode; + int i; + int maxslot; + int inc_ofs; + ir_node *node; + ir_node *stores[MAXPUSH_OPTIMIZE]; + ir_node *block; + ir_graph *irg; + ir_node *curr_sp; + ir_mode *spmode; + ir_node *first_push = NULL; + ir_edge_t const *edge; + ir_edge_t const *next; memset(stores, 0, sizeof(stores)); @@ -323,20 +392,18 @@ static void peephole_IncSP_Store_to_push(ir_node *irn) /* unfortunately we can't support the full AMs possible for push at the * moment. TODO: fix this */ - if (get_ia32_am_scale(node) > 0 || !is_ia32_NoReg_GP(get_irn_n(node, n_ia32_index))) + if (!is_ia32_NoReg_GP(get_irn_n(node, n_ia32_index))) break; offset = get_ia32_am_offs_int(node); /* we should NEVER access uninitialized stack BELOW the current SP */ assert(offset >= 0); - offset = inc_ofs - 4 - offset; - /* storing at half-slots is bad */ if ((offset & 3) != 0) break; - if (offset < 0 || offset >= MAXPUSH_OPTIMIZE * 4) + if (inc_ofs - 4 < offset || offset >= MAXPUSH_OPTIMIZE * 4) continue; storeslot = offset >> 2; @@ -349,29 +416,34 @@ static void peephole_IncSP_Store_to_push(ir_node *irn) maxslot = storeslot; } - curr_sp = be_get_IncSP_pred(irn); + curr_sp = irn; + + for (i = -1; i < maxslot; ++i) { + if (stores[i + 1] == NULL) + break; + } /* walk through the Stores and create Pushs for them */ block = get_nodes_block(irn); spmode = get_irn_mode(irn); irg = cg->irg; - for (i = 0; i <= maxslot; ++i) { + for (; i >= 0; --i) { const arch_register_t *spreg; ir_node *push; ir_node *val, *mem, *mem_proj; ir_node *store = stores[i]; ir_node *noreg = ia32_new_NoReg_gp(cg); - if (store == NULL) - break; - val = get_irn_n(store, n_ia32_unary_op); mem = get_irn_n(store, n_ia32_mem); spreg = arch_get_irn_register(cg->arch_env, curr_sp); push = new_rd_ia32_Push(get_irn_dbg_info(store), irg, block, noreg, noreg, mem, val, curr_sp); - sched_add_before(irn, push); + if (first_push == NULL) + first_push = push; + + sched_add_after(curr_sp, push); /* create stackpointer Proj */ curr_sp = new_r_Proj(irg, block, push, spmode, pn_ia32_Push_stack); @@ -381,16 +453,22 @@ static void peephole_IncSP_Store_to_push(ir_node *irn) mem_proj = new_r_Proj(irg, block, push, mode_M, pn_ia32_Push_M); /* use the memproj now */ - exchange(store, mem_proj); - - /* we can remove the Store now */ - sched_remove(store); + be_peephole_exchange(store, mem_proj); inc_ofs -= 4; } + foreach_out_edge_safe(irn, edge, next) { + ir_node *const src = get_edge_src_irn(edge); + int const pos = get_edge_src_pos(edge); + + if (src == first_push) + continue; + + set_irn_n(src, pos, curr_sp); + } + be_set_IncSP_offset(irn, inc_ofs); - be_set_IncSP_pred(irn, curr_sp); } /** @@ -435,7 +513,6 @@ static void peephole_Load_IncSP_to_pop(ir_node *irn) maxslot = -1; pred_sp = be_get_IncSP_pred(irn); for (node = sched_prev(irn); !sched_is_end(node); node = sched_prev(node)) { - ir_node *mem; int offset; int loadslot; const arch_register_t *sreg, *dreg; @@ -474,13 +551,9 @@ static void peephole_Load_IncSP_to_pop(ir_node *irn) * but we do not check this */ break; } - /* Load has to be attached to Spill-Mem */ - mem = skip_Proj(get_irn_n(node, n_ia32_mem)); - if (!is_Phi(mem) && !is_ia32_Store(mem) && !is_ia32_Push(mem)) - break; /* should have NO index */ - if (get_ia32_am_scale(node) > 0 || !is_ia32_NoReg_GP(get_irn_n(node, n_ia32_index))) + if (!is_ia32_NoReg_GP(get_irn_n(node, n_ia32_index))) break; offset = get_ia32_am_offs_int(node); @@ -562,14 +635,13 @@ static void peephole_Load_IncSP_to_pop(ir_node *irn) set_Proj_pred(proj, pop); } - /* we can remove the Load now */ sched_remove(load); kill_node(load); } + be_set_IncSP_offset(irn, -ofs); be_set_IncSP_pred(irn, pred_sp); - } @@ -643,19 +715,14 @@ static ir_node *create_pop(dbg_info *dbgi, ir_graph *irg, ir_node *block, * @return the new stack value */ static ir_node *create_push(dbg_info *dbgi, ir_graph *irg, ir_node *block, - ir_node *stack, ir_node *schedpoint, - const arch_register_t *reg) + ir_node *stack, ir_node *schedpoint) { const arch_register_t *esp = &ia32_gp_regs[REG_ESP]; - ir_node *noreg, *nomem, *push, *val; - - val = new_rd_ia32_ProduceVal(NULL, irg, block); - arch_set_irn_register(arch_env, val, reg); - sched_add_before(schedpoint, val); - noreg = ia32_new_NoReg_gp(cg); - nomem = get_irg_no_mem(irg); - push = new_rd_ia32_Push(dbgi, irg, block, noreg, noreg, nomem, val, stack); + ir_node *val = ia32_new_Unknown_gp(cg); + ir_node *noreg = ia32_new_NoReg_gp(cg); + ir_node *nomem = get_irg_no_mem(irg); + ir_node *push = new_rd_ia32_Push(dbgi, irg, block, noreg, noreg, nomem, val, stack); sched_add_before(schedpoint, push); stack = new_r_Proj(irg, block, push, mode_Iu, pn_ia32_Push_stack); @@ -716,12 +783,10 @@ static void peephole_be_IncSP(ir_node *node) dbgi = get_irn_dbg_info(node); block = get_nodes_block(node); stack = be_get_IncSP_pred(node); - reg = &ia32_gp_regs[REG_EAX]; - - stack = create_push(dbgi, irg, block, stack, node, reg); + stack = create_push(dbgi, irg, block, stack, node); if (offset == +8) { - stack = create_push(dbgi, irg, block, stack, node, reg); + stack = create_push(dbgi, irg, block, stack, node); } } @@ -1056,12 +1121,14 @@ void ia32_peephole_optimization(ia32_code_gen_t *new_cg) /* register peephole optimisations */ 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); - register_peephole_optimisation(op_ia32_Test, peephole_ia32_Test); + 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); + register_peephole_optimisation(op_ia32_Cmp, peephole_ia32_Cmp); + register_peephole_optimisation(op_ia32_Cmp8Bit, peephole_ia32_Cmp); + register_peephole_optimisation(op_ia32_Test, peephole_ia32_Test); register_peephole_optimisation(op_ia32_Test8Bit, peephole_ia32_Test); - register_peephole_optimisation(op_be_Return, peephole_ia32_Return); + register_peephole_optimisation(op_be_Return, peephole_ia32_Return); if (! ia32_cg_config.use_imul_mem_imm32) register_peephole_optimisation(op_ia32_IMul, peephole_ia32_Imul_split); if (ia32_cg_config.use_pxor) @@ -1092,7 +1159,7 @@ static INLINE void try_kill(ir_node *node) sched_remove(node); } - be_kill_node(node); + kill_node(node); } static void optimize_conv_store(ir_node *node) @@ -1126,9 +1193,9 @@ static void optimize_conv_store(ir_node *node) set_irn_n(node, n_ia32_Store_val, get_irn_n(pred, n_ia32_Conv_I2I_val)); if(get_irn_n_edges(pred_proj) == 0) { - be_kill_node(pred_proj); + kill_node(pred_proj); if(pred != pred_proj) - be_kill_node(pred); + kill_node(pred); } } @@ -1253,9 +1320,9 @@ static void optimize_conv_conv(ir_node *node) exchange(node, result_conv); if(get_irn_n_edges(pred_proj) == 0) { - be_kill_node(pred_proj); + kill_node(pred_proj); if(pred != pred_proj) - be_kill_node(pred); + kill_node(pred); } optimize_conv_conv(result_conv); }