X-Git-Url: http://nsz.repo.hu/git/?a=blobdiff_plain;f=ir%2Fbe%2Fbelower.c;h=f2dd1d49e68ed9bbd55a1a56f04eb47dad4a460c;hb=af0b60cf42e54a163d0b83dbab2874ea020bdc0d;hp=16bafc80d172b636a52de544abd973a67fb85f05;hpb=55437d814f031e648187e51ba6e952907f9a480c;p=libfirm diff --git a/ir/be/belower.c b/ir/be/belower.c index 16bafc80d..f2dd1d49e 100644 --- a/ir/be/belower.c +++ b/ir/be/belower.c @@ -178,14 +178,14 @@ static int get_pairidx_for_regidx(reg_pair_t *pairs, int n, int reg_idx, int in_ if (in_out) { for (i = 0; i < n; i++) { /* out register matches */ - if (pairs[i].out_reg->index == reg_idx) + if ((int) pairs[i].out_reg->index == reg_idx) return i; } } else { for (i = 0; i < n; i++) { /* in register matches */ - if (pairs[i].in_reg->index == reg_idx) + if ((int) pairs[i].in_reg->index == reg_idx) return i; } } @@ -309,6 +309,7 @@ static void lower_perm_node(ir_node *irn, void *walk_env) { should be ok. */ sched_point = sched_prev(irn); + DBG((mod, LEVEL_1, "perm: %+F\n", irn)); DBG((mod, LEVEL_1, "sched point is %+F\n", sched_point)); assert(sched_point && "Perm is not scheduled or has no predecessor"); @@ -349,11 +350,6 @@ static void lower_perm_node(ir_node *irn, void *walk_env) { set_Proj_proj(pairs[i].out_node, get_Proj_proj(pairs[i].in_node)); } -#ifdef SCHEDULE_PROJS - /* remove the proj from the schedule */ - sched_remove(pairs[i].out_node); -#endif - /* reroute the edges from the proj to the argument */ exchange(pairs[i].out_node, pairs[i].in_node); //edges_reroute(pairs[i].out_node, pairs[i].in_node, env->birg->irg); @@ -465,25 +461,12 @@ static void lower_perm_node(ir_node *irn, void *walk_env) { /* set as in for next Perm */ pairs[pidx].in_node = res1; } - else { -#ifdef SCHEDULE_PROJS - sched_remove(res1); -#endif - } - -#ifdef SCHEDULE_PROJS - sched_remove(res2); -#endif set_Proj_pred(res2, cpyxchg); set_Proj_proj(res2, 0); set_Proj_pred(res1, cpyxchg); set_Proj_proj(res1, 1); -#ifdef SCHEDULE_PROJS - sched_add_after(sched_point, res1); - sched_add_after(sched_point, res2); -#endif arch_set_irn_register(arch_env, res2, cycle->elems[i + 1]); arch_set_irn_register(arch_env, res1, cycle->elems[i]); @@ -503,10 +486,6 @@ static void lower_perm_node(ir_node *irn, void *walk_env) { arch_set_irn_register(arch_env, cpyxchg, cycle->elems[i + 1]); n_ops++; -#ifdef SCHEDULE_PROJS - /* remove the proj from the schedule */ - sched_remove(res2); -#endif /* exchange copy node and proj */ exchange(res2, cpyxchg); @@ -775,20 +754,15 @@ static void melt_copykeeps(constraint_env_t *cenv) { new_ck = be_new_CopyKeep(entry->cls, irg, get_nodes_block(ref), be_get_CopyKeep_op(ref), n_melt, new_ck_in, get_irn_mode(ref)); #endif /* KEEP_ALIVE_COPYKEEP_HACK */ - /* set register class for all keeped inputs */ + /* set register class for all kept inputs */ for (j = 1; j <= n_melt; ++j) be_node_set_reg_class(new_ck, j, entry->cls); ir_nodeset_insert(&entry->copies, new_ck); /* find scheduling point */ - if (get_irn_mode(ref_mode_T) == mode_T) { - /* walk along the Projs */ - for (sched_pt = sched_next(ref_mode_T); is_Proj(sched_pt) || be_is_Keep(sched_pt) || be_is_CopyKeep(sched_pt); sched_pt = sched_next(sched_pt)) - /* just walk along the schedule until a non-Proj/Keep/CopyKeep node is found*/ ; - } - else { - sched_pt = ref_mode_T; + for (sched_pt = sched_next(ref_mode_T); be_is_Keep(sched_pt) || be_is_CopyKeep(sched_pt); sched_pt = sched_next(sched_pt)) { + /* just walk along the schedule until a non-Keep/CopyKeep node is found */ } sched_add_before(sched_pt, new_ck); @@ -903,17 +877,20 @@ static int push_through_perm(ir_node *perm, void *data) ir_graph *irg = get_irn_irg(perm); ir_node *bl = get_nodes_block(perm); - int n = get_irn_arity(perm); - int *map = alloca(n * sizeof(map[0])); - ir_node **projs = alloca(n * sizeof(projs[0])); - bitset_t *keep = bitset_alloca(n); + ir_node *node; + int arity = get_irn_arity(perm); + int *map; + int *proj_map; + bitset_t *moved = bitset_alloca(arity); + int n_moved; + int new_size; ir_node *frontier = sched_first(bl); FIRM_DBG_REGISTER(firm_dbg_module_t *mod, "firm.be.lower.permmove"); - int i, new_size, n_keep; + int i, n; const ir_edge_t *edge; - ir_node *last_proj, *irn; - const arch_register_class_t *cls; + ir_node *last_proj = NULL, *irn; + const arch_register_class_t *cls = NULL; DBG((mod, LEVEL_1, "perm move %+F irg %+F\n", perm, irg)); @@ -944,84 +921,100 @@ found_front: DBG((mod, LEVEL_2, "\tfrontier: %+F\n", frontier)); - foreach_out_edge (perm, edge) { - ir_node *proj = get_edge_src_irn(edge); - int nr = get_Proj_proj(proj); - ir_node *op = get_irn_n(perm, nr); - - assert(nr < n); - - /* we will need the last Proj as an insertion point - * for the instruction(s) pushed through the Perm */ - if (sched_comes_after(last_proj, proj)) - last_proj = proj; - - projs[nr] = proj; - - bitset_set(keep, nr); - if (!is_Proj(op) && get_nodes_block(op) == bl - && (op == frontier || sched_comes_after(frontier, op))) { - for (i = get_irn_arity(op) - 1; i >= 0; --i) { - ir_node *opop = get_irn_n(op, i); - if (!arch_irn_consider_in_reg_alloc(aenv, cls, opop)) { - bitset_clear(keep, nr); - break; - } + node = sched_prev(perm); + n_moved = 0; + while(!sched_is_begin(node)) { + const arch_register_req_t *req; + int input = -1; + ir_node *proj; + + foreach_out_edge(perm, edge) { + ir_node *out = get_edge_src_irn(edge); + int pn = get_Proj_proj(out); + ir_node *in = get_irn_n(perm, pn); + if(node == in) { + proj = out; + input = pn; + break; } } - } - - n_keep = bitset_popcnt(keep); - - /* well, we could not push enything through the perm */ - if (n_keep == n) - return 1; - - assert(is_Proj(last_proj)); - - DBG((mod, LEVEL_2, "\tkeep: %d, total: %d, mask: %b\n", n_keep, n, keep)); - last_proj = sched_next(last_proj); - for (new_size = 0, i = 0; i < n; ++i) { - ir_node *proj = projs[i]; - - if (bitset_is_set(keep, i)) { - map[i] = new_size++; - set_Proj_proj(proj, map[i]); - DBG((mod, LEVEL_1, "\targ %d remap to %d\n", i, map[i])); + /* it wasn't an input to the perm, we can't do anything more */ + if(input < 0) + break; + if(!sched_comes_after(frontier, node)) + break; + if(arch_irn_is(aenv, node, modify_flags)) + break; + if(is_Proj(node)) { + req = arch_get_register_req(aenv, get_Proj_pred(node), + -1 - get_Proj_proj(node)); + } else { + req = arch_get_register_req(aenv, node, -1); + } + if(req->type != arch_register_req_type_normal) + break; + for(i = get_irn_arity(node) - 1; i >= 0; --i) { + ir_node *opop = get_irn_n(node, i); + if (arch_irn_consider_in_reg_alloc(aenv, cls, opop)) { + break; + } } + if(i >= 0) + break; - else { - ir_node *move = get_irn_n(perm, i); + DBG((mod, LEVEL_2, "\tmoving %+F after %+F, killing %+F\n", node, perm, proj)); - DBG((mod, LEVEL_2, "\tmoving %+F before %+F, killing %+F\n", move, last_proj, proj)); + /* move the movable node in front of the Perm */ + sched_remove(node); + sched_add_after(perm, node); - /* move the movable node in front of the Perm */ - sched_remove(move); - sched_add_before(last_proj, move); + /* give it the proj's register */ + arch_set_irn_register(aenv, node, arch_get_irn_register(aenv, proj)); - /* give it the proj's register */ - arch_set_irn_register(aenv, move, arch_get_irn_register(aenv, proj)); + /* reroute all users of the proj to the moved node. */ + edges_reroute(proj, node, irg); - /* reroute all users of the proj to the moved node. */ - edges_reroute(proj, move, irg); + /* and kill it */ + set_Proj_pred(proj, new_Bad()); + be_kill_node(proj); -#ifdef SCHEDULE_PROJS - /* remove the proj from the schedule. */ - sched_remove(proj); -#endif + bitset_set(moved, input); + n_moved++; - /* and like it to bad so it is no more in the use array of the perm */ - set_Proj_pred(proj, get_irg_bad(irg)); + node = sched_prev(node); + } - map[i] = -1; - } + /* well, we could not push anything through the perm */ + if(n_moved == 0) + return 1; + new_size = arity - n_moved; + if(new_size == 0) { + return 0; } - if (n_keep > 0) - be_Perm_reduce(perm, new_size, map); + map = alloca(new_size * sizeof(map[0])); + proj_map = alloca(arity * sizeof(proj_map[0])); + memset(proj_map, -1, sizeof(proj_map[0])); + n = 0; + for(i = 0; i < arity; ++i) { + if(bitset_is_set(moved, i)) + continue; + map[n] = i; + proj_map[i] = n; + n++; + } + assert(n == new_size); + foreach_out_edge(perm, edge) { + ir_node *proj = get_edge_src_irn(edge); + int pn = get_Proj_proj(proj); + pn = proj_map[pn]; + assert(pn >= 0); + set_Proj_proj(proj, pn); + } - return n_keep > 0; + be_Perm_reduce(perm, new_size, map); + return 1; } /** @@ -1031,15 +1024,18 @@ found_front: * @param walk_env The walker environment */ static void lower_nodes_after_ra_walker(ir_node *irn, void *walk_env) { - if (! is_Block(irn) && ! is_Proj(irn)) { - if (be_is_Perm(irn)) { - int perm_stayed = push_through_perm(irn, walk_env); - if (perm_stayed) - lower_perm_node(irn, walk_env); - } - } + int perm_stayed; - return; + if (is_Block(irn) || is_Proj(irn)) + return; + if (!be_is_Perm(irn)) + return; + + perm_stayed = push_through_perm(irn, walk_env); + if (!perm_stayed) + return; + + lower_perm_node(irn, walk_env); } /**