X-Git-Url: http://nsz.repo.hu/git/?a=blobdiff_plain;f=ir%2Fbe%2Fia32%2Fia32_optimize.c;h=d2d1c99021f9dbed0a1b121a5fea85d390ace13a;hb=3f807bf48426a29da4129ff29c44a4b4690c45f6;hp=341437cc746e9040403a4f8a540b3aaf17b6021a;hpb=2440343b60976b5a7bcc1ef290f7ca693336254b;p=libfirm diff --git a/ir/be/ia32/ia32_optimize.c b/ir/be/ia32/ia32_optimize.c index 341437cc7..d2d1c9902 100644 --- a/ir/be/ia32/ia32_optimize.c +++ b/ir/be/ia32/ia32_optimize.c @@ -331,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); } @@ -347,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)); @@ -389,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; @@ -415,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); @@ -452,8 +458,17 @@ static void peephole_IncSP_Store_to_push(ir_node *irn) 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); } /** @@ -498,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; @@ -537,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);