From: Matthias Braun Date: Mon, 9 Aug 2010 14:53:04 +0000 (+0000) Subject: allow ignore registers as inputs of Phis; cleanup bessadestr.c X-Git-Url: http://nsz.repo.hu/git/?a=commitdiff_plain;h=83bf742ecd99bb63cc25e159f578b3d90bb3f096;p=libfirm allow ignore registers as inputs of Phis; cleanup bessadestr.c [r27909] --- diff --git a/ir/be/bearch.h b/ir/be/bearch.h index 5207c79be..419bc7eff 100644 --- a/ir/be/bearch.h +++ b/ir/be/bearch.h @@ -842,7 +842,7 @@ static inline void arch_set_out_register_req(ir_node *node, int pos, * are not marked as ignore. * Executes @p code for each definition. */ -#define be_foreach_definition(node, cls, value, code) \ +#define be_foreach_definition_(node, cls, value, code) \ do { \ if (get_irn_mode(node) == mode_T) { \ const ir_edge_t *edge_; \ @@ -852,18 +852,22 @@ static inline void arch_set_out_register_req(ir_node *node, int pos, req_ = arch_get_register_req_out(value); \ if (req_->cls != cls) \ continue; \ - if (req_->type & arch_register_req_type_ignore) \ - continue; \ code \ } \ } else { \ const arch_register_req_t *req_ = arch_get_register_req_out(node); \ value = node; \ - if (req_->cls == cls \ - && !(req_->type & arch_register_req_type_ignore)) { \ + if (req_->cls == cls) { \ code \ } \ } \ } while (0) +#define be_foreach_definition(node, cls, value, code) \ + be_foreach_definition_(node, cls, value, \ + if (req_->type & arch_register_req_type_ignore) \ + continue; \ + code \ + ) + #endif diff --git a/ir/be/beprefalloc.c b/ir/be/beprefalloc.c index 451bf0ea8..1ab4e3cc9 100644 --- a/ir/be/beprefalloc.c +++ b/ir/be/beprefalloc.c @@ -368,8 +368,9 @@ static void analyze_block(ir_node *block, void *data) info = get_allocation_info(node); for (i = 0; i < arity; ++i) { - ir_node *op = get_irn_n(node, i); - if (!arch_irn_consider_in_reg_alloc(cls, op)) + ir_node *op = get_irn_n(node, i); + const arch_register_req_t *req = arch_get_register_req_out(op); + if (req->cls != cls) continue; /* last usage of a value? */ @@ -767,8 +768,6 @@ static void assign_reg(const ir_node *block, ir_node *node, unsigned r; assert(!is_Phi(node)); - assert(arch_irn_consider_in_reg_alloc(cls, node)); - /* preassigned register? */ reg = arch_get_irn_register(node); if (reg != NULL) { @@ -777,10 +776,12 @@ static void assign_reg(const ir_node *block, ir_node *node, return; } - /* give should_be_same boni */ - info = get_allocation_info(node); - req = arch_get_register_req_out(node); + req = arch_get_register_req_out(node); + /* ignore reqs must be preassigned */ + assert (! (req->type & arch_register_req_type_ignore)); + /* give should_be_same boni */ + info = get_allocation_info(node); in_node = skip_Proj(node); if (req->type & arch_register_req_type_should_be_same) { float weight = (float)get_block_execfreq(execfreqs, block); @@ -1042,10 +1043,10 @@ static void permute_values(ir_nodeset_t *live_nodes, ir_node *before, */ static void free_last_uses(ir_nodeset_t *live_nodes, ir_node *node) { - allocation_info_t *info = get_allocation_info(node); - const unsigned *last_uses = info->last_uses; - int arity = get_irn_arity(node); - int i; + allocation_info_t *info = get_allocation_info(node); + const unsigned *last_uses = info->last_uses; + int arity = get_irn_arity(node); + int i; for (i = 0; i < arity; ++i) { ir_node *op; @@ -1301,7 +1302,7 @@ static void add_phi_permutations(ir_node *block, int p) unsigned *permutation; ir_node **old_assignments; bool need_permutation; - ir_node *node; + ir_node *phi; ir_node *pred = get_Block_cfgpred_block(block, p); block_info_t *pred_info = get_block_info(pred); @@ -1317,29 +1318,36 @@ static void add_phi_permutations(ir_node *block, int p) /* check phi nodes */ need_permutation = false; - node = sched_first(block); - for ( ; is_Phi(node); node = sched_next(node)) { + phi = sched_first(block); + for ( ; is_Phi(phi); phi = sched_next(phi)) { const arch_register_t *reg; + const arch_register_t *op_reg; int regn; int a; ir_node *op; - if (!arch_irn_consider_in_reg_alloc(cls, node)) - continue; - - op = get_Phi_pred(node, p); - if (!arch_irn_consider_in_reg_alloc(cls, op)) + if (!arch_irn_consider_in_reg_alloc(cls, phi)) continue; - a = find_value_in_block_info(pred_info, op); + op = get_Phi_pred(phi, p); + a = find_value_in_block_info(pred_info, op); assert(a >= 0); - reg = arch_get_irn_register(node); + reg = arch_get_irn_register(phi); regn = arch_register_get_index(reg); - if (regn != a) { - permutation[regn] = a; - need_permutation = true; - } + /* same register? nothing to do */ + if (regn == a) + continue; + + op = pred_info->assignments[a]; + op_reg = arch_get_irn_register(op); + /* virtual or joker registers are ok too */ + if ((op_reg->type & arch_register_type_joker) + || (op_reg->type & arch_register_type_virtual)) + continue; + + permutation[regn] = a; + need_permutation = true; } if (need_permutation) { @@ -1347,30 +1355,27 @@ static void add_phi_permutations(ir_node *block, int p) old_assignments = assignments; assignments = pred_info->assignments; permute_values(NULL, be_get_end_of_block_insertion_point(pred), - permutation); + permutation); assignments = old_assignments; } /* change phi nodes to use the copied values */ - node = sched_first(block); - for ( ; is_Phi(node); node = sched_next(node)) { + phi = sched_first(block); + for ( ; is_Phi(phi); phi = sched_next(phi)) { int a; ir_node *op; - if (!arch_irn_consider_in_reg_alloc(cls, node)) + if (!arch_irn_consider_in_reg_alloc(cls, phi)) continue; - op = get_Phi_pred(node, p); - /* no need to do anything for Unknown inputs */ - if (!arch_irn_consider_in_reg_alloc(cls, op)) - continue; + op = get_Phi_pred(phi, p); /* we have permuted all values into the correct registers so we can simply query which value occupies the phis register in the predecessor */ - a = arch_register_get_index(arch_get_irn_register(node)); + a = arch_register_get_index(arch_get_irn_register(phi)); op = pred_info->assignments[a]; - set_Phi_pred(node, p, op); + set_Phi_pred(phi, p, op); } } @@ -1536,14 +1541,14 @@ static void assign_phi_registers(ir_node *block) */ static void allocate_coalesce_block(ir_node *block, void *data) { - int i; - ir_nodeset_t live_nodes; - ir_node *node; - int n_preds; - block_info_t *block_info; - block_info_t **pred_block_infos; - ir_node **phi_ins; - unsigned *forbidden_regs; /**< collects registers which must + int i; + ir_nodeset_t live_nodes; + ir_node *node; + int n_preds; + block_info_t *block_info; + block_info_t **pred_block_infos; + ir_node **phi_ins; + unsigned *forbidden_regs; /**< collects registers which must not be used for optimistic splits */ (void) data; @@ -1556,8 +1561,8 @@ static void allocate_coalesce_block(ir_node *block, void *data) ir_nodeset_init(&live_nodes); /* gather regalloc infos of predecessor blocks */ - n_preds = get_Block_n_cfgpreds(block); - pred_block_infos = ALLOCAN(block_info_t*, n_preds); + n_preds = get_Block_n_cfgpreds(block); + pred_block_infos = ALLOCAN(block_info_t*, n_preds); for (i = 0; i < n_preds; ++i) { ir_node *pred = get_Block_cfgpred_block(block, i); block_info_t *pred_info = get_block_info(pred); @@ -1568,14 +1573,26 @@ static void allocate_coalesce_block(ir_node *block, void *data) /* collect live-in nodes and preassigned values */ be_lv_foreach(lv, block, be_lv_state_in, i) { - const arch_register_t *reg; - int p; - bool need_phi = false; + bool need_phi = false; + const arch_register_req_t *req; + const arch_register_t *reg; + int p; node = be_lv_get_irn(lv, block, i); - if (!arch_irn_consider_in_reg_alloc(cls, node)) + req = arch_get_register_req_out(node); + if (req->cls != cls) continue; + if (req->type & arch_register_req_type_ignore) { + allocation_info_t *info = get_allocation_info(node); + info->current_value = node; + + reg = arch_get_irn_register(node); + assert(reg != NULL); /* ignore values must be preassigned */ + use_reg(node, reg); + continue; + } + /* check all predecessors for this value, if it is not everywhere the same or unknown then we have to construct a phi (we collect the potential phi inputs here) */ @@ -1691,8 +1708,7 @@ static void allocate_coalesce_block(ir_node *block, void *data) free_last_uses(&live_nodes, node); /* assign output registers */ - /* TODO: 2 phases: first: pre-assigned ones, 2nd real regs */ - be_foreach_definition(node, cls, value, + be_foreach_definition_(node, cls, value, assign_reg(block, value, forbidden_regs); ); } diff --git a/ir/be/bessadestr.c b/ir/be/bessadestr.c index a1f2f7bdf..cb917ac44 100644 --- a/ir/be/bessadestr.c +++ b/ir/be/bessadestr.c @@ -137,13 +137,9 @@ static void insert_all_perms_walker(ir_node *bl, void *data) */ for (phi = get_irn_link(bl); phi; phi = get_irn_link(phi)) { ir_node *arg = get_irn_n(phi, i); - const arch_register_req_t *req = arch_get_register_req_out(arg); unsigned hash; perm_proj_t templ; - if (req->type & arch_register_req_type_ignore) - continue; - hash = hash_irn(arg); templ.arg = arg; pp = set_find(arg_set, &templ, sizeof(templ), hash); @@ -251,13 +247,9 @@ static void set_regs_or_place_dupls_walker(ir_node *bl, void *data) /* process all arguments of the phi */ for (i = 0, max = get_irn_arity(phi); i < max; ++i) { ir_node *arg = get_irn_n(phi, i); - const arch_register_req_t *req = arch_get_register_req_out(arg); const arch_register_t *arg_reg; ir_node *arg_block; - if (req->type & arch_register_req_type_ignore) - continue; - arg_block = get_Block_cfgpred_block(phi_block, i); arg_reg = get_reg(arg); @@ -265,6 +257,15 @@ static void set_regs_or_place_dupls_walker(ir_node *bl, void *data) DBG((dbg, LEVEL_1, " for %+F(%s) -- %+F(%s)\n", phi, phi_reg->name, arg, arg_reg->name)); + if (phi_reg == arg_reg + || (arg_reg->type & arch_register_type_joker) + || (arg_reg->type & arch_register_type_virtual)) { + /* Phi and arg have the same register, so pin and continue */ + pin_irn(arg, phi_block); + DBG((dbg, LEVEL_1, " arg has same reg: pin %+F(%s)\n", arg, get_reg(arg)->name)); + continue; + } + if (be_values_interfere(lv, phi, arg)) { /* Insert a duplicate in arguments block, @@ -275,19 +276,6 @@ static void set_regs_or_place_dupls_walker(ir_node *bl, void *data) */ ir_node *dupl = be_new_Copy(cls, arg_block, arg); - /* this is commented out because it will fail in case of unknown float */ -#if 0 - ir_mode *m_phi = get_irn_mode(phi), *m_dupl = get_irn_mode(dupl); - - /* - Conv signed <-> unsigned is killed on ia32 - check for: (both int OR both float) AND equal mode sizes - */ - assert(((mode_is_int(m_phi) && mode_is_int(m_dupl)) || - (mode_is_float(m_phi) && mode_is_float(m_dupl))) && - (get_mode_size_bits(m_phi) == get_mode_size_bits(m_dupl))); -#endif /* if 0 */ - set_irn_n(phi, i, dupl); set_reg(dupl, phi_reg); sched_add_after(sched_skip(sched_last(arg_block), 0, sched_skip_cf_predicator, NULL), dupl); @@ -298,13 +286,6 @@ static void set_regs_or_place_dupls_walker(ir_node *bl, void *data) continue; /* with next argument */ } - if (phi_reg == arg_reg) { - /* Phi and arg have the same register, so pin and continue */ - pin_irn(arg, phi_block); - DBG((dbg, LEVEL_1, " arg has same reg: pin %+F(%s)\n", arg, get_reg(arg)->name)); - continue; - } - DBG((dbg, LEVEL_1, " they do not interfere\n")); assert(is_Proj(arg)); /* @@ -346,20 +327,6 @@ static void set_regs_or_place_dupls_walker(ir_node *bl, void *data) ir_node *dupl = be_new_Copy(cls, arg_block, arg); ir_node *ins; - /* this is commented out because it will fail in case of unknown float */ -#if 0 - ir_mode *m_phi = get_irn_mode(phi); - ir_mode *m_dupl = get_irn_mode(dupl); - - /* - Conv signed <-> unsigned is killed on ia32 - check for: (both int OR both float) AND equal mode sizes - */ - assert(((mode_is_int(m_phi) && mode_is_int(m_dupl)) || - (mode_is_float(m_phi) && mode_is_float(m_dupl))) && - (get_mode_size_bits(m_phi) == get_mode_size_bits(m_dupl))); -#endif /* if 0 */ - set_irn_n(phi, i, dupl); set_reg(dupl, phi_reg); /* skip the Perm's Projs and insert the copies behind. */