beinfo: Remove declaration of the non-existent function be_info_duplicate().
[libfirm] / ir / be / bechordal.c
index ea259f6..d2b414c 100644 (file)
@@ -22,7 +22,6 @@
  * @brief       Chordal register allocation.
  * @author      Sebastian Hack
  * @date        08.12.2004
- * @version     $Id$
  */
 #include "config.h"
 
@@ -33,7 +32,6 @@
 #include "list.h"
 #include "bitset.h"
 #include "raw_bitset.h"
-#include "iterator.h"
 #include "bipartite.h"
 #include "hungarian.h"
 
@@ -44,7 +42,6 @@
 #include "irdump.h"
 #include "irdom.h"
 #include "irtools.h"
-#include "irbitset.h"
 #include "debug.h"
 #include "iredges.h"
 
@@ -57,7 +54,7 @@
 #include "beirgmod.h"
 #include "beifg.h"
 #include "beinsn_t.h"
-#include "bestatevent.h"
+#include "statev_t.h"
 #include "beirg.h"
 #include "beintlive_t.h"
 #include "bera.h"
 
 DEBUG_ONLY(static firm_dbg_module_t *dbg = NULL;)
 
-#define NO_COLOR (-1)
-
-#define DUMP_INTERVALS
-
 typedef struct be_chordal_alloc_env_t {
        be_chordal_env_t *chordal_env;
 
@@ -80,8 +73,6 @@ typedef struct be_chordal_alloc_env_t {
        bitset_t *live;        /**< A liveness bitset. */
        bitset_t *tmp_colors;  /**< An auxiliary bitset which is as long as the number of colors in the class. */
        bitset_t *colors;      /**< The color mask. */
-       bitset_t *in_colors;   /**< Colors used by live in values. */
-       int colors_n;          /**< The number of colors. */
 } be_chordal_alloc_env_t;
 
 static int get_next_free_reg(const be_chordal_alloc_env_t *alloc_env, bitset_t *colors)
@@ -93,31 +84,18 @@ static int get_next_free_reg(const be_chordal_alloc_env_t *alloc_env, bitset_t *
        return bitset_next_set(tmp, 0);
 }
 
-static bitset_t *get_decisive_partner_regs(bitset_t *bs, const be_operand_t *o1, const be_operand_t *o2)
+static bitset_t const *get_decisive_partner_regs(be_operand_t const *const o1)
 {
-       bitset_t *res = bs;
+       be_operand_t const *const o2 = o1->partner;
+       assert(!o2 || o1->req->cls == o2->req->cls);
 
-       if (!o1) {
-               bitset_copy(bs, o2->regs);
-               return bs;
-       }
-
-       if (!o2) {
-               bitset_copy(bs, o1->regs);
-               return bs;
-       }
-
-       assert(o1->req->cls == o2->req->cls || ! o1->req->cls || ! o2->req->cls);
-
-       if (bitset_contains(o1->regs, o2->regs)) {
-               bitset_copy(bs, o1->regs);
+       if (!o2 || bitset_contains(o1->regs, o2->regs)) {
+               return o1->regs;
        } else if (bitset_contains(o2->regs, o1->regs)) {
-               bitset_copy(bs, o2->regs);
+               return o2->regs;
        } else {
-               res = NULL;
+               return NULL;
        }
-
-       return res;
 }
 
 static void pair_up_operands(const be_chordal_alloc_env_t *alloc_env, be_insn_t *insn)
@@ -170,25 +148,20 @@ static void pair_up_operands(const be_chordal_alloc_env_t *alloc_env, be_insn_t
        }
 }
 
-static ir_node *handle_constraints(be_chordal_alloc_env_t *alloc_env,
-                                   ir_node *irn, int *silent)
+static void handle_constraints(be_chordal_alloc_env_t *alloc_env,
+                                   ir_node *irn)
 {
        int n_regs;
-       bitset_t *bs;
        ir_node **alloc_nodes;
        //hungarian_problem_t *bp;
        int *assignment;
        pmap *partners;
        int i, n_alloc;
-       size_t col;
-       const ir_edge_t *edge;
        ir_node *perm = NULL;
        //int match_res, cost;
        be_chordal_env_t *env  = alloc_env->chordal_env;
        void *base             = obstack_base(env->obst);
-       be_insn_t *insn        = chordal_scan_insn(env, irn);
-       ir_node *res           = insn->next_insn;
-       int be_silent          = *silent;
+       be_insn_t *insn        = be_scan_insn(env, irn);
        bipartite_t *bp;
 
        if (insn->pre_colored) {
@@ -197,28 +170,14 @@ static ir_node *handle_constraints(be_chordal_alloc_env_t *alloc_env,
                        pset_insert_ptr(alloc_env->pre_colored, insn->ops[i].carrier);
        }
 
-       /*
-        * If the current node is a barrier toggle the silent flag.
-        * If we are in the start block, we are ought to be silent at the beginning,
-        * so the toggling activates the constraint handling but skips the barrier.
-        * If we are in the end block we handle the in requirements of the barrier
-        * and set the rest to silent.
-        */
-       if (be_is_Barrier(irn))
-               *silent = !*silent;
-
-       if (be_silent)
-               goto end;
-
        /*
         * Perms inserted before the constraint handling phase are considered to be
         * correctly precolored. These Perms arise during the ABI handling phase.
         */
-       if (!insn->has_constraints)
+       if (!insn->has_constraints || is_Phi(irn))
                goto end;
 
        n_regs      = env->cls->n_regs;
-       bs          = bitset_alloca(n_regs);
        alloc_nodes = ALLOCAN(ir_node*, n_regs);
        //bp          = hungarian_new(n_regs, n_regs, 2, HUNGARIAN_MATCH_PERFECT);
        bp          = bipartite_new(n_regs, n_regs);
@@ -270,15 +229,16 @@ static ir_node *handle_constraints(be_chordal_alloc_env_t *alloc_env,
                        DBG((dbg, LEVEL_2, "\tassociating %+F and %+F\n", op->carrier,
                             partner));
 
-                       bitset_clear_all(bs);
-                       get_decisive_partner_regs(bs, op, op->partner);
-
-                       DBG((dbg, LEVEL_2, "\tallowed registers for %+F: %B\n", op->carrier,
-                            bs));
+                       bitset_t const *const bs = get_decisive_partner_regs(op);
+                       if (bs) {
+                               DBG((dbg, LEVEL_2, "\tallowed registers for %+F: %B\n", op->carrier, bs));
 
-                       bitset_foreach(bs, col) {
-                               //hungarian_add(bp, n_alloc, col, 1);
-                               bipartite_add(bp, n_alloc, col);
+                               bitset_foreach(bs, col) {
+                                       //hungarian_add(bp, n_alloc, col, 1);
+                                       bipartite_add(bp, n_alloc, col);
+                               }
+                       } else {
+                               DBG((dbg, LEVEL_2, "\tallowed registers for %+F: none\n", op->carrier));
                        }
 
                        n_alloc++;
@@ -350,7 +310,7 @@ static ir_node *handle_constraints(be_chordal_alloc_env_t *alloc_env,
                        DBG((dbg, LEVEL_2, "\tsetting %+F to register %s\n", irn, reg->name));
                }
 
-               irn = (ir_node*)pmap_get(partners, alloc_nodes[i]);
+               irn = pmap_get(ir_node, partners, alloc_nodes[i]);
                if (irn != NULL) {
                        arch_set_irn_register(irn, reg);
                        (void) pset_hinsert_ptr(alloc_env->pre_colored, irn);
@@ -360,9 +320,8 @@ static ir_node *handle_constraints(be_chordal_alloc_env_t *alloc_env,
 
        /* Allocate the non-constrained Projs of the Perm. */
        if (perm != NULL) {
-               bitset_clear_all(bs);
-
                /* Put the colors of all Projs in a bitset. */
+               bitset_t *const bs = bitset_alloca(n_regs);
                foreach_out_edge(perm, edge) {
                        ir_node *proj              = get_edge_src_irn(edge);
                        const arch_register_t *reg = arch_get_irn_register(proj);
@@ -379,7 +338,7 @@ static ir_node *handle_constraints(be_chordal_alloc_env_t *alloc_env,
                        DBG((dbg, LEVEL_2, "\tchecking reg of %+F: %s\n", proj, reg ? reg->name : "<none>"));
 
                        if (reg == NULL) {
-                               col = get_next_free_reg(alloc_env, bs);
+                               size_t const col = get_next_free_reg(alloc_env, bs);
                                reg = arch_register_for_index(env->cls, col);
                                bitset_set(bs, reg->index);
                                arch_set_irn_register(proj, reg);
@@ -395,7 +354,6 @@ static ir_node *handle_constraints(be_chordal_alloc_env_t *alloc_env,
 
 end:
        obstack_free(env->obst, base);
-       return res;
 }
 
 /**
@@ -407,21 +365,13 @@ end:
  */
 static void constraints(ir_node *bl, void *data)
 {
-       /*
-        * Start silent in the start block.
-        * The silence remains until the first barrier is seen.
-        * Each other block is begun loud.
-        */
-       int                     silent = bl == get_irg_start_block(get_irn_irg(bl));
        be_chordal_alloc_env_t *env    = (be_chordal_alloc_env_t*)data;
        ir_node                *irn;
 
-       /*
-        * If the block is the start block search the barrier and
-        * start handling constraints from there.
-        */
        for (irn = sched_first(bl); !sched_is_end(irn);) {
-               irn = handle_constraints(env, irn, &silent);
+               ir_node *const next = sched_next(irn);
+               handle_constraints(env, irn);
+               irn = next;
        }
 }
 
@@ -431,21 +381,15 @@ static void assign(ir_node *block, void *env_ptr)
        be_chordal_env_t *env       = alloc_env->chordal_env;
        bitset_t *live              = alloc_env->live;
        bitset_t *colors            = alloc_env->colors;
-       bitset_t *in_colors         = alloc_env->in_colors;
        struct list_head *head      = get_block_border_head(env, block);
        be_lv_t *lv                 = be_get_irg_liveness(env->irg);
 
-       const ir_node *irn;
-       border_t *b;
-       int idx;
-
        bitset_clear_all(colors);
        bitset_clear_all(live);
-       bitset_clear_all(in_colors);
 
        DBG((dbg, LEVEL_4, "Assigning colors for block %+F\n", block));
        DBG((dbg, LEVEL_4, "\tusedef chain for block\n"));
-       list_for_each_entry(border_t, b, head, list) {
+       foreach_border_head(head, b) {
                DBG((dbg, LEVEL_4, "\t%s %+F/%d\n", b->is_def ? "def" : "use",
                                        b->irn, get_irn_idx(b->irn)));
        }
@@ -455,20 +399,16 @@ static void assign(ir_node *block, void *env_ptr)
         * Since their colors have already been assigned (The dominators were
         * allocated before), we have to mark their colors as used also.
         */
-       be_lv_foreach(lv, block, be_lv_state_in, idx) {
-               irn = be_lv_get_irn(lv, block, idx);
-               if (has_reg_class(env, irn)) {
+       be_lv_foreach(lv, block, be_lv_state_in, irn) {
+               if (arch_irn_consider_in_reg_alloc(env->cls, irn)) {
                        const arch_register_t *reg = arch_get_irn_register(irn);
-                       int col;
 
                        assert(reg && "Node must have been assigned a register");
-                       col = arch_register_get_index(reg);
-
                        DBG((dbg, LEVEL_4, "%+F has reg %s\n", irn, reg->name));
 
                        /* Mark the color of the live in value as used. */
+                       int const col = reg->index;
                        bitset_set(colors, col);
-                       bitset_set(in_colors, col);
 
                        /* Mark the value live in. */
                        bitset_set(live, get_irn_idx(irn));
@@ -480,7 +420,7 @@ static void assign(ir_node *block, void *env_ptr)
         * elimination order. So, coloring the definitions from first to last
         * will work.
         */
-       list_for_each_entry_reverse(border_t, b, head, list) {
+       foreach_border_head(head, b) {
                ir_node *irn = b->irn;
                int nr       = get_irn_idx(irn);
                int ignore   = arch_irn_is_ignore(irn);
@@ -491,7 +431,7 @@ static void assign(ir_node *block, void *env_ptr)
                 */
                if (b->is_def && !be_is_live_in(lv, block, irn)) {
                        const arch_register_t *reg;
-                       int col = NO_COLOR;
+                       int col;
 
                        if (ignore || pset_find_ptr(alloc_env->pre_colored, irn)) {
                                reg = arch_get_irn_register(irn);
@@ -506,48 +446,48 @@ static void assign(ir_node *block, void *env_ptr)
                        bitset_set(colors, col);
                        arch_set_irn_register(irn, reg);
 
-                       DBG((dbg, LEVEL_1, "\tassigning register %s(%d) to %+F\n", arch_register_get_name(reg), col, irn));
+                       DBG((dbg, LEVEL_1, "\tassigning register %s(%d) to %+F\n", reg->name, col, irn));
 
                        assert(!bitset_is_set(live, nr) && "Value's definition must not have been encountered");
                        bitset_set(live, nr);
                } else if (!b->is_def) {
                        /* Clear the color upon a use. */
                        const arch_register_t *reg = arch_get_irn_register(irn);
-                       int col;
 
                        assert(reg && "Register must have been assigned");
 
-                       col = arch_register_get_index(reg);
-
-                       bitset_clear(colors, col);
+                       bitset_clear(colors, reg->index);
                        bitset_clear(live, nr);
                }
        }
 }
 
-void be_ra_chordal_color(be_chordal_env_t *chordal_env)
+static void be_ra_chordal_color(be_chordal_env_t *const chordal_env)
 {
        be_chordal_alloc_env_t env;
        char buf[256];
-       be_lv_t *lv;
        const arch_register_class_t *cls = chordal_env->cls;
 
-       int colors_n          = arch_register_class_n_regs(cls);
-       ir_graph *irg         = chordal_env->irg;
-
-       lv = be_assure_liveness(irg);
-       be_liveness_assure_sets(lv);
-       be_liveness_assure_chk(lv);
+       int       colors_n = arch_register_class_n_regs(cls);
+       ir_graph *irg      = chordal_env->irg;
 
+       be_assure_live_sets(irg);
        assure_doms(irg);
 
        env.chordal_env   = chordal_env;
-       env.colors_n      = colors_n;
        env.colors        = bitset_alloca(colors_n);
        env.tmp_colors    = bitset_alloca(colors_n);
-       env.in_colors     = bitset_alloca(colors_n);
        env.pre_colored   = pset_new_ptr_default();
 
+       be_timer_push(T_SPLIT);
+
+       if (chordal_env->opts->dump_flags & BE_CH_DUMP_SPLIT) {
+               snprintf(buf, sizeof(buf), "%s-split", chordal_env->cls->name);
+               dump_ir_graph(chordal_env->irg, buf);
+       }
+
+       be_timer_pop(T_SPLIT);
+
        be_timer_push(T_CONSTR);
 
        /* Handle register targeting constraints */
@@ -580,7 +520,7 @@ void be_ra_chordal_color(be_chordal_env_t *chordal_env)
        del_pset(env.pre_colored);
 }
 
-BE_REGISTER_MODULE_CONSTRUCTOR(be_init_chordal);
+BE_REGISTER_MODULE_CONSTRUCTOR(be_init_chordal)
 void be_init_chordal(void)
 {
        static be_ra_chordal_coloring_t coloring = {