+ /* find suitable in operands to the out operands of the node. */
+ pair_up_operands(alloc_env, insn);
+
+ /*
+ look at the in/out operands and add each operand (and its possible partner)
+ to a bipartite graph (left: nodes with partners, right: admissible colors).
+ */
+ for(i = 0, n_alloc = 0; i < insn->n_ops; ++i) {
+ be_operand_t *op = &insn->ops[i];
+
+ /*
+ If the operand has no partner or the partner has not been marked
+ for allocation, determine the admissible registers and mark it
+ for allocation by associating the node and its partner with the
+ set of admissible registers via a bipartite graph.
+ */
+ if(!op->partner || !pmap_contains(partners, op->partner->carrier)) {
+ ir_node *partner = op->partner ? op->partner->carrier : NULL;
+ int i;
+
+ pmap_insert(partners, op->carrier, partner);
+ if(partner != NULL)
+ pmap_insert(partners, partner, op->carrier);
+
+ /* don't insert a node twice */
+ for(i = 0; i < n_alloc; ++i) {
+ if(alloc_nodes[i] == op->carrier) {
+ break;
+ }
+ }
+ if(i < n_alloc)
+ continue;
+
+ alloc_nodes[n_alloc] = op->carrier;
+
+ 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_foreach(bs, col) {
+ //hungarian_add(bp, n_alloc, col, 1);
+ bipartite_add(bp, n_alloc, col);
+ }
+
+ n_alloc++;
+ }
+ }
+
+ /*
+ Put all nodes which live through the constrained instruction also to the
+ allocation bipartite graph. They are considered unconstrained.
+ */
+ if(perm != NULL) {
+ foreach_out_edge(perm, edge) {
+ int i;
+ ir_node *proj = get_edge_src_irn(edge);
+
+ assert(is_Proj(proj));
+
+ if(!values_interfere(birg, proj, irn) || pmap_contains(partners, proj))
+ continue;
+
+ /* don't insert a node twice */
+ for(i = 0; i < n_alloc; ++i) {
+ if(alloc_nodes[i] == proj) {
+ break;
+ }
+ }
+ if(i < n_alloc)
+ continue;
+
+
+ assert(n_alloc < n_regs);
+
+ alloc_nodes[n_alloc] = proj;
+ pmap_insert(partners, proj, NULL);
+
+ bitset_clear_all(bs);
+ arch_put_non_ignore_regs(aenv, env->cls, bs);
+ bitset_andnot(bs, env->ignore_colors);
+ bitset_foreach(bs, col) {
+ //hungarian_add(bp, n_alloc, col, 1);
+ bipartite_add(bp, n_alloc, col);
+ }
+
+ n_alloc++;
+ }
+ }
+
+ /* Compute a valid register allocation. */
+#if 0
+ hungarian_prepare_cost_matrix(bp, HUNGARIAN_MODE_MAXIMIZE_UTIL);
+ match_res = hungarian_solve(bp, assignment, &cost, 1);
+ assert(match_res == 0 && "matching failed");
+#else
+ bipartite_matching(bp, assignment);
+#endif
+
+ /* Assign colors obtained from the matching. */
+ for(i = 0; i < n_alloc; ++i) {
+ const arch_register_t *reg;
+ ir_node *irn;
+
+ assert(assignment[i] >= 0 && "there must have been a register assigned");
+ reg = arch_register_for_index(env->cls, assignment[i]);
+ assert(! (reg->type & arch_register_type_ignore));
+
+ irn = alloc_nodes[i];
+ if (irn != NULL) {
+ arch_set_irn_register(aenv, irn, reg);
+ (void) pset_hinsert_ptr(alloc_env->pre_colored, irn);
+ DBG((dbg, LEVEL_2, "\tsetting %+F to register %s\n", irn, reg->name));
+ }
+
+ irn = pmap_get(partners, alloc_nodes[i]);
+ if (irn != NULL) {
+ arch_set_irn_register(aenv, irn, reg);
+ (void) pset_hinsert_ptr(alloc_env->pre_colored, irn);
+ DBG((dbg, LEVEL_2, "\tsetting %+F to register %s\n", irn, reg->name));
+ }
+ }
+
+ /* Allocate the non-constrained Projs of the Perm. */
+ if(perm != NULL) {
+ bitset_clear_all(bs);
+
+ /* Put the colors of all Projs in a bitset. */
+ foreach_out_edge(perm, edge) {
+ ir_node *proj = get_edge_src_irn(edge);
+ const arch_register_t *reg = arch_get_irn_register(aenv, proj);
+
+ if(reg != NULL)
+ bitset_set(bs, reg->index);
+ }
+
+ /* Assign the not yet assigned Projs of the Perm a suitable color. */
+ foreach_out_edge(perm, edge) {
+ ir_node *proj = get_edge_src_irn(edge);
+ const arch_register_t *reg = arch_get_irn_register(aenv, proj);
+
+ 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);
+ reg = arch_register_for_index(env->cls, col);
+ bitset_set(bs, reg->index);
+ arch_set_irn_register(aenv, proj, reg);
+ pset_insert_ptr(alloc_env->pre_colored, proj);
+ DBG((dbg, LEVEL_2, "\tsetting %+F to register %s\n", proj, reg->name));
+ }
+ }
+ }
+
+ bipartite_free(bp);
+ //hungarian_free(bp);
+ pmap_destroy(partners);
+
+end:
+ obstack_free(env->obst, base);
+ return res;
+}
+
+/**
+ * Handle constraint nodes in each basic block.
+ * handle_constraints() inserts Perm nodes which perm
+ * over all values live at the constrained node right in front
+ * of the constrained node. These Perms signal a constrained node.
+ * For further comments, refer to handle_constraints().
+ */
+static void constraints(ir_node *bl, void *data)
+{
+ be_chordal_alloc_env_t *env = 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));
+ 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);
+ }
+}
+
+/**
+ * Annotate the register pressure to the nodes and compute
+ * the liveness intervals.
+ * @param block The block to do it for.
+ * @param env_ptr The environment.
+ */
+static void pressure(ir_node *block, void *env_ptr)
+{
+/* Convenience macro for a def */
+#define border_def(irn, step, real) \
+ border_add(env, head, irn, step, pressure--, 1, real)
+
+/* Convenience macro for a use */
+#define border_use(irn, step, real) \
+ border_add(env, head, irn, step, ++pressure, 0, real)
+
+ be_chordal_alloc_env_t *alloc_env = env_ptr;
+ be_chordal_env_t *env = alloc_env->chordal_env;
+ bitset_t *live = alloc_env->live;
+ ir_node *irn;
+ be_lv_t *lv = env->birg->lv;
+
+ int i, n;
+ bitset_pos_t elm;
+ unsigned step = 0;
+ unsigned pressure = 0;
+ struct list_head *head;
+
+ DBG((dbg, LEVEL_1, "Computing pressure in block %+F\n", block));