X-Git-Url: http://nsz.repo.hu/git/?a=blobdiff_plain;f=ir%2Fbe%2Fbestack.c;h=a28b4a43ad5a7bfbbe110587160c9581533dc8e8;hb=5474a1c188c9d59eea2c915515980cd9cbab58d8;hp=d63e7dc61788bf9cf22196cc13983ce729a3afa3;hpb=ff94a727febe4d155e1e807b57179df47f8fd489;p=libfirm diff --git a/ir/be/bestack.c b/ir/be/bestack.c index d63e7dc61..a28b4a43a 100644 --- a/ir/be/bestack.c +++ b/ir/be/bestack.c @@ -20,7 +20,6 @@ /** * @file * @author Sebastian Hack, Matthias Braun - * @version $Id$ * * Handling of the stack frame. It is composed of three types: * 1) The type of the arguments which are pushed on the stack. @@ -86,12 +85,11 @@ static ir_entity *search_ent_with_offset(ir_type *t, int offset) static int stack_frame_compute_initial_offset(be_stack_layout_t *frame) { - ir_type *base = frame->stack_dir < 0 ? frame->between_type : frame->frame_type; + ir_type *base = frame->between_type; ir_entity *ent = search_ent_with_offset(base, 0); if (ent == NULL) { - frame->initial_offset - = frame->stack_dir < 0 ? get_type_size_bytes(frame->frame_type) : get_type_size_bytes(frame->between_type); + frame->initial_offset = get_type_size_bytes(frame->frame_type); } else { frame->initial_offset = be_get_stack_entity_offset(frame, ent, 0); } @@ -141,11 +139,11 @@ static void lower_outer_frame_sels(ir_node *sel, void *ctx) /** * A helper struct for the bias walker. */ -struct bias_walk { +typedef struct bias_walk { int start_block_bias; /**< The bias at the end of the start block. */ int between_size; ir_node *start_block; /**< The start block of the current graph. */ -}; +} bias_walk; /** * Fix all stack accessing operations in the block bl. @@ -183,44 +181,41 @@ static int process_stack_bias(ir_node *bl, int real_bias) * If the node modifies the stack pointer by a constant offset, * record that in the bias. */ - ofs = arch_get_sp_bias(irn); - if (be_is_IncSP(irn)) { + ofs = be_get_IncSP_offset(irn); /* fill in real stack frame size */ - if (ofs == BE_STACK_FRAME_SIZE_EXPAND) { - ir_type *frame_type = get_irg_frame_type(irg); - ofs = (int) get_type_size_bytes(frame_type); - be_set_IncSP_offset(irn, ofs); - } else if (ofs == BE_STACK_FRAME_SIZE_SHRINK) { - ir_type *frame_type = get_irg_frame_type(irg); - ofs = - (int)get_type_size_bytes(frame_type); - be_set_IncSP_offset(irn, ofs); + if (be_get_IncSP_align(irn)) { + /* patch IncSP to produce an aligned stack pointer */ + ir_type *between_type = layout->between_type; + int between_size = get_type_size_bytes(between_type); + int alignment = 1 << arch_env->stack_alignment; + int delta = (real_bias + ofs + between_size) & (alignment - 1); + assert(ofs >= 0); + if (delta > 0) { + be_set_IncSP_offset(irn, ofs + alignment - delta); + real_bias += alignment - delta; + } } else { - if (be_get_IncSP_align(irn)) { - /* patch IncSP to produce an aligned stack pointer */ - ir_type *between_type = layout->between_type; - int between_size = get_type_size_bytes(between_type); - int alignment = 1 << arch_env->stack_alignment; - int delta = (real_bias + ofs + between_size) & (alignment - 1); - assert(ofs >= 0); - if (delta > 0) { - be_set_IncSP_offset(irn, ofs + alignment - delta); - real_bias += alignment - delta; - } - } else { - /* adjust so real_bias corresponds with wanted_bias */ - int delta = wanted_bias - real_bias; - assert(delta <= 0); - if (delta != 0) { - be_set_IncSP_offset(irn, ofs + delta); - real_bias += delta; - } + /* adjust so real_bias corresponds with wanted_bias */ + int delta = wanted_bias - real_bias; + assert(delta <= 0); + if (delta != 0) { + be_set_IncSP_offset(irn, ofs + delta); + real_bias += delta; } } + real_bias += ofs; + wanted_bias += ofs; + } else { + ofs = arch_get_sp_bias(irn); + if (ofs == SP_BIAS_RESET) { + real_bias = 0; + wanted_bias = 0; + } else { + real_bias += ofs; + wanted_bias += ofs; + } } - - real_bias += ofs; - wanted_bias += ofs; } assert(real_bias == wanted_bias); @@ -233,7 +228,7 @@ static int process_stack_bias(ir_node *bl, int real_bias) */ static void stack_bias_walker(ir_node *bl, void *data) { - struct bias_walk *bw = data; + bias_walk *bw = (bias_walk*)data; if (bl != bw->start_block) { process_stack_bias(bl, bw->start_block_bias); } @@ -243,8 +238,8 @@ void be_abi_fix_stack_bias(ir_graph *irg) { be_stack_layout_t *stack_layout = be_get_irg_stack_layout(irg); ir_type *frame_tp; - int i; - struct bias_walk bw; + int i; + bias_walk bw; stack_frame_compute_initial_offset(stack_layout); @@ -280,19 +275,19 @@ typedef struct fix_stack_walker_env_t { static void collect_stack_nodes_walker(ir_node *node, void *data) { ir_node *insn = node; - fix_stack_walker_env_t *env = data; + fix_stack_walker_env_t *env = (fix_stack_walker_env_t*)data; const arch_register_req_t *req; if (is_Proj(node)) { insn = get_Proj_pred(node); } - if (arch_irn_get_n_outs(insn) == 0) + if (arch_get_irn_n_outs(insn) == 0) return; if (get_irn_mode(node) == mode_T) return; - req = arch_get_register_req_out(node); + req = arch_get_irn_register_req(node); if (! (req->type & arch_register_req_type_produces_sp)) return; @@ -305,6 +300,7 @@ void be_abi_fix_stack_nodes(ir_graph *irg) const arch_env_t *arch_env = be_get_irg_arch_env(irg); be_irg_t *birg = be_birg_from_irg(irg); const arch_register_req_t *sp_req = birg->sp_req; + const arch_register_t *sp = arch_env->sp; be_ssa_construction_env_t senv; int i, len; ir_node **phis; @@ -322,9 +318,10 @@ void be_abi_fix_stack_nodes(ir_graph *irg) new_sp_req->width = 1; limited_bitset = rbitset_obstack_alloc(obst, new_sp_req->cls->n_regs); - rbitset_set(limited_bitset, arch_register_get_index(arch_env->sp)); + rbitset_set(limited_bitset, arch_register_get_index(sp)); new_sp_req->limited = limited_bitset; - if (arch_env->sp->type & arch_register_type_ignore) { + + if (!rbitset_is_set(birg->allocatable_regs, sp->global_index)) { new_sp_req->type |= arch_register_req_type_ignore; } @@ -370,6 +367,28 @@ void be_abi_fix_stack_nodes(ir_graph *irg) arch_set_irn_register(phi, arch_env->sp); } be_ssa_construction_destroy(&senv); - DEL_ARR_F(walker_env.sp_nodes); + + /* when doing code with frame-pointers then often the last incsp-nodes are + * not used anymore because we copy the framepointer to the stack pointer + * when leaving the function. Though the last incsp is often kept (because + * you often don't know which incsp is the last one and fixstack should find + * them all). Remove unnecessary keeps and IncSP nodes */ + { + ir_node *end = get_irg_end(irg); + int arity = get_irn_arity(end); + int i; + for (i = arity-1; i >= 0; --i) { + ir_node *in = get_irn_n(end, i); + if (!be_is_IncSP(in)) { + continue; + } + + remove_End_keepalive(end, in); + if (get_irn_n_edges(in) == 0) { + sched_remove(in); + kill_node(in); + } + } + } }