X-Git-Url: http://nsz.repo.hu/git/?a=blobdiff_plain;f=ir%2Fbe%2Fbeabi.c;h=e01d3641cb945059c80386fa80677d8ea325d9be;hb=b151d11c50d89b9dffadfb63f7ccfd81ea8db44f;hp=e5eb80f5b822d63f63fb1c6e8cce629efae40405;hpb=270f2356557d43d3e7ea36dacac46cd1e54a902d;p=libfirm diff --git a/ir/be/beabi.c b/ir/be/beabi.c index e5eb80f5b..e01d3641c 100644 --- a/ir/be/beabi.c +++ b/ir/be/beabi.c @@ -55,6 +55,7 @@ #include "beirg.h" #include "bessaconstr.h" #include "bemodule.h" +#include "betranshlp.h" DEBUG_ONLY(static firm_dbg_module_t *dbg;) @@ -86,8 +87,6 @@ struct be_abi_call_t { * The ABI information for the current graph. */ struct be_abi_irg_t { - survive_dce_t *dce_survivor; - be_abi_call_t *call; /**< The ABI call information. */ ir_node *init_sp; /**< The node representing the stack pointer @@ -979,6 +978,7 @@ static int cmp_call_dependency(const void *c1, const void *c2) { ir_node *n1 = *(ir_node **) c1; ir_node *n2 = *(ir_node **) c2; + unsigned h1, h2; /* Classical qsort() comparison function behavior: @@ -993,7 +993,16 @@ static int cmp_call_dependency(const void *c1, const void *c2) return 1; /* The nodes have no depth order, but we need a total order because qsort() - * is not stable. */ + * is not stable. + * + * Additionally, we need to respect transitive dependencies. Consider a + * Call a depending on Call b and an independent Call c. + * We MUST NOT order c > a and b > c. */ + h1 = get_irn_height(ir_heights, n1); + h2 = get_irn_height(ir_heights, n2); + if (h1 < h2) return -1; + if (h1 > h2) return 1; + /* Same height, so use a random (but stable) order */ return get_irn_idx(n1) - get_irn_idx(n2); } @@ -1214,76 +1223,14 @@ static void reg_map_to_arr(reg_node_map_t *res, pmap *reg_map) qsort(res, n, sizeof(res[0]), cmp_regs); } -/** - * Creates a barrier. - */ -static ir_node *create_barrier(ir_node *bl, ir_node **mem, pmap *regs, - int in_req) -{ - int n_regs = pmap_count(regs); - int n; - ir_node *irn; - ir_node **in; - reg_node_map_t *rm; - - in = ALLOCAN(ir_node*, n_regs+1); - rm = ALLOCAN(reg_node_map_t, n_regs); - reg_map_to_arr(rm, regs); - for (n = 0; n < n_regs; ++n) { - in[n] = rm[n].irn; - } - - if (mem) { - in[n++] = *mem; - } - - irn = be_new_Barrier(bl, n, in); - - for (n = 0; n < n_regs; ++n) { - ir_node *pred = rm[n].irn; - const arch_register_t *reg = rm[n].reg; - arch_register_req_type_t add_type = arch_register_req_type_none; - ir_node *proj; - const backend_info_t *info; - - /* stupid workaround for now... as not all nodes report register - * requirements. */ - info = be_get_info(skip_Proj(pred)); - if (info != NULL && info->out_infos != NULL) { - const arch_register_req_t *ireq = arch_get_register_req_out(pred); - if (ireq->type & arch_register_req_type_ignore) - add_type |= arch_register_req_type_ignore; - if (ireq->type & arch_register_req_type_produces_sp) - add_type |= arch_register_req_type_produces_sp; - } - - proj = new_r_Proj(irn, get_irn_mode(pred), n); - be_node_set_reg_class_in(irn, n, reg->reg_class); - if (in_req) { - be_set_constr_single_reg_in(irn, n, reg, - arch_register_req_type_none); - } - be_set_constr_single_reg_out(irn, n, reg, add_type); - arch_set_irn_register(proj, reg); - - pmap_insert(regs, (void *) reg, proj); - } - - if (mem) { - *mem = new_r_Proj(irn, mode_M, n); - } - - return irn; -} - /** * Creates a be_Return for a Return node. * - * @param @env the abi environment - * @param irn the Return node or NULL if there was none - * @param bl the block where the be_Retun should be placed - * @param mem the current memory - * @param n_res number of return results + * @param @env the abi environment + * @param irn the Return node or NULL if there was none + * @param bl the block where the be_Retun should be placed + * @param mem the current memory + * @param n_res number of return results */ static ir_node *create_be_return(be_abi_irg_t *env, ir_node *irn, ir_node *bl, ir_node *mem, int n_res) @@ -1335,7 +1282,6 @@ static ir_node *create_be_return(be_abi_irg_t *env, ir_node *irn, ir_node *bl, be_abi_reg_map_set(reg_map, arch_env->sp, stack); /* Make the Epilogue node and call the arch's epilogue maker. */ - create_barrier(bl, &mem, reg_map, 1); call->cb->epilogue(env->cb, bl, &mem, reg_map); /* @@ -1382,13 +1328,14 @@ static ir_node *create_be_return(be_abi_irg_t *env, ir_node *irn, ir_node *bl, /* we have to pop the shadow parameter in in case of struct returns */ pop = call->pop; ret = be_new_Return(dbgi, irg, bl, n_res, pop, n, in); + arch_irn_add_flags(ret, arch_irn_flags_epilog); /* Set the register classes of the return's parameter accordingly. */ for (i = 0; i < n; ++i) { if (regs[i] == NULL) continue; - be_node_set_reg_class_in(ret, i, regs[i]->reg_class); + be_set_constr_single_reg_in(ret, i, regs[i], arch_register_req_type_none); } /* Free the space of the Epilog's in array and the register <-> proj map. */ @@ -1611,25 +1558,13 @@ static void fix_address_of_parameter_access(be_abi_irg_t *env, ir_graph *irg, */ static void fix_start_block(ir_graph *irg) { - ir_node *initial_X = get_irg_initial_exec(irg); - ir_node *start_block = get_irg_start_block(irg); - const ir_edge_t *edge; + ir_node *initial_X = get_irg_initial_exec(irg); + ir_node *start_block = get_irg_start_block(irg); + ir_node *jmp = new_r_Jmp(start_block); assert(is_Proj(initial_X)); - - foreach_out_edge(initial_X, edge) { - ir_node *block = get_edge_src_irn(edge); - - if (is_Anchor(block)) - continue; - if (block != start_block) { - ir_node *jmp = new_r_Jmp(start_block); - set_Block_cfgpred(block, get_edge_src_pos(edge), jmp); - set_irg_initial_exec(irg, jmp); - return; - } - } - panic("Initial exec has no follow block in %+F", irg); + exchange(initial_X, jmp); + set_irg_initial_exec(irg, new_r_Bad(irg)); } /** @@ -1737,8 +1672,6 @@ static void modify_irg(ir_graph *irg) DBG((dbg, LEVEL_1, "introducing abi on %+F\n", irg)); - /* Must fetch memory here, otherwise the start Barrier gets the wrong - * memory, which leads to loops in the DAG. */ old_mem = get_irg_initial_mem(irg); irp_reserve_resources(irp, IR_RESOURCE_ENTITY_LINK); @@ -1856,6 +1789,8 @@ static void modify_irg(ir_graph *irg) pmap_insert(env->regs, (void *) arch_env->bp, NULL); start_bl = get_irg_start_block(irg); env->start = be_new_Start(NULL, start_bl, pmap_count(env->regs) + 1); + arch_irn_add_flags(env->start, arch_irn_flags_prolog); + set_irg_start(irg, env->start); /* * make proj nodes for the callee save registers. @@ -1896,14 +1831,11 @@ static void modify_irg(ir_graph *irg) /* Generate the Prologue */ fp_reg = call->cb->prologue(env->cb, &mem, env->regs, &stack_layout->initial_bias); - /* do the stack allocation BEFORE the barrier, or spill code - might be added before it */ env->init_sp = be_abi_reg_map_get(env->regs, sp); env->init_sp = be_new_IncSP(sp, start_bl, env->init_sp, BE_STACK_FRAME_SIZE_EXPAND, 0); + arch_irn_add_flags(env->init_sp, arch_irn_flags_prolog); be_abi_reg_map_set(env->regs, sp, env->init_sp); - create_barrier(start_bl, &mem, env->regs, 0); - env->init_sp = be_abi_reg_map_get(env->regs, sp); arch_set_irn_register(env->init_sp, sp); @@ -2197,7 +2129,6 @@ be_abi_irg_t *be_abi_introduce(ir_graph *irg) struct obstack *obst = &birg->obst; unsigned r; - pmap_entry *ent; ir_node *dummy; /* determine allocatable registers */ @@ -2218,7 +2149,6 @@ be_abi_irg_t *be_abi_introduce(ir_graph *irg) be_omit_fp = options->omit_fp; - env->dce_survivor = new_survive_dce(); env->keep_map = pmap_create(); env->call = be_abi_call_new(arch_env->sp->reg_class); arch_env_get_call_abi(arch_env, method_type, env->call); @@ -2257,12 +2187,6 @@ be_abi_irg_t *be_abi_introduce(ir_graph *irg) exchange(dummy, env->init_sp); exchange(old_frame, get_irg_frame(irg)); - /* Make some important node pointers survive the dead node elimination. */ - survive_dce_register_irn(env->dce_survivor, &env->init_sp); - foreach_pmap(env->regs, ent) { - survive_dce_register_irn(env->dce_survivor, (ir_node **) &ent->value); - } - env->call->cb->done(env->cb); env->cb = NULL; return env; @@ -2274,8 +2198,6 @@ void be_abi_free(ir_graph *irg) if (env->call != NULL) be_abi_call_free(env->call); - if (env->dce_survivor != NULL) - free_survive_dce(env->dce_survivor); if (env->regs != NULL) pmap_destroy(env->regs); free(env); @@ -2283,6 +2205,28 @@ void be_abi_free(ir_graph *irg) be_set_irg_abi(irg, NULL); } +/** + * called after nodes have been transformed so some node references can be + * replaced with new nodes + */ +void be_abi_transform_fixup(ir_graph *irg) +{ + be_abi_irg_t *abi = be_get_irg_abi(irg); + pmap *new_regs; + pmap_entry *entry; + if (abi == NULL || abi->regs == NULL) + return; + + new_regs = pmap_create(); + foreach_pmap(abi->regs, entry) { + ir_node *value = (ir_node*)entry->value; + ir_node *transformed = be_transform_node(value); + pmap_insert(new_regs, entry->key, transformed); + } + pmap_destroy(abi->regs); + abi->regs = new_regs; +} + void be_put_allocatable_regs(const ir_graph *irg, const arch_register_class_t *cls, bitset_t *bs) {