- use ir_nodemap_t instead of pset: This probably
[libfirm] / ir / be / belower.c
index 4309966..ee09f6b 100644 (file)
@@ -24,9 +24,7 @@
  * @date        14.12.2005
  * @version     $Id$
  */
-#ifdef HAVE_CONFIG_H
 #include "config.h"
-#endif
 
 #include <stdlib.h>
 
 #include "irhooks.h"
 #include "xmalloc.h"
 #include "irnodeset.h"
+#include "irnodemap.h"
 #include "irgmod.h"
 #include "iredges_t.h"
 #include "irgwalk.h"
+#include "array_t.h"
 
 #include "bearch_t.h"
 #include "belower.h"
@@ -49,9 +49,8 @@
 
 #undef KEEP_ALIVE_COPYKEEP_HACK
 
-/** Associates an op with it's copy and CopyKeep. */
+/** Associates an ir_node with it's copy and CopyKeep. */
 typedef struct {
-       ir_node *op;         /**< an irn which must be different */
        ir_nodeset_t copies; /**< all non-spillable copies of this irn */
        const arch_register_class_t *cls;
 } op_copy_assoc_t;
@@ -59,7 +58,7 @@ typedef struct {
 /** Environment for constraints. */
 typedef struct {
        be_irg_t       *birg;
-       pset           *op_set;
+       ir_nodemap_t   op_set;
        struct obstack obst;
        DEBUG_ONLY(firm_dbg_module_t *dbg;)
 } constraint_env_t;
@@ -67,7 +66,6 @@ typedef struct {
 /** Lowering walker environment. */
 typedef struct _lower_env_t {
        be_irg_t         *birg;
-       const arch_env_t *arch_env;
        unsigned          do_copy : 1;
        DEBUG_ONLY(firm_dbg_module_t *dbg_module;)
 } lower_env_t;
@@ -97,14 +95,6 @@ typedef struct _perm_cycle_t {
        perm_type_t             type;        /**< type (CHAIN or CYCLE) */
 } perm_cycle_t;
 
-/** Compare the two operands. */
-static int cmp_op_copy_assoc(const void *a, const void *b) {
-       const op_copy_assoc_t *op1 = a;
-       const op_copy_assoc_t *op2 = b;
-
-       return op1->op != op2->op;
-}
-
 /** Compare the in registers of two register pairs. */
 static int compare_reg_pair(const void *a, const void *b) {
        const reg_pair_t *pair_a = a;
@@ -224,7 +214,7 @@ static perm_cycle_t *get_perm_cycle(perm_cycle_t *cycle, reg_pair_t *pairs, int
        }
 
        /* assume worst case: all remaining pairs build a cycle or chain */
-       cycle->elems    = xcalloc((n - n_pairs_done) * 2, sizeof(cycle->elems[0]));
+       cycle->elems    = XMALLOCNZ(const arch_register_t*, (n - n_pairs_done) * 2);
        cycle->n_elems  = 2;  /* initial number of elements is 2 */
        cycle->elems[0] = pairs[start].in_reg;
        cycle->elems[1] = pairs[start].out_reg;
@@ -282,20 +272,17 @@ static perm_cycle_t *get_perm_cycle(perm_cycle_t *cycle, reg_pair_t *pairs, int
 static void lower_perm_node(ir_node *irn, void *walk_env) {
        ir_graph        *irg = get_irn_irg(irn);
        const arch_register_class_t *reg_class;
-       const arch_env_t            *arch_env;
        lower_env_t     *env         = walk_env;
        int             real_size    = 0;
        int             keep_perm    = 0;
        int             n, i, pn, do_copy, j, n_ops;
        reg_pair_t      *pairs;
        const ir_edge_t *edge;
-       perm_cycle_t    *cycle;
        ir_node         *sched_point, *block, *in[2];
        ir_node         *arg1, *arg2, *res1, *res2;
        ir_node         *cpyxchg = NULL;
        DEBUG_ONLY(firm_dbg_module_t *mod;)
 
-       arch_env = env->arch_env;
        do_copy  = env->do_copy;
        DEBUG_ONLY(mod = env->dbg_module;)
        block    = get_nodes_block(irn);
@@ -314,7 +301,7 @@ static void lower_perm_node(ir_node *irn, void *walk_env) {
        n = get_irn_arity(irn);
        assert(n == get_irn_n_edges(irn) && "perm's in and out numbers different");
 
-       reg_class = arch_get_irn_register(arch_env, get_irn_n(irn, 0))->reg_class;
+       reg_class = arch_get_irn_register(get_irn_n(irn, 0))->reg_class;
        pairs     = alloca(n * sizeof(pairs[0]));
 
        /* build the list of register pairs (in, out) */
@@ -324,8 +311,8 @@ static void lower_perm_node(ir_node *irn, void *walk_env) {
                pn                = get_Proj_proj(pairs[i].out_node);
                pairs[i].in_node  = get_irn_n(irn, pn);
 
-               pairs[i].in_reg  = arch_get_irn_register(arch_env, pairs[i].in_node);
-               pairs[i].out_reg = arch_get_irn_register(arch_env, pairs[i].out_node);
+               pairs[i].in_reg  = arch_get_irn_register(pairs[i].in_node);
+               pairs[i].out_reg = arch_get_irn_register(pairs[i].out_node);
 
                pairs[i].checked = 0;
                i++;
@@ -364,15 +351,15 @@ static void lower_perm_node(ir_node *irn, void *walk_env) {
 
        real_size = n - get_n_checked_pairs(pairs, n);
 
-       be_do_stat_perm(reg_class->name, reg_class->n_regs, irn, block, n, real_size);
-
        /* check for cycles and chains */
        while (get_n_checked_pairs(pairs, n) < n) {
+               perm_cycle_t *cycle;
+
                i = n_ops = 0;
 
                /* go to the first not-checked pair */
                while (pairs[i].checked) i++;
-               cycle = xcalloc(1, sizeof(*cycle));
+               cycle = XMALLOCZ(perm_cycle_t);
                cycle = get_perm_cycle(cycle, pairs, n, i);
 
                DB((mod, LEVEL_1, "%+F: following %s created:\n  ", irn, cycle->type == PERM_CHAIN ? "chain" : "cycle"));
@@ -465,8 +452,8 @@ static void lower_perm_node(ir_node *irn, void *walk_env) {
                                set_Proj_pred(res1, cpyxchg);
                                set_Proj_proj(res1, 1);
 
-                               arch_set_irn_register(arch_env, res2, cycle->elems[i + 1]);
-                               arch_set_irn_register(arch_env, res1, cycle->elems[i]);
+                               arch_set_irn_register(res2, cycle->elems[i + 1]);
+                               arch_set_irn_register(res1, cycle->elems[i]);
 
                                /* insert the copy/exchange node in schedule after the magic schedule node (see above) */
                                sched_add_after(sched_point, cpyxchg);
@@ -481,7 +468,7 @@ static void lower_perm_node(ir_node *irn, void *walk_env) {
                                        irn, arg1, cycle->elems[i]->name, res2, cycle->elems[i + 1]->name));
 
                                cpyxchg = be_new_Copy(reg_class, irg, block, arg1);
-                               arch_set_irn_register(arch_env, cpyxchg, cycle->elems[i + 1]);
+                               arch_set_irn_register(cpyxchg, cycle->elems[i + 1]);
                                n_ops++;
 
                                /* exchange copy node and proj */
@@ -495,8 +482,6 @@ static void lower_perm_node(ir_node *irn, void *walk_env) {
                        }
                }
 
-               be_do_stat_permcycle(reg_class->name, irn, block, cycle->type == PERM_CHAIN, cycle->n_elems, n_ops);
-
                free((void *) cycle->elems);
                free(cycle);
        }
@@ -523,16 +508,16 @@ static INLINE ir_node *belower_skip_proj(ir_node *irn) {
        return irn;
 }
 
-static ir_node *find_copy(constraint_env_t *env, ir_node *irn, ir_node *op) {
-       const arch_env_t *arch_env = be_get_birg_arch_env(env->birg);
-       ir_node          *block    = get_nodes_block(irn);
-       ir_node          *cur_node;
+static ir_node *find_copy(ir_node *irn, ir_node *op)
+{
+       ir_node *block    = get_nodes_block(irn);
+       ir_node *cur_node;
 
        for (cur_node = sched_prev(irn);
                ! is_Block(cur_node) && be_is_Copy(cur_node) && get_nodes_block(cur_node) == block;
                cur_node = sched_prev(cur_node))
        {
-               if (be_get_Copy_op(cur_node) == op && arch_irn_is(arch_env, cur_node, dont_spill))
+               if (be_get_Copy_op(cur_node) == op && arch_irn_is(cur_node, dont_spill))
                        return cur_node;
        }
 
@@ -542,15 +527,15 @@ static ir_node *find_copy(constraint_env_t *env, ir_node *irn, ir_node *op) {
 static void gen_assure_different_pattern(ir_node *irn, ir_node *other_different, constraint_env_t *env) {
        be_irg_t                    *birg     = env->birg;
        ir_graph                    *irg      = be_get_birg_irg(birg);
-       pset                        *op_set   = env->op_set;
-       const arch_env_t            *arch_env = be_get_birg_arch_env(birg);
+       ir_nodemap_t                *op_set   = &env->op_set;
        ir_node                     *block    = get_nodes_block(irn);
-       const arch_register_class_t *cls      = arch_get_irn_reg_class(arch_env, other_different, -1);
+       const arch_register_class_t *cls      = arch_get_irn_reg_class(other_different, -1);
        ir_node                     *in[2], *keep, *cpy;
-       op_copy_assoc_t             key, *entry;
+       op_copy_assoc_t             *entry;
        DEBUG_ONLY(firm_dbg_module_t *mod     = env->dbg;)
 
-       if (arch_irn_is(arch_env, other_different, ignore) || ! mode_is_datab(get_irn_mode(other_different))) {
+       if (arch_irn_is(other_different, ignore) ||
+                       !mode_is_datab(get_irn_mode(other_different))) {
                DBG((mod, LEVEL_1, "ignore constraint for %+F because other_irn is ignore or not a datab node\n", irn));
                return;
        }
@@ -561,7 +546,7 @@ static void gen_assure_different_pattern(ir_node *irn, ir_node *other_different,
        /* The copy is optimized later if not needed         */
 
        /* check if already exists such a copy in the schedule immediately before */
-       cpy = find_copy(env, belower_skip_proj(irn), other_different);
+       cpy = find_copy(belower_skip_proj(irn), other_different);
        if (! cpy) {
                cpy = be_new_Copy(cls, irg, block, other_different);
                be_node_set_flags(cpy, BE_OUT_POS(0), arch_irn_flags_dont_spill);
@@ -592,15 +577,14 @@ static void gen_assure_different_pattern(ir_node *irn, ir_node *other_different,
                sched_add_before(belower_skip_proj(irn), cpy);
        sched_add_after(irn, keep);
 
-       /* insert the other different and it's copies into the set */
-       key.op = other_different;
-       entry  = pset_find(op_set, &key, hash_irn(other_different));
-
+       /* insert the other different and it's copies into the map */
+       entry = ir_nodemap_get(op_set, other_different);
        if (! entry) {
-               entry         = obstack_alloc(&env->obst, sizeof(*entry));
+               entry      = obstack_alloc(&env->obst, sizeof(*entry));
+               entry->cls = cls;
                ir_nodeset_init(&entry->copies);
-               entry->op     = other_different;
-               entry->cls    = cls;
+
+               ir_nodemap_insert(op_set, other_different, entry);
        }
 
        /* insert copy */
@@ -610,8 +594,6 @@ static void gen_assure_different_pattern(ir_node *irn, ir_node *other_different,
        if (be_is_CopyKeep(keep)) {
                ir_nodeset_insert(&entry->copies, keep);
        }
-
-       pset_insert(op_set, entry, hash_irn(other_different));
 }
 
 /**
@@ -619,11 +601,8 @@ static void gen_assure_different_pattern(ir_node *irn, ir_node *other_different,
  * then to assure the constraint.
  */
 static void assure_different_constraints(ir_node *irn, constraint_env_t *env) {
-       const arch_register_req_t *req;
-       const arch_env_t          *arch_env    = be_get_birg_arch_env(env->birg);
        ir_node                   *skipped_irn = belower_skip_proj(irn);
-
-       req = arch_get_register_req(arch_env, irn, -1);
+       const arch_register_req_t *req         = arch_get_register_req(irn, -1);
 
        if (arch_register_req_is(req, must_be_different)) {
                const unsigned other = req->other_different;
@@ -675,10 +654,12 @@ static void assure_constraints_walker(ir_node *irn, void *walk_env) {
 static void melt_copykeeps(constraint_env_t *cenv) {
        be_irg_t *birg = cenv->birg;
        ir_graph *irg  = be_get_birg_irg(birg);
-       op_copy_assoc_t *entry;
+       ir_nodemap_iterator_t map_iter;
+       ir_nodemap_entry_t    map_entry;
 
        /* for all */
-       foreach_pset(cenv->op_set, entry) {
+       foreach_ir_nodemap(&cenv->op_set, map_entry, map_iter) {
+               op_copy_assoc_t *entry = map_entry.data;
                int     idx, num_ck;
                ir_node *cp;
                struct obstack obst;
@@ -794,16 +775,16 @@ static void melt_copykeeps(constraint_env_t *cenv) {
  * @param birg  The birg structure containing the irg
  */
 void assure_constraints(be_irg_t *birg) {
-       ir_graph         *irg      = be_get_birg_irg(birg);
-       const arch_env_t *arch_env = be_get_birg_arch_env(birg);
-       constraint_env_t cenv;
-       op_copy_assoc_t  *entry;
-       ir_node          **nodes;
+       ir_graph              *irg = be_get_birg_irg(birg);
+       constraint_env_t      cenv;
+       ir_node               **nodes;
+       ir_nodemap_iterator_t map_iter;
+       ir_nodemap_entry_t    map_entry;
        FIRM_DBG_REGISTER(firm_dbg_module_t *mod, "firm.be.lower.constr");
 
        DEBUG_ONLY(cenv.dbg = mod;)
        cenv.birg   = birg;
-       cenv.op_set = new_pset(cmp_op_copy_assoc, 16);
+       ir_nodemap_init(&cenv.op_set);
        obstack_init(&cenv.obst);
 
        irg_walk_blkwise_graph(irg, NULL, assure_constraints_walker, &cenv);
@@ -814,7 +795,8 @@ void assure_constraints(be_irg_t *birg) {
        melt_copykeeps(&cenv);
 
        /* for all */
-       foreach_pset(cenv.op_set, entry) {
+       foreach_ir_nodemap(&cenv.op_set, map_entry, map_iter) {
+               op_copy_assoc_t *entry = map_entry.data;
                int     n;
                ir_node *cp;
                ir_nodeset_iterator_t iter;
@@ -824,7 +806,7 @@ void assure_constraints(be_irg_t *birg) {
                nodes = alloca(n * sizeof(nodes[0]));
 
                /* put the node in an array */
-               DBG((mod, LEVEL_1, "introduce copies for %+F ", entry->op));
+               DBG((mod, LEVEL_1, "introduce copies for %+F ", map_entry.node));
 
                /* collect all copies */
                n = 0;
@@ -837,9 +819,9 @@ void assure_constraints(be_irg_t *birg) {
 
                /* introduce the copies for the operand and it's copies */
                be_ssa_construction_init(&senv, birg);
-               be_ssa_construction_add_copy(&senv, entry->op);
+               be_ssa_construction_add_copy(&senv, map_entry.node);
                be_ssa_construction_add_copies(&senv, nodes, n);
-               be_ssa_construction_fix_users(&senv, entry->op);
+               be_ssa_construction_fix_users(&senv, map_entry.node);
                be_ssa_construction_destroy(&senv);
 
                /* Could be that not all CopyKeeps are really needed, */
@@ -849,7 +831,7 @@ void assure_constraints(be_irg_t *birg) {
                                ir_node *keep;
                                int     n = get_irn_arity(cp);
 
-                               keep = be_new_Keep(arch_get_irn_reg_class(arch_env, cp, -1),
+                               keep = be_new_Keep(arch_get_irn_reg_class(cp, -1),
                                        irg, get_nodes_block(cp), n, get_irn_in(cp) + 1);
                                sched_add_before(cp, keep);
 
@@ -862,7 +844,7 @@ void assure_constraints(be_irg_t *birg) {
                ir_nodeset_destroy(&entry->copies);
        }
 
-       del_pset(cenv.op_set);
+       ir_nodemap_destroy(&cenv.op_set);
        obstack_free(&cenv.obst, NULL);
        be_liveness_invalidate(be_get_birg_liveness(birg));
 }
@@ -881,8 +863,7 @@ void assure_constraints(be_irg_t *birg) {
  */
 static int push_through_perm(ir_node *perm, void *data)
 {
-       lower_env_t *env       = data;
-       const arch_env_t *aenv = env->arch_env;
+       lower_env_t *env = data;
 
        ir_graph *irg     = get_irn_irg(perm);
        ir_node *bl       = get_nodes_block(perm);
@@ -907,7 +888,7 @@ static int push_through_perm(ir_node *perm, void *data)
        edge     = get_irn_out_edge_first_kind(perm, EDGE_KIND_NORMAL);
        one_proj = get_edge_src_irn(edge);
        assert(is_Proj(one_proj));
-       cls      = arch_get_irn_reg_class(aenv, one_proj, -1);
+       cls      = arch_get_irn_reg_class(one_proj, -1);
 
        /* Find the point in the schedule after which the
         * potentially movable nodes must be defined.
@@ -920,7 +901,7 @@ static int push_through_perm(ir_node *perm, void *data)
        sched_foreach_reverse_from (sched_prev(perm), irn) {
                for (i = get_irn_arity(irn) - 1; i >= 0; --i) {
                        ir_node *op = get_irn_n(irn, i);
-                       if (arch_irn_consider_in_reg_alloc(aenv, cls, op) &&
+                       if (arch_irn_consider_in_reg_alloc(cls, op) &&
                            !values_interfere(env->birg, op, one_proj)) {
                                frontier = irn;
                                goto found_front;
@@ -954,19 +935,19 @@ found_front:
                        break;
                if(!sched_comes_after(frontier, node))
                        break;
-               if(arch_irn_is(aenv, node, modify_flags))
+               if (arch_irn_is(node, modify_flags))
                        break;
                if(is_Proj(node)) {
-                       req = arch_get_register_req(aenv, get_Proj_pred(node),
+                       req = arch_get_register_req(get_Proj_pred(node),
                                                    -1 - get_Proj_proj(node));
                } else {
-                       req = arch_get_register_req(aenv, node, -1);
+                       req = arch_get_register_req(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)) {
+                       if (arch_irn_consider_in_reg_alloc(cls, opop)) {
                                break;
                        }
                }
@@ -980,7 +961,7 @@ found_front:
                sched_add_after(perm, node);
 
                /* give it the proj's register */
-               arch_set_irn_register(aenv, node, arch_get_irn_register(aenv, proj));
+               arch_set_irn_register(node, arch_get_irn_register(proj));
 
                /* reroute all users of the proj to the moved node. */
                edges_reroute(proj, node, irg);
@@ -1060,9 +1041,8 @@ void lower_nodes_after_ra(be_irg_t *birg, int do_copy) {
        lower_env_t env;
        ir_graph    *irg = be_get_birg_irg(birg);
 
-       env.birg     = birg;
-       env.arch_env = be_get_birg_arch_env(birg);
-       env.do_copy  = do_copy;
+       env.birg    = birg;
+       env.do_copy = do_copy;
        FIRM_DBG_REGISTER(env.dbg_module, "firm.be.lower");
 
        /* we will need interference */