merge kaps
authorAndreas Zwinkau <zwinkau@kit.edu>
Fri, 8 Apr 2011 12:10:06 +0000 (14:10 +0200)
committerAndreas Zwinkau <zwinkau@kit.edu>
Fri, 8 Apr 2011 12:10:06 +0000 (14:10 +0200)
30 files changed:
1  2 
ir/kaps/brute_force.c
ir/kaps/brute_force.h
ir/kaps/bucket.c
ir/kaps/bucket.h
ir/kaps/bucket_t.h
ir/kaps/heuristical.c
ir/kaps/heuristical.h
ir/kaps/heuristical_co.c
ir/kaps/heuristical_co.h
ir/kaps/heuristical_co_ld.c
ir/kaps/heuristical_co_ld.h
ir/kaps/html_dumper.c
ir/kaps/html_dumper.h
ir/kaps/kaps.c
ir/kaps/kaps.h
ir/kaps/matrix.c
ir/kaps/matrix.h
ir/kaps/matrix_t.h
ir/kaps/optimal.c
ir/kaps/optimal.h
ir/kaps/pbqp_edge.c
ir/kaps/pbqp_edge.h
ir/kaps/pbqp_edge_t.h
ir/kaps/pbqp_node.c
ir/kaps/pbqp_node.h
ir/kaps/pbqp_node_t.h
ir/kaps/pbqp_t.h
ir/kaps/vector.c
ir/kaps/vector.h
ir/kaps/vector_t.h

index 0000000,0000000..94111ce
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,386 @@@
++/*
++ * Copyright (C) 1995-2008 University of Karlsruhe.  All right reserved.
++ *
++ * This file is part of libFirm.
++ *
++ * This file may be distributed and/or modified under the terms of the
++ * GNU General Public License version 2 as published by the Free Software
++ * Foundation and appearing in the file LICENSE.GPL included in the
++ * packaging of this file.
++ *
++ * Licensees holding valid libFirm Professional Edition licenses may use
++ * this file in accordance with the libFirm Commercial License.
++ * Agreement provided with the Software.
++ *
++ * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
++ * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
++ * PURPOSE.
++ */
++
++/**
++ * @file
++ * @brief   Brute force PBQP solver.
++ * @date    02.12.2008
++ * @author  Sebastian Buchwald
++ * @version $Id$
++ */
++#include "config.h"
++
++#include "assert.h"
++#include "error.h"
++
++#include "bucket.h"
++#include "brute_force.h"
++#include "optimal.h"
++#if   KAPS_DUMP
++#include "html_dumper.h"
++#endif
++#include "kaps.h"
++#include "matrix.h"
++#include "pbqp_edge.h"
++#include "pbqp_edge_t.h"
++#include "pbqp_node.h"
++#include "pbqp_node_t.h"
++#include "vector.h"
++
++#if KAPS_STATISTIC
++static int dump = 0;
++#endif
++
++/* Forward declarations. */
++static void apply_Brute_Force(pbqp_t *pbqp);
++
++static void apply_brute_force_reductions(pbqp_t *pbqp)
++{
++      for (;;) {
++              if (edge_bucket_get_length(edge_bucket) > 0) {
++                      apply_edge(pbqp);
++              } else if (node_bucket_get_length(node_buckets[1]) > 0) {
++                      apply_RI(pbqp);
++              } else if (node_bucket_get_length(node_buckets[2]) > 0) {
++                      apply_RII(pbqp);
++              } else if (node_bucket_get_length(node_buckets[3]) > 0) {
++                      apply_Brute_Force(pbqp);
++              } else {
++                      return;
++              }
++      }
++}
++
++static unsigned get_minimal_alternative(pbqp_t *pbqp, pbqp_node_t *node)
++{
++      vector_t *node_vec;
++      unsigned  node_index;
++      unsigned  node_len;
++      unsigned  min_index    = 0;
++      num       min          = INF_COSTS;
++      unsigned  bucket_index;
++
++      assert(pbqp);
++      assert(node);
++      node_vec     = node->costs;
++      node_len     = node_vec->len;
++      bucket_index = node->bucket_index;
++
++      for (node_index = 0; node_index < node_len; ++node_index) {
++              pbqp_node_bucket_t bucket_deg3;
++              num                value;
++              unsigned           bucket_0_length;
++              unsigned           bucket_red_length;
++
++              char *tmp = (char*)obstack_finish(&pbqp->obstack);
++
++              node_bucket_init(&bucket_deg3);
++
++              /* Some node buckets and the edge bucket should be empty. */
++              assert(node_bucket_get_length(node_buckets[1]) == 0);
++              assert(node_bucket_get_length(node_buckets[2]) == 0);
++              assert(edge_bucket_get_length(edge_bucket)     == 0);
++
++              /* char *tmp = obstack_finish(&pbqp->obstack); */
++
++              /* Save current PBQP state. */
++              node_bucket_copy(&bucket_deg3, node_buckets[3]);
++              node_bucket_shrink(&node_buckets[3], 0);
++              node_bucket_deep_copy(pbqp, &node_buckets[3], bucket_deg3);
++              node_bucket_update(pbqp, node_buckets[3]);
++              bucket_0_length   = node_bucket_get_length(node_buckets[0]);
++              bucket_red_length = node_bucket_get_length(reduced_bucket);
++
++              /* Select alternative and solve PBQP recursively. */
++              select_alternative(node_buckets[3][bucket_index], node_index);
++              apply_brute_force_reductions(pbqp);
++
++              value = determine_solution(pbqp);
++
++              if (value < min) {
++                      min = value;
++                      min_index = node_index;
++              }
++
++              /* Some node buckets and the edge bucket should still be empty. */
++              assert(node_bucket_get_length(node_buckets[1]) == 0);
++              assert(node_bucket_get_length(node_buckets[2]) == 0);
++              assert(edge_bucket_get_length(edge_bucket)     == 0);
++
++              /* Clear modified buckets... */
++              node_bucket_shrink(&node_buckets[3], 0);
++
++              /* ... and restore old PBQP state. */
++              node_bucket_shrink(&node_buckets[0], bucket_0_length);
++              node_bucket_shrink(&reduced_bucket, bucket_red_length);
++              node_bucket_copy(&node_buckets[3], bucket_deg3);
++              node_bucket_update(pbqp, node_buckets[3]);
++
++              /* Free copies. */
++              /* obstack_free(&pbqp->obstack, tmp); */
++              node_bucket_free(&bucket_deg3);
++
++              obstack_free(&pbqp->obstack, tmp);
++      }
++
++      return min_index;
++}
++
++static void apply_Brute_Force(pbqp_t *pbqp)
++{
++      pbqp_node_t *node         = NULL;
++      unsigned     min_index    = 0;
++
++      assert(pbqp);
++
++      /* We want to reduce a node with maximum degree. */
++      node = get_node_with_max_degree();
++      assert(node);
++      assert(pbqp_node_get_degree(node) > 2);
++
++#if   KAPS_DUMP
++      if (pbqp->dump_file) {
++              char     txt[100];
++              sprintf(txt, "BF-Reduction of Node n%d", node->index);
++              dump_section(pbqp->dump_file, 2, txt);
++              pbqp_dump_graph(pbqp);
++      }
++#endif
++
++#if KAPS_STATISTIC
++      dump++;
++#endif
++
++      min_index = get_minimal_alternative(pbqp, node);
++      node = pbqp->nodes[node->index];
++
++#if   KAPS_DUMP
++      if (pbqp->dump_file) {
++              fprintf(pbqp->dump_file, "node n%d is set to %d<br><br>\n",
++                                      node->index, min_index);
++      }
++#endif
++
++#if KAPS_STATISTIC
++      dump--;
++      if (dump == 0) {
++              FILE *fh = fopen("solutions.pb", "a");
++              fprintf(fh, "[%u]", min_index);
++              fclose(fh);
++              pbqp->num_bf++;
++      }
++#endif
++
++      /* Now that we found the minimum set all other costs to infinity. */
++      select_alternative(node, min_index);
++}
++
++
++
++static void back_propagate_RI(pbqp_t *pbqp, pbqp_node_t *node)
++{
++      pbqp_edge_t   *edge;
++      pbqp_node_t   *other;
++      pbqp_matrix_t *mat;
++      vector_t      *vec;
++      int            is_src;
++
++      assert(pbqp);
++      assert(node);
++
++      edge = node->edges[0];
++      mat = edge->costs;
++      is_src = edge->src == node;
++      vec = node->costs;
++
++      if (is_src) {
++              other = edge->tgt;
++              assert(other);
++
++              /* Update pointer for brute force solver. */
++              other = pbqp->nodes[other->index];
++
++              node->solution = pbqp_matrix_get_col_min_index(mat, other->solution, vec);
++      } else {
++              other = edge->src;
++              assert(other);
++
++              /* Update pointer for brute force solver. */
++              other = pbqp->nodes[other->index];
++
++              node->solution = pbqp_matrix_get_row_min_index(mat, other->solution, vec);
++      }
++
++#if   KAPS_DUMP
++      if (pbqp->dump_file) {
++              fprintf(pbqp->dump_file, "node n%d is set to %d<br>\n", node->index, node->solution);
++      }
++#endif
++}
++
++static void back_propagate_RII(pbqp_t *pbqp, pbqp_node_t *node)
++{
++      pbqp_edge_t   *src_edge   = node->edges[0];
++      pbqp_edge_t   *tgt_edge   = node->edges[1];
++      int            src_is_src = src_edge->src == node;
++      int            tgt_is_src = tgt_edge->src == node;
++      pbqp_matrix_t *src_mat;
++      pbqp_matrix_t *tgt_mat;
++      pbqp_node_t   *src_node;
++      pbqp_node_t   *tgt_node;
++      vector_t      *vec;
++      vector_t      *node_vec;
++      unsigned       col_index;
++      unsigned       row_index;
++
++      assert(pbqp);
++
++      if (src_is_src) {
++              src_node = src_edge->tgt;
++      } else {
++              src_node = src_edge->src;
++      }
++
++      if (tgt_is_src) {
++              tgt_node = tgt_edge->tgt;
++      } else {
++              tgt_node = tgt_edge->src;
++      }
++
++      /* Swap nodes if necessary. */
++      if (tgt_node->index < src_node->index) {
++              pbqp_node_t *tmp_node;
++              pbqp_edge_t *tmp_edge;
++
++              tmp_node = src_node;
++              src_node = tgt_node;
++              tgt_node = tmp_node;
++
++              tmp_edge = src_edge;
++              src_edge = tgt_edge;
++              tgt_edge = tmp_edge;
++
++              src_is_src = src_edge->src == node;
++              tgt_is_src = tgt_edge->src == node;
++      }
++
++      /* Update pointer for brute force solver. */
++      src_node = pbqp->nodes[src_node->index];
++      tgt_node = pbqp->nodes[tgt_node->index];
++
++      src_mat = src_edge->costs;
++      tgt_mat = tgt_edge->costs;
++
++      node_vec = node->costs;
++
++      row_index = src_node->solution;
++      col_index = tgt_node->solution;
++
++      vec = vector_copy(pbqp, node_vec);
++
++      if (src_is_src) {
++              vector_add_matrix_col(vec, src_mat, row_index);
++      } else {
++              vector_add_matrix_row(vec, src_mat, row_index);
++      }
++
++      if (tgt_is_src) {
++              vector_add_matrix_col(vec, tgt_mat, col_index);
++      } else {
++              vector_add_matrix_row(vec, tgt_mat, col_index);
++      }
++
++      node->solution = vector_get_min_index(vec);
++
++#if   KAPS_DUMP
++      if (pbqp->dump_file) {
++              fprintf(pbqp->dump_file, "node n%d is set to %d<br>\n", node->index, node->solution);
++      }
++#endif
++
++      obstack_free(&pbqp->obstack, vec);
++}
++
++static void back_propagate_brute_force(pbqp_t *pbqp)
++{
++      unsigned node_index;
++      unsigned node_len = node_bucket_get_length(reduced_bucket);
++
++      assert(pbqp);
++
++#if   KAPS_DUMP
++      if (pbqp->dump_file) {
++              dump_section(pbqp->dump_file, 2, "Back Propagation");
++      }
++#endif
++
++      for (node_index = node_len; node_index > 0; --node_index) {
++              pbqp_node_t *node = reduced_bucket[node_index - 1];
++
++              switch (pbqp_node_get_degree(node)) {
++                      case 1:
++                              back_propagate_RI(pbqp, node);
++                              break;
++                      case 2:
++                              back_propagate_RII(pbqp, node);
++                              break;
++                      default:
++                              panic("Only nodes with degree one or two should be in this bucket");
++                              break;
++              }
++      }
++}
++
++void solve_pbqp_brute_force(pbqp_t *pbqp)
++{
++      /* Reduce nodes degree ... */
++      initial_simplify_edges(pbqp);
++
++      /* ... and put node into bucket representing their degree. */
++      fill_node_buckets(pbqp);
++
++#if KAPS_STATISTIC
++      FILE *fh = fopen("solutions.pb", "a");
++      fprintf(fh, "Solution");
++      fclose(fh);
++#endif
++
++      apply_brute_force_reductions(pbqp);
++
++      pbqp->solution = determine_solution(pbqp);
++
++#if KAPS_STATISTIC
++      fh = fopen("solutions.pb", "a");
++      #if KAPS_USE_UNSIGNED
++              fprintf(fh, ": %u RE:%u R0:%u R1:%u R2:%u RM:%u RN/BF:%u\n", pbqp->solution,
++                              pbqp->num_edges, pbqp->num_r0, pbqp->num_r1, pbqp->num_r2,
++                              pbqp->num_rm, pbqp->num_rn);
++      #else
++              fprintf(fh, ": %lld RE:%u R0:%u R1:%u R2:%u RM:%u RN/BF:%u\n", pbqp->solution,
++                              pbqp->num_edges, pbqp->num_r0, pbqp->num_r1, pbqp->num_r2,
++                              pbqp->num_rm, pbqp->num_bf);
++      #endif
++      fclose(fh);
++#endif
++
++      /* Solve reduced nodes. */
++      back_propagate_brute_force(pbqp);
++
++      free_buckets();
++}
index 0000000,0000000..696dccc
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,34 @@@
++/*
++ * Copyright (C) 1995-2008 University of Karlsruhe.  All right reserved.
++ *
++ * This file is part of libFirm.
++ *
++ * This file may be distributed and/or modified under the terms of the
++ * GNU General Public License version 2 as published by the Free Software
++ * Foundation and appearing in the file LICENSE.GPL included in the
++ * packaging of this file.
++ *
++ * Licensees holding valid libFirm Professional Edition licenses may use
++ * this file in accordance with the libFirm Commercial License.
++ * Agreement provided with the Software.
++ *
++ * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
++ * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
++ * PURPOSE.
++ */
++
++/**
++ * @file
++ * @brief   Brute force PBQP solver.
++ * @date    02.12.2008
++ * @author  Sebastian Buchwald
++ * @version $Id$
++ */
++#ifndef KAPS_BRUTE_FORCE_H
++#define KAPS_BRUTE_FORCE_H
++
++#include "pbqp_t.h"
++
++void solve_pbqp_brute_force(pbqp_t *pbqp);
++
++#endif /* KAPS_BRUTE_FORCE_H */
index 0000000,0000000..77e8599
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,182 @@@
++/*
++ * Copyright (C) 1995-2008 University of Karlsruhe.  All right reserved.
++ *
++ * This file is part of libFirm.
++ *
++ * This file may be distributed and/or modified under the terms of the
++ * GNU General Public License version 2 as published by the Free Software
++ * Foundation and appearing in the file LICENSE.GPL included in the
++ * packaging of this file.
++ *
++ * Licensees holding valid libFirm Professional Edition licenses may use
++ * this file in accordance with the libFirm Commercial License.
++ * Agreement provided with the Software.
++ *
++ * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
++ * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
++ * PURPOSE.
++ */
++
++/**
++ * @file
++ * @brief   Buckets for nodes and edges.
++ * @date    30.11.2008
++ * @author  Sebastian Buchwald
++ * @version $Id$
++ */
++#include "config.h"
++
++#include "adt/array.h"
++
++#include "bucket.h"
++#include "pbqp_edge_t.h"
++#include "pbqp_node.h"
++#include "pbqp_node_t.h"
++
++int edge_bucket_contains(pbqp_edge_bucket_t bucket, pbqp_edge_t *edge)
++{
++      assert(edge);
++
++      return edge->bucket_index < edge_bucket_get_length(bucket)
++                      && bucket[edge->bucket_index] == edge;
++}
++
++void edge_bucket_free(pbqp_edge_bucket_t *bucket)
++{
++      DEL_ARR_F(*bucket);
++      *bucket = NULL;
++}
++
++unsigned edge_bucket_get_length(pbqp_edge_bucket_t bucket)
++{
++      return ARR_LEN(bucket);
++}
++
++void edge_bucket_init(pbqp_edge_bucket_t *bucket)
++{
++      *bucket = NEW_ARR_F(pbqp_edge_t *, 0);
++}
++
++void edge_bucket_insert(pbqp_edge_bucket_t *bucket, pbqp_edge_t *edge)
++{
++      edge->bucket_index = edge_bucket_get_length(*bucket);
++      ARR_APP1(pbqp_edge_t *, *bucket, edge);
++}
++
++pbqp_edge_t *edge_bucket_pop(pbqp_edge_bucket_t *bucket)
++{
++      unsigned     bucket_len = edge_bucket_get_length(*bucket);
++      pbqp_edge_t *edge;
++
++      assert(bucket_len > 0);
++
++      edge = (*bucket)[bucket_len - 1];
++
++      ARR_SHRINKLEN(*bucket, (int)bucket_len - 1);
++      edge->bucket_index = UINT_MAX;
++
++      return edge;
++}
++
++void node_bucket_shrink(pbqp_node_bucket_t *bucket, unsigned len)
++{
++      ARR_SHRINKLEN(*bucket, (int)len);
++}
++
++int node_bucket_contains(pbqp_node_bucket_t bucket, pbqp_node_t *node)
++{
++      assert(node);
++
++      return node->bucket_index < node_bucket_get_length(bucket)
++                      && bucket[node->bucket_index] == node;
++}
++
++void node_bucket_copy(pbqp_node_bucket_t *dst, pbqp_node_bucket_t src)
++{
++      unsigned src_index;
++      unsigned src_length = node_bucket_get_length(src);
++
++      for (src_index = 0; src_index < src_length; ++src_index) {
++              node_bucket_insert(dst, src[src_index]);
++      }
++}
++
++void node_bucket_update(pbqp_t *pbqp, pbqp_node_bucket_t bucket)
++{
++      unsigned index;
++      unsigned length = node_bucket_get_length(bucket);
++
++      for (index = 0; index < length; ++index) {
++              pbqp->nodes[bucket[index]->index] = bucket[index];
++      }
++}
++
++void node_bucket_free(pbqp_node_bucket_t *bucket)
++{
++      DEL_ARR_F(*bucket);
++      *bucket = NULL;
++}
++
++unsigned node_bucket_get_length(pbqp_node_bucket_t bucket)
++{
++      return ARR_LEN(bucket);
++}
++
++void node_bucket_init(pbqp_node_bucket_t *bucket)
++{
++      *bucket = NEW_ARR_F(pbqp_node_t*, 0);
++}
++
++void node_bucket_insert(pbqp_node_bucket_t *bucket, pbqp_node_t *node)
++{
++      node->bucket_index = node_bucket_get_length(*bucket);
++      ARR_APP1(pbqp_node_t *, *bucket, node);
++}
++
++pbqp_node_t *node_bucket_pop(pbqp_node_bucket_t *bucket)
++{
++      unsigned     bucket_len = node_bucket_get_length(*bucket);
++      pbqp_node_t *node;
++
++      assert(bucket_len > 0);
++
++      node = (*bucket)[bucket_len - 1];
++      assert(node);
++
++      ARR_SHRINKLEN(*bucket, (int)bucket_len - 1);
++      node->bucket_index = UINT_MAX;
++
++      return node;
++}
++
++void node_bucket_remove(pbqp_node_bucket_t *bucket, pbqp_node_t *node)
++{
++      unsigned     bucket_len = node_bucket_get_length(*bucket);
++      unsigned     node_index;
++      pbqp_node_t *other;
++
++      assert(node);
++      assert(node_bucket_contains(*bucket, node));
++      assert(bucket_len > 0);
++
++      node_index            = node->bucket_index;
++      other                 = (*bucket)[bucket_len - 1];
++      other->bucket_index   = node_index;
++      (*bucket)[node_index] = other;
++
++      ARR_SHRINKLEN(*bucket, (int)bucket_len - 1);
++      node->bucket_index = UINT_MAX;
++}
++
++void node_bucket_deep_copy(pbqp_t *pbqp, pbqp_node_bucket_t *dst,
++                           pbqp_node_bucket_t src)
++{
++      unsigned bucket_index;
++      unsigned bucket_length;
++
++      bucket_length = node_bucket_get_length(src);
++
++      for (bucket_index = 0; bucket_index < bucket_length; ++bucket_index) {
++              node_bucket_insert(dst, pbqp_node_deep_copy(pbqp, *dst, src[bucket_index]));
++      }
++}
index 0000000,0000000..fd0d92e
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,51 @@@
++/*
++ * Copyright (C) 1995-2008 University of Karlsruhe.  All right reserved.
++ *
++ * This file is part of libFirm.
++ *
++ * This file may be distributed and/or modified under the terms of the
++ * GNU General Public License version 2 as published by the Free Software
++ * Foundation and appearing in the file LICENSE.GPL included in the
++ * packaging of this file.
++ *
++ * Licensees holding valid libFirm Professional Edition licenses may use
++ * this file in accordance with the libFirm Commercial License.
++ * Agreement provided with the Software.
++ *
++ * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
++ * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
++ * PURPOSE.
++ */
++
++/**
++ * @file
++ * @brief   Buckets for nodes and edges.
++ * @date    30.11.2008
++ * @author  Sebastian Buchwald
++ * @version $Id$
++ */
++#ifndef KAPS_BUCKET_H
++#define KAPS_BUCKET_H
++
++#include "bucket_t.h"
++
++int edge_bucket_contains(pbqp_edge_bucket_t bucket, pbqp_edge_t *edge);
++void edge_bucket_free(pbqp_edge_bucket_t *bucket);
++unsigned edge_bucket_get_length(pbqp_edge_bucket_t bucket);
++void edge_bucket_init(pbqp_edge_bucket_t *bucket);
++void edge_bucket_insert(pbqp_edge_bucket_t *bucket, pbqp_edge_t *edge);
++pbqp_edge_t *edge_bucket_pop(pbqp_edge_bucket_t *bucket);
++
++int node_bucket_contains(pbqp_node_bucket_t bucket, pbqp_node_t *node);
++void node_bucket_copy(pbqp_node_bucket_t *dst, pbqp_node_bucket_t src);
++void node_bucket_deep_copy(pbqp_t *pbqp, pbqp_node_bucket_t *dst, pbqp_node_bucket_t src);
++void node_bucket_free(pbqp_node_bucket_t *bucket);
++unsigned node_bucket_get_length(pbqp_node_bucket_t bucket);
++void node_bucket_init(pbqp_node_bucket_t *bucket);
++void node_bucket_insert(pbqp_node_bucket_t *bucket, pbqp_node_t *node);
++pbqp_node_t *node_bucket_pop(pbqp_node_bucket_t *bucket);
++void node_bucket_remove(pbqp_node_bucket_t *bucket, pbqp_node_t *node);
++void node_bucket_shrink(pbqp_node_bucket_t *bucket, unsigned len);
++void node_bucket_update(pbqp_t *pbqp, pbqp_node_bucket_t bucket);
++
++#endif /* KAPS_BUCKET_H */
index 0000000,0000000..df9cce5
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,35 @@@
++/*
++ * Copyright (C) 1995-2008 University of Karlsruhe.  All right reserved.
++ *
++ * This file is part of libFirm.
++ *
++ * This file may be distributed and/or modified under the terms of the
++ * GNU General Public License version 2 as published by the Free Software
++ * Foundation and appearing in the file LICENSE.GPL included in the
++ * packaging of this file.
++ *
++ * Licensees holding valid libFirm Professional Edition licenses may use
++ * this file in accordance with the libFirm Commercial License.
++ * Agreement provided with the Software.
++ *
++ * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
++ * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
++ * PURPOSE.
++ */
++
++/**
++ * @file
++ * @brief   Node/edge bucket data types.
++ * @date    30.11.2008
++ * @author  Sebastian Buchwald
++ * @version $Id$
++ */
++#ifndef KAPS_BUCKET_T_H
++#define KAPS_BUCKET_T_H
++
++#include "pbqp_t.h"
++
++typedef pbqp_node_t** pbqp_node_bucket_t;
++typedef pbqp_edge_t** pbqp_edge_bucket_t;
++
++#endif /* KAPS_BUCKET_T_H */
index 0000000,0000000..c078f5d
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,143 @@@
++/*
++ * Copyright (C) 1995-2008 University of Karlsruhe.  All right reserved.
++ *
++ * This file is part of libFirm.
++ *
++ * This file may be distributed and/or modified under the terms of the
++ * GNU General Public License version 2 as published by the Free Software
++ * Foundation and appearing in the file LICENSE.GPL included in the
++ * packaging of this file.
++ *
++ * Licensees holding valid libFirm Professional Edition licenses may use
++ * this file in accordance with the libFirm Commercial License.
++ * Agreement provided with the Software.
++ *
++ * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
++ * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
++ * PURPOSE.
++ */
++
++/**
++ * @file
++ * @brief   Heuristic PBQP solver.
++ * @date    02.10.2008
++ * @author  Sebastian Buchwald
++ * @version $Id$
++ */
++#include "config.h"
++
++#include "adt/array.h"
++#include "assert.h"
++#include "error.h"
++
++#include "bucket.h"
++#include "heuristical.h"
++#include "optimal.h"
++#if   KAPS_DUMP
++#include "html_dumper.h"
++#endif
++#include "kaps.h"
++#include "matrix.h"
++#include "pbqp_edge.h"
++#include "pbqp_edge_t.h"
++#include "pbqp_node.h"
++#include "pbqp_node_t.h"
++#include "vector.h"
++
++#include "timing.h"
++
++static void apply_RN(pbqp_t *pbqp)
++{
++      pbqp_node_t *node      = NULL;
++      unsigned     min_index = 0;
++
++      assert(pbqp);
++
++      /* We want to reduce a node with maximum degree. */
++      node = get_node_with_max_degree();
++      assert(node);
++      assert(pbqp_node_get_degree(node) > 2);
++
++#if   KAPS_DUMP
++      if (pbqp->dump_file) {
++              char     txt[100];
++              sprintf(txt, "RN-Reduction of Node n%d", node->index);
++              dump_section(pbqp->dump_file, 2, txt);
++              pbqp_dump_graph(pbqp);
++      }
++#endif
++
++      min_index = get_local_minimal_alternative(pbqp, node);
++
++#if   KAPS_DUMP
++      if (pbqp->dump_file) {
++              fprintf(pbqp->dump_file, "node n%d is set to %d<br><br>\n",
++                                      node->index, min_index);
++      }
++#endif
++
++#if KAPS_STATISTIC
++      FILE *fh = fopen("solutions.pb", "a");
++      fprintf(fh, "[%u]", min_index);
++      fclose(fh);
++      pbqp->num_rn++;
++#endif
++
++      /* Now that we found the local minimum set all other costs to infinity. */
++      select_alternative(node, min_index);
++}
++
++static void apply_heuristic_reductions(pbqp_t *pbqp)
++{
++      for (;;) {
++              if (edge_bucket_get_length(edge_bucket) > 0) {
++                      apply_edge(pbqp);
++              } else if (node_bucket_get_length(node_buckets[1]) > 0) {
++                      apply_RI(pbqp);
++              } else if (node_bucket_get_length(node_buckets[2]) > 0) {
++                      apply_RII(pbqp);
++              } else if (node_bucket_get_length(node_buckets[3]) > 0) {
++                      apply_RN(pbqp);
++              } else {
++                      return;
++              }
++      }
++}
++
++void solve_pbqp_heuristical(pbqp_t *pbqp)
++{
++      /* Reduce nodes degree ... */
++      initial_simplify_edges(pbqp);
++
++      /* ... and put node into bucket representing their degree. */
++      fill_node_buckets(pbqp);
++
++#if KAPS_STATISTIC
++      FILE *fh = fopen("solutions.pb", "a");
++      fprintf(fh, "Solution");
++      fclose(fh);
++#endif
++
++      apply_heuristic_reductions(pbqp);
++
++      pbqp->solution = determine_solution(pbqp);
++
++#if KAPS_STATISTIC
++      fh = fopen("solutions.pb", "a");
++      #if KAPS_USE_UNSIGNED
++              fprintf(fh, ": %u RE:%u R0:%u R1:%u R2:%u RM:%u RN/BF:%u\n", pbqp->solution,
++                              pbqp->num_edges, pbqp->num_r0, pbqp->num_r1, pbqp->num_r2,
++                              pbqp->num_rm, pbqp->num_rn);
++      #else
++              fprintf(fh, ": %lld RE:%u R0:%u R1:%u R2:%u RM:%u RN/BF:%u\n", pbqp->solution,
++                              pbqp->num_edges, pbqp->num_r0, pbqp->num_r1, pbqp->num_r2,
++                              pbqp->num_rm, pbqp->num_rn);
++      #endif
++      fclose(fh);
++#endif
++
++      /* Solve reduced nodes. */
++      back_propagate(pbqp);
++
++      free_buckets();
++}
index 0000000,0000000..688b2bf
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,34 @@@
++/*
++ * Copyright (C) 1995-2008 University of Karlsruhe.  All right reserved.
++ *
++ * This file is part of libFirm.
++ *
++ * This file may be distributed and/or modified under the terms of the
++ * GNU General Public License version 2 as published by the Free Software
++ * Foundation and appearing in the file LICENSE.GPL included in the
++ * packaging of this file.
++ *
++ * Licensees holding valid libFirm Professional Edition licenses may use
++ * this file in accordance with the libFirm Commercial License.
++ * Agreement provided with the Software.
++ *
++ * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
++ * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
++ * PURPOSE.
++ */
++
++/**
++ * @file
++ * @brief   Heuristic PBQP solver.
++ * @date    02.10.2008
++ * @author  Sebastian Buchwald
++ * @version $Id$
++ */
++#ifndef KAPS_HEURISTICAL_CO_H
++#define KAPS_HEURISTICAL_CO_H
++
++#include "pbqp_t.h"
++
++void solve_pbqp_heuristical(pbqp_t *pbqp);
++
++#endif /* KAPS_HEURISTICAL_CO_H */
index 0000000,0000000..aa30729
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,225 @@@
++/*
++ * Copyright (C) 1995-2008 University of Karlsruhe.  All right reserved.
++ *
++ * This file is part of libFirm.
++ *
++ * This file may be distributed and/or modified under the terms of the
++ * GNU General Public License version 2 as published by the Free Software
++ * Foundation and appearing in the file LICENSE.GPL included in the
++ * packaging of this file.
++ *
++ * Licensees holding valid libFirm Professional Edition licenses may use
++ * this file in accordance with the libFirm Commercial License.
++ * Agreement provided with the Software.
++ *
++ * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
++ * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
++ * PURPOSE.
++ */
++
++/**
++ * @file
++ * @brief   Heuristic PBQP solver for SSA-based register allocation.
++ * @date    18.09.2009
++ * @author  Thomas Bersch
++ * @version $Id$
++ */
++#include "config.h"
++
++#include "adt/array.h"
++#include "assert.h"
++#include "error.h"
++
++#include "bucket.h"
++#include "heuristical_co.h"
++#include "optimal.h"
++#if   KAPS_DUMP
++#include "html_dumper.h"
++#endif
++#include "kaps.h"
++#include "matrix.h"
++#include "pbqp_edge.h"
++#include "pbqp_edge_t.h"
++#include "pbqp_node.h"
++#include "pbqp_node_t.h"
++#include "vector.h"
++
++#include "plist.h"
++#include "timing.h"
++
++static void merge_into_RN_node(pbqp_t *pbqp, plist_t *rpeo)
++{
++      pbqp_node_t *node = NULL;
++
++      assert(pbqp);
++
++      /* We want to reduce the first node in reverse perfect elimination order. */
++      do {
++              /* get first element from reverse perfect elimination order */
++              node = (pbqp_node_t*)plist_first(rpeo)->data;
++              /* remove element from reverse perfect elimination order */
++              plist_erase(rpeo, plist_first(rpeo));
++              /* insert node at the end of rpeo so the rpeo already exits after pbqp solving */
++              plist_insert_back(rpeo, node);
++      } while(node_is_reduced(node));
++
++      assert(node);
++      assert(pbqp_node_get_degree(node) > 2);
++
++      /* Check whether we can merge a neighbor into the current node. */
++      apply_RM(pbqp, node);
++}
++
++static void apply_RN_co(pbqp_t *pbqp)
++{
++      pbqp_node_t *node;
++      unsigned     min_index;
++
++      assert(pbqp);
++
++      node        = merged_node;
++      merged_node = NULL;
++      assert(node);
++
++      if (node_is_reduced(node))
++              return;
++
++#if   KAPS_DUMP
++      if (pbqp->dump_file) {
++              char     txt[100];
++              sprintf(txt, "RN-Reduction of Node n%d", node->index);
++              dump_section(pbqp->dump_file, 2, txt);
++              pbqp_dump_graph(pbqp);
++      }
++#endif
++
++      min_index = get_local_minimal_alternative(pbqp, node);
++
++#if   KAPS_DUMP
++      if (pbqp->dump_file) {
++              fprintf(pbqp->dump_file, "node n%d is set to %d<br><br>\n",
++                                      node->index, min_index);
++      }
++#endif
++
++#if KAPS_STATISTIC
++              FILE *fh = fopen("solutions.pb", "a");
++              fprintf(fh, "[%u]", min_index);
++              fclose(fh);
++              pbqp->num_rn++;
++#endif
++
++      /* Now that we found the local minimum set all other costs to infinity. */
++      select_alternative(node, min_index);
++}
++
++static void apply_heuristic_reductions_co(pbqp_t *pbqp, plist_t *rpeo)
++{
++      #if KAPS_TIMING
++              /* create timers */
++              ir_timer_t *t_edge = ir_timer_new();
++              ir_timer_t *t_r1   = ir_timer_new();
++              ir_timer_t *t_r2   = ir_timer_new();
++              ir_timer_t *t_rn   = ir_timer_new();
++      #endif
++
++      for (;;) {
++              if (edge_bucket_get_length(edge_bucket) > 0) {
++                      #if KAPS_TIMING
++                              ir_timer_start(t_edge);
++                      #endif
++
++                      apply_edge(pbqp);
++
++                      #if KAPS_TIMING
++                              ir_timer_stop(t_edge);
++                      #endif
++              } else if (node_bucket_get_length(node_buckets[1]) > 0) {
++                      #if KAPS_TIMING
++                              ir_timer_start(t_r1);
++                      #endif
++
++                      apply_RI(pbqp);
++
++                      #if KAPS_TIMING
++                              ir_timer_stop(t_r1);
++                      #endif
++              } else if (node_bucket_get_length(node_buckets[2]) > 0) {
++                      #if KAPS_TIMING
++                              ir_timer_start(t_r2);
++                      #endif
++
++                      apply_RII(pbqp);
++
++                      #if KAPS_TIMING
++                              ir_timer_stop(t_r2);
++                      #endif
++              } else if (merged_node != NULL) {
++                      #if KAPS_TIMING
++                              ir_timer_start(t_rn);
++                      #endif
++
++                      apply_RN_co(pbqp);
++
++                      #if KAPS_TIMING
++                              ir_timer_stop(t_rn);
++                      #endif
++              } else if (node_bucket_get_length(node_buckets[3]) > 0) {
++                      #if KAPS_TIMING
++                              ir_timer_start(t_rn);
++                      #endif
++
++                      merge_into_RN_node(pbqp, rpeo);
++
++                      #if KAPS_TIMING
++                              ir_timer_stop(t_rn);
++                      #endif
++              } else {
++                      #if KAPS_TIMING
++                              printf("PBQP RE reductions:           %10.3lf msec\n", (double)ir_timer_elapsed_usec(t_edge) / 1000.0);
++                              printf("PBQP R1 reductions:           %10.3lf msec\n", (double)ir_timer_elapsed_usec(t_r1) / 1000.0);
++                              printf("PBQP R2 reductions:           %10.3lf msec\n", (double)ir_timer_elapsed_usec(t_r2) / 1000.0);
++                              printf("PBQP RN reductions:           %10.3lf msec\n", (double)ir_timer_elapsed_usec(t_rn) / 1000.0);
++                      #endif
++
++                      return;
++              }
++      }
++}
++
++void solve_pbqp_heuristical_co(pbqp_t *pbqp, plist_t *rpeo)
++{
++      /* Reduce nodes degree ... */
++      initial_simplify_edges(pbqp);
++
++      /* ... and put node into bucket representing their degree. */
++      fill_node_buckets(pbqp);
++
++      #if KAPS_STATISTIC
++              FILE *fh = fopen("solutions.pb", "a");
++              fprintf(fh, "Solution");
++              fclose(fh);
++      #endif
++
++      apply_heuristic_reductions_co(pbqp, rpeo);
++
++      pbqp->solution = determine_solution(pbqp);
++
++      #if KAPS_STATISTIC
++              fh = fopen("solutions.pb", "a");
++              #if KAPS_USE_UNSIGNED
++                      fprintf(fh, ": %u RE:%u R0:%u R1:%u R2:%u RM:%u RN/BF:%u\n", pbqp->solution,
++                                      pbqp->num_edges, pbqp->num_r0, pbqp->num_r1, pbqp->num_r2,
++                                      pbqp->num_rm, pbqp->num_rn);
++              #else
++                      fprintf(fh, ": %lld RE:%u R0:%u R1:%u R2:%u RM:%u RN/BF:%u\n", pbqp->solution,
++                                      pbqp->num_edges, pbqp->num_r0, pbqp->num_r1, pbqp->num_r2,
++              #endif
++              fclose(fh);
++      #endif
++
++      /* Solve reduced nodes. */
++      back_propagate(pbqp);
++
++      free_buckets();
++}
index 0000000,0000000..2872edc
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,36 @@@
++/*
++ * Copyright (C) 1995-2008 University of Karlsruhe.  All right reserved.
++ *
++ * This file is part of libFirm.
++ *
++ * This file may be distributed and/or modified under the terms of the
++ * GNU General Public License version 2 as published by the Free Software
++ * Foundation and appearing in the file LICENSE.GPL included in the
++ * packaging of this file.
++ *
++ * Licensees holding valid libFirm Professional Edition licenses may use
++ * this file in accordance with the libFirm Commercial License.
++ * Agreement provided with the Software.
++ *
++ * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
++ * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
++ * PURPOSE.
++ */
++
++/**
++ * @file
++ * @brief   Heuristic PBQP solver for SSA-based register allocation.
++ * @date    18.09.2009
++ * @author  Thomas Bersch
++ * @version $Id$
++ */
++#ifndef KAPS_HEURISTICAL_H
++#define KAPS_HEURISTICAL_H
++
++#include "pbqp_t.h"
++
++#include "plist.h"
++
++void solve_pbqp_heuristical_co(pbqp_t *pbqp, plist_t *rpeo);
++
++#endif /* KAPS_HEURISTICAL_H */
index 0000000,0000000..ba694f9
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,396 @@@
++/*
++ * heuristical_co_ld.c
++ *
++ *  Created on: 06.05.2010
++ *      Author: berschth
++ */
++
++#include "config.h"
++
++#include "adt/array.h"
++#include "assert.h"
++#include "error.h"
++
++#include "bucket.h"
++#include "heuristical_co_ld.h"
++#include "optimal.h"
++#if   KAPS_DUMP
++#include "html_dumper.h"
++#endif
++#include "kaps.h"
++#include "matrix.h"
++#include "pbqp_edge.h"
++#include "pbqp_edge_t.h"
++#include "pbqp_node.h"
++#include "pbqp_node_t.h"
++#include "vector.h"
++
++#include "plist.h"
++#include "timing.h"
++
++static void back_propagate_RI(pbqp_t *pbqp, pbqp_node_t *node)
++{
++      pbqp_edge_t   *edge;
++      pbqp_node_t   *other;
++      pbqp_matrix_t *mat;
++      vector_t      *vec;
++      int            is_src;
++
++      assert(pbqp);
++      assert(node);
++
++      (void) pbqp;
++
++      edge = node->edges[0];
++      mat = edge->costs;
++      is_src = edge->src == node;
++      vec = node->costs;
++
++      if (is_src) {
++              other = edge->tgt;
++              assert(other);
++
++              node->solution = pbqp_matrix_get_col_min_index(mat, other->solution, vec);
++      } else {
++              other = edge->src;
++              assert(other);
++
++              node->solution = pbqp_matrix_get_row_min_index(mat, other->solution, vec);
++      }
++
++#if   KAPS_DUMP
++      if (pbqp->dump_file) {
++              fprintf(pbqp->dump_file, "node n%d is set to %d<br>\n", node->index, node->solution);
++      }
++#endif
++}
++
++static void back_propagate_RII(pbqp_t *pbqp, pbqp_node_t *node)
++{
++      pbqp_edge_t   *src_edge   = node->edges[0];
++      pbqp_edge_t   *tgt_edge   = node->edges[1];
++      int            src_is_src = src_edge->src == node;
++      int            tgt_is_src = tgt_edge->src == node;
++      pbqp_matrix_t *src_mat;
++      pbqp_matrix_t *tgt_mat;
++      pbqp_node_t   *src_node;
++      pbqp_node_t   *tgt_node;
++      vector_t      *vec;
++      vector_t      *node_vec;
++      unsigned       col_index;
++      unsigned       row_index;
++
++      assert(pbqp);
++
++      if (src_is_src) {
++              src_node = src_edge->tgt;
++      } else {
++              src_node = src_edge->src;
++      }
++
++      if (tgt_is_src) {
++              tgt_node = tgt_edge->tgt;
++      } else {
++              tgt_node = tgt_edge->src;
++      }
++
++      /* Swap nodes if necessary. */
++      if (tgt_node->index < src_node->index) {
++              pbqp_node_t *tmp_node;
++              pbqp_edge_t *tmp_edge;
++
++              tmp_node = src_node;
++              src_node = tgt_node;
++              tgt_node = tmp_node;
++
++              tmp_edge = src_edge;
++              src_edge = tgt_edge;
++              tgt_edge = tmp_edge;
++
++              src_is_src = src_edge->src == node;
++              tgt_is_src = tgt_edge->src == node;
++      }
++
++      src_mat = src_edge->costs;
++      tgt_mat = tgt_edge->costs;
++
++      node_vec = node->costs;
++
++      row_index = src_node->solution;
++      col_index = tgt_node->solution;
++
++      vec = vector_copy(pbqp, node_vec);
++
++      if (src_is_src) {
++              vector_add_matrix_col(vec, src_mat, row_index);
++      } else {
++              vector_add_matrix_row(vec, src_mat, row_index);
++      }
++
++      if (tgt_is_src) {
++              vector_add_matrix_col(vec, tgt_mat, col_index);
++      } else {
++              vector_add_matrix_row(vec, tgt_mat, col_index);
++      }
++
++      node->solution = vector_get_min_index(vec);
++
++#if   KAPS_DUMP
++      if (pbqp->dump_file) {
++              fprintf(pbqp->dump_file, "node n%d is set to %d<br>\n", node->index, node->solution);
++      }
++#endif
++
++      obstack_free(&pbqp->obstack, vec);
++}
++
++static void back_propagate_RN(pbqp_t *pbqp, pbqp_node_t *node)
++{
++      vector_t    *vec        = NULL;
++      pbqp_node_t *neighbor   = NULL;
++      pbqp_edge_t *edge       = NULL;
++      unsigned     edge_index = 0;
++
++      assert(pbqp);
++
++      vec = vector_copy(pbqp, node->costs);
++
++      for(edge_index = 0; edge_index < pbqp_node_get_degree(node); edge_index++) {
++              /* get neighbor node */
++              edge = node->edges[edge_index];
++              neighbor = edge->src == node ? edge->tgt : edge->src;
++
++              /* node is edge src node */
++              if(edge->src == node)
++                      vector_add_matrix_col(vec, edge->costs, neighbor->solution);
++              /* node is edge tgt node */
++              else
++                      vector_add_matrix_row(vec, edge->costs, neighbor->solution);
++      }
++
++      assert(vector_get_min(vec) != INF_COSTS);
++      node->solution = vector_get_min_index(vec);
++
++#if   KAPS_DUMP
++      if (pbqp->dump_file) {
++              fprintf(pbqp->dump_file, "node n%d is set to %d<br>\n", node->index, node->solution);
++      }
++#endif
++
++      obstack_free(&pbqp->obstack, vec);
++}
++
++static void back_propagate_ld(pbqp_t *pbqp)
++{
++      unsigned node_index;
++      unsigned node_len   = node_bucket_get_length(reduced_bucket);
++
++      assert(pbqp);
++
++#if   KAPS_DUMP
++      if (pbqp->dump_file) {
++              dump_section(pbqp->dump_file, 2, "Back Propagation");
++      }
++#endif
++
++      for (node_index = node_len; node_index > 0; --node_index) {
++              pbqp_node_t *node = reduced_bucket[node_index - 1];
++
++              switch (pbqp_node_get_degree(node)) {
++                      case 1:
++                              back_propagate_RI(pbqp, node);
++                              break;
++                      case 2:
++                              back_propagate_RII(pbqp, node);
++                              break;
++                      default:
++                              back_propagate_RN(pbqp, node);
++                              break;
++              }
++      }
++}
++
++static void merge_into_RN_node(pbqp_t *pbqp, plist_t *rpeo)
++{
++      pbqp_node_t *node = NULL;
++
++      assert(pbqp);
++
++      do {
++              /* get last element from reverse perfect elimination order */
++              node = (pbqp_node_t*)plist_last(rpeo)->data;
++              /* remove element from reverse perfect elimination order */
++              plist_erase(rpeo, plist_last(rpeo));
++              /* insert node at the beginning of rpeo so the rpeo already exits after pbqp solving */
++              plist_insert_front(rpeo, node);
++      } while(node_is_reduced(node));
++
++      assert(node);
++      assert(pbqp_node_get_degree(node) > 2);
++
++      /* Check whether we can merge a neighbor into the current node. */
++      apply_RM(pbqp, node);
++}
++
++static void apply_RN_co_without_selection(pbqp_t *pbqp)
++{
++      pbqp_node_t *node;
++      unsigned     edge_index;
++
++      assert(pbqp);
++
++      node        = merged_node;
++      merged_node = NULL;
++      assert(node);
++
++      if (node_is_reduced(node))
++              return;
++
++#if   KAPS_DUMP
++      if (pbqp->dump_file) {
++              char     txt[100];
++              sprintf(txt, "RN-Reduction of Node n%d", node->index);
++              dump_section(pbqp->dump_file, 2, txt);
++              pbqp_dump_graph(pbqp);
++      }
++#endif
++
++      /* Disconnect neighbor nodes */
++      for(edge_index = 0; edge_index < pbqp_node_get_degree(node); edge_index++) {
++              pbqp_edge_t *edge;
++              pbqp_node_t *neighbor;
++
++              /* get neighbor node */
++              edge = node->edges[edge_index];
++              assert(edge);
++
++              neighbor = edge->src == node ? edge->tgt : edge->src;
++              assert(neighbor);
++
++              assert(neighbor != node);
++
++              if(!is_connected(neighbor, edge))
++                      continue;
++
++              disconnect_edge(neighbor, edge);
++              reorder_node_after_edge_deletion(neighbor);
++      }
++
++      /* Remove node from old bucket */
++      node_bucket_remove(&node_buckets[3], node);
++
++      /* Add node to back propagation list. */
++      node_bucket_insert(&reduced_bucket, node);
++}
++
++static void apply_heuristic_reductions_co(pbqp_t *pbqp, plist_t *rpeo)
++{
++      #if KAPS_TIMING
++              /* create timers */
++              ir_timer_t *t_edge = ir_timer_new();
++              ir_timer_t *t_r1   = ir_timer_new();
++              ir_timer_t *t_r2   = ir_timer_new();
++              ir_timer_t *t_rn   = ir_timer_new();
++      #endif
++
++      for (;;) {
++              if (edge_bucket_get_length(edge_bucket) > 0) {
++                      #if KAPS_TIMING
++                              ir_timer_start(t_edge);
++                      #endif
++
++                      apply_edge(pbqp);
++
++                      #if KAPS_TIMING
++                              ir_timer_stop(t_edge);
++                      #endif
++              } else if (node_bucket_get_length(node_buckets[1]) > 0) {
++                      #if KAPS_TIMING
++                              ir_timer_start(t_r1);
++                      #endif
++
++                      apply_RI(pbqp);
++
++                      #if KAPS_TIMING
++                              ir_timer_stop(t_r1);
++                      #endif
++              } else if (node_bucket_get_length(node_buckets[2]) > 0) {
++                      #if KAPS_TIMING
++                              ir_timer_start(t_r2);
++                      #endif
++
++                      apply_RII(pbqp);
++
++                      #if KAPS_TIMING
++                              ir_timer_stop(t_r2);
++                      #endif
++              } else if (merged_node != NULL) {
++                      #if KAPS_TIMING
++                              ir_timer_start(t_rn);
++                      #endif
++
++                      apply_RN_co_without_selection(pbqp);
++
++                      #if KAPS_TIMING
++                              ir_timer_stop(t_rn);
++                      #endif
++              } else if (node_bucket_get_length(node_buckets[3]) > 0) {
++                      #if KAPS_TIMING
++                              ir_timer_start(t_rn);
++                      #endif
++
++                      merge_into_RN_node(pbqp, rpeo);
++
++                      #if KAPS_TIMING
++                              ir_timer_stop(t_rn);
++                      #endif
++              } else {
++                      #if KAPS_TIMING
++                              printf("PBQP RE reductions:           %10.3lf msec\n", (double)ir_timer_elapsed_usec(t_edge) / 1000.0);
++                              printf("PBQP R1 reductions:           %10.3lf msec\n", (double)ir_timer_elapsed_usec(t_r1) / 1000.0);
++                              printf("PBQP R2 reductions:           %10.3lf msec\n", (double)ir_timer_elapsed_usec(t_r2) / 1000.0);
++                              printf("PBQP RN reductions:           %10.3lf msec\n", (double)ir_timer_elapsed_usec(t_rn) / 1000.0);
++                      #endif
++
++                      return;
++              }
++      }
++}
++
++void solve_pbqp_heuristical_co_ld(pbqp_t *pbqp, plist_t *rpeo)
++{
++      /* Reduce nodes degree ... */
++      initial_simplify_edges(pbqp);
++
++      /* ... and put node into bucket representing their degree. */
++      fill_node_buckets(pbqp);
++
++      #if KAPS_STATISTIC
++              FILE *fh = fopen("solutions.pb", "a");
++              fprintf(fh, "Solution");
++              fclose(fh);
++      #endif
++
++      apply_heuristic_reductions_co(pbqp, rpeo);
++
++      pbqp->solution = determine_solution(pbqp);
++
++      #if KAPS_STATISTIC
++              fh = fopen("solutions.pb", "a");
++              #if KAPS_USE_UNSIGNED
++                      fprintf(fh, ": %u RE:%u R0:%u R1:%u R2:%u RM:%u RN/BF:%u\n", pbqp->solution,
++                                      pbqp->num_edges, pbqp->num_r0, pbqp->num_r1, pbqp->num_r2,
++                                      pbqp->num_rm, pbqp->num_rn);
++              #else
++                      fprintf(fh, ": %lld RE:%u R0:%u R1:%u R2:%u RM:%u RN/BF:%u\n", pbqp->solution,
++                                      pbqp->num_edges, pbqp->num_r0, pbqp->num_r1, pbqp->num_r2,
++                                      pbqp->num_rm, pbqp->num_rn);
++              #endif
++              fclose(fh);
++      #endif
++
++      /* Solve reduced nodes. */
++      back_propagate_ld(pbqp);
++
++      free_buckets();
++}
index 0000000,0000000..097fe3b
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,16 @@@
++/*
++ * heuristical_co_ld.h
++ *
++ *  Created on: 06.05.2010
++ *      Author: berschth
++ */
++
++#ifndef HEURISTICAL_CO_LD_H_
++#define HEURISTICAL_CO_LD_H_
++
++#include "pbqp_t.h"
++#include "plist.h"
++
++void solve_pbqp_heuristical_co_ld(pbqp_t *pbqp, plist_t *rpeo);
++
++#endif /* HEURISTICAL_CO_LD_H_ */
index 0000000,0000000..93d0fd1
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,225 @@@
++/*
++ * Copyright (C) 1995-2008 University of Karlsruhe.  All right reserved.
++ *
++ * This file is part of libFirm.
++ *
++ * This file may be distributed and/or modified under the terms of the
++ * GNU General Public License version 2 as published by the Free Software
++ * Foundation and appearing in the file LICENSE.GPL included in the
++ * packaging of this file.
++ *
++ * Licensees holding valid libFirm Professional Edition licenses may use
++ * this file in accordance with the libFirm Commercial License.
++ * Agreement provided with the Software.
++ *
++ * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
++ * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
++ * PURPOSE.
++ */
++
++/**
++ * @file
++ * @brief   HTML dumper for PBQP.
++ * @date    03.10.2008
++ * @author  Sebastian Buchwald
++ * @version $Id$
++ */
++#include "config.h"
++
++#include "adt/array.h"
++#include "assert.h"
++
++#include "pbqp_edge_t.h"
++#include "pbqp_node_t.h"
++#include "optimal.h"
++#include "html_dumper.h"
++#include "kaps.h"
++
++/* Caution: Due to static buffer use only once per statement */
++static const char *cost2a(num const cost)
++{
++      static char buf[10];
++
++      if (cost == INF_COSTS) return "inf";
++#if KAPS_USE_UNSIGNED
++      sprintf(buf, "%u", cost);
++#else
++      sprintf(buf, "%10lld", cost);
++#endif
++      return buf;
++}
++
++/* print vector */
++static void dump_vector(FILE *f, vector_t *vec)
++{
++      unsigned index;
++      assert(vec);
++
++      fprintf(f, "<span class=\"vector\">( ");
++      unsigned len = vec->len;
++      assert(len > 0);
++      for (index = 0; index < len; ++index) {
++#if KAPS_ENABLE_VECTOR_NAMES
++              fprintf(f, "<span title=\"%s\">%s</span> ",
++                              vec->entries[index].name, cost2a(vec->entries[index].data));
++#else
++              fprintf(f, "%s ", cost2a(vec->entries[index].data));
++#endif
++      }
++      fprintf(f, " )</span>\n");
++}
++
++static void dump_matrix(FILE *f, pbqp_matrix_t *mat)
++{
++      unsigned row, col;
++      assert(mat);
++      num *p = mat->entries;
++
++      assert(mat->cols> 0);
++      assert(mat->rows> 0);
++      fprintf(f, "\t\\begin{pmatrix}\n");
++      for (row = 0; row < mat->rows; ++row) {
++              fprintf(f, "\t %s", cost2a(*p++));
++
++              for (col = 1; col < mat->cols; ++col) {
++                      fprintf(f, "& %s", cost2a(*p++));
++              }
++              fprintf(f, "\\\\\n");
++      }
++      fprintf(f, "\t\\end{pmatrix}\n");
++}
++
++void dump_edge(FILE *file, pbqp_edge_t *edge)
++{
++      fputs("<tex>\n", file);
++      fprintf(file, "\t\\overline\n{C}_{%d,%d}=\n",
++                      edge->src->index, edge->tgt->index);
++      dump_matrix(file, edge->costs);
++      fputs("</tex><br>", file);
++}
++
++static void dump_edge_costs(pbqp_t *pbqp)
++{
++      unsigned src_index;
++
++      assert(pbqp);
++      assert(pbqp->dump_file);
++
++      fputs("<p>", pbqp->dump_file);
++      for (src_index = 0; src_index < pbqp->num_nodes; ++src_index) {
++              pbqp_node_t *src_node = get_node(pbqp, src_index);
++
++              if (!src_node)
++                      continue;
++
++              unsigned edge_index;
++              unsigned len = ARR_LEN(src_node->edges);
++              for (edge_index = 0; edge_index < len; ++edge_index) {
++                      pbqp_edge_t *edge      = src_node->edges[edge_index];
++                      unsigned     tgt_index = edge->tgt->index;
++                      if (src_index < tgt_index) {
++                              dump_edge(pbqp->dump_file, edge);
++                      }
++              }
++      }
++      fputs("</p>", pbqp->dump_file);
++}
++
++void dump_node(FILE *file, pbqp_node_t *node)
++{
++      assert(file);
++
++      if (node) {
++              fprintf(file, "\tc<sub>%d</sub> = ", node->index);
++              dump_vector(file, node->costs);
++              fputs("<br>\n", file);
++      }
++}
++
++static void dump_node_costs(pbqp_t *pbqp)
++{
++      unsigned index;
++
++      assert(pbqp);
++      assert(pbqp->dump_file);
++
++      /* dump node costs */
++      fputs("<p>", pbqp->dump_file);
++      for (index = 0; index < pbqp->num_nodes; ++index) {
++              dump_node(pbqp->dump_file, get_node(pbqp, index));
++      }
++      fputs("</p>", pbqp->dump_file);
++}
++
++void dump_section(FILE *f, int level, const char *txt)
++{
++      assert(f);
++
++      fprintf(f, "<h%d>%s</h%d>\n", level, txt, level);
++}
++
++void pbqp_dump_graph(pbqp_t *pbqp)
++{
++      unsigned src_index;
++
++      assert(pbqp);
++      assert(pbqp->dump_file);
++
++      fputs("<p>\n<graph>\n\tgraph input {\n", pbqp->dump_file);
++      for (src_index = 0; src_index < pbqp->num_nodes; ++src_index) {
++              pbqp_node_t *node = get_node(pbqp, src_index);
++              if (node && !node_is_reduced(node)) {
++                      fprintf(pbqp->dump_file, "\t n%d;\n", src_index);
++              }
++      }
++
++      for (src_index = 0; src_index < pbqp->num_nodes; ++src_index) {
++              pbqp_node_t *node = get_node(pbqp, src_index);
++
++              if (!node)
++                      continue;
++
++              if (node_is_reduced(node))
++                      continue;
++
++              unsigned len = ARR_LEN(node->edges);
++              unsigned edge_index;
++              for (edge_index = 0; edge_index < len; ++edge_index) {
++                      pbqp_node_t *tgt_node  = node->edges[edge_index]->tgt;
++                      unsigned     tgt_index = tgt_node->index;
++
++                      if (node_is_reduced(tgt_node))
++                              continue;
++
++                      if (src_index < tgt_index) {
++                              fprintf(pbqp->dump_file, "\t n%d -- n%d;\n", src_index,
++                                              tgt_index);
++                      }
++              }
++      }
++      fputs("\t}\n</graph>\n</p>\n", pbqp->dump_file);
++}
++
++void pbqp_dump_input(pbqp_t *pbqp)
++{
++      assert(pbqp);
++      assert(pbqp->dump_file);
++
++      dump_section(pbqp->dump_file, 1, "1. PBQP Problem");
++      dump_section(pbqp->dump_file, 2, "1.1 Topology");
++      pbqp_dump_graph(pbqp);
++      dump_section(pbqp->dump_file, 2, "1.2 Cost Vectors");
++      dump_node_costs(pbqp);
++      dump_section(pbqp->dump_file, 2, "1.3 Cost Matrices");
++      dump_edge_costs(pbqp);
++}
++
++void dump_simplifyedge(pbqp_t *pbqp, pbqp_edge_t *edge)
++{
++      assert(pbqp);
++      assert(pbqp->dump_file);
++
++      dump_node(pbqp->dump_file, edge->src);
++      dump_edge(pbqp->dump_file, edge);
++      dump_node(pbqp->dump_file, edge->tgt);
++}
index 0000000,0000000..7f0ac06
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,43 @@@
++/*
++ * Copyright (C) 1995-2008 University of Karlsruhe.  All right reserved.
++ *
++ * This file is part of libFirm.
++ *
++ * This file may be distributed and/or modified under the terms of the
++ * GNU General Public License version 2 as published by the Free Software
++ * Foundation and appearing in the file LICENSE.GPL included in the
++ * packaging of this file.
++ *
++ * Licensees holding valid libFirm Professional Edition licenses may use
++ * this file in accordance with the libFirm Commercial License.
++ * Agreement provided with the Software.
++ *
++ * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
++ * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
++ * PURPOSE.
++ */
++
++/**
++ * @file
++ * @brief   HTML dumper for PBQP.
++ * @date    03.10.2008
++ * @author  Sebastian Buchwald
++ * @version $Id$
++ */
++#ifndef KAPS_HTML_DUMPER_H
++#define KAPS_HTML_DUMPER_H
++
++#include "pbqp_t.h"
++
++void pbqp_dump_input(pbqp_t *pbqp);
++
++void pbqp_dump_graph(pbqp_t *pbqp);
++
++void dump_simplifyedge(pbqp_t *pbqp, pbqp_edge_t *edge);
++
++void dump_section(FILE *f, int level, const char *txt);
++
++void dump_node(FILE *file, pbqp_node_t *node);
++void dump_edge(FILE *file, pbqp_edge_t *edge);
++
++#endif /* KAPS_HTML_DUMPER_H */
diff --cc ir/kaps/kaps.c
index 0000000,0000000..8bbbd93
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,153 @@@
++/*
++ * Copyright (C) 1995-2008 University of Karlsruhe.  All right reserved.
++ *
++ * This file is part of libFirm.
++ *
++ * This file may be distributed and/or modified under the terms of the
++ * GNU General Public License version 2 as published by the Free Software
++ * Foundation and appearing in the file LICENSE.GPL included in the
++ * packaging of this file.
++ *
++ * Licensees holding valid libFirm Professional Edition licenses may use
++ * this file in accordance with the libFirm Commercial License.
++ * Agreement provided with the Software.
++ *
++ * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
++ * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
++ * PURPOSE.
++ */
++
++/**
++ * @file
++ * @brief   Partitioned Boolean Quadratic Problem (PBQP) solver.
++ * @date    02.10.2008
++ * @author  Sebastian Buchwald
++ * @version $Id$
++ */
++#include "config.h"
++
++#include "adt/array.h"
++#include "adt/xmalloc.h"
++
++#include "kaps.h"
++#include "matrix.h"
++#include "pbqp_edge.h"
++#include "pbqp_edge_t.h"
++#include "pbqp_node.h"
++#include "pbqp_node_t.h"
++#include "vector.h"
++
++pbqp_node_t *get_node(pbqp_t *pbqp, unsigned index)
++{
++      return pbqp->nodes[index];
++}
++
++pbqp_edge_t *get_edge(pbqp_t *pbqp, unsigned src_index, unsigned tgt_index)
++{
++      int i;
++      int len;
++
++      if (tgt_index < src_index) {
++              unsigned tmp = src_index;
++              src_index    = tgt_index;
++              tgt_index    = tmp;
++      }
++
++      pbqp_node_t *src_node = get_node(pbqp, src_index);
++      pbqp_node_t *tgt_node = get_node(pbqp, tgt_index);
++      assert(src_node);
++      assert(tgt_node);
++
++      len = ARR_LEN(src_node->edges);
++
++      for (i = 0; i < len; ++i) {
++              pbqp_edge_t *cur_edge = src_node->edges[i];
++              if (cur_edge->tgt == tgt_node) {
++                      return cur_edge;
++              }
++      }
++
++      return NULL;
++}
++
++pbqp_t *alloc_pbqp(unsigned number_nodes)
++{
++      pbqp_t *pbqp = XMALLOC(pbqp_t);
++
++      obstack_init(&pbqp->obstack);
++
++      pbqp->solution = 0;
++      pbqp->num_nodes = number_nodes;
++#if   KAPS_DUMP
++      pbqp->dump_file = NULL;
++#endif
++      pbqp->nodes = OALLOCNZ(&pbqp->obstack, pbqp_node_t*, number_nodes);
++#if KAPS_STATISTIC
++      pbqp->num_bf = 0;
++      pbqp->num_edges = 0;
++      pbqp->num_r0 = 0;
++      pbqp->num_r1 = 0;
++      pbqp->num_r2 = 0;
++      pbqp->num_rm = 0;
++      pbqp->num_rn = 0;
++#endif
++
++      return pbqp;
++}
++
++void free_pbqp(pbqp_t *pbqp)
++{
++      obstack_free(&pbqp->obstack, NULL);
++      xfree(pbqp);
++}
++
++void add_node_costs(pbqp_t *pbqp, unsigned node_index, vector_t *costs)
++{
++      pbqp_node_t *node = get_node(pbqp, node_index);
++
++      if (node == NULL) {
++              node = alloc_node(pbqp, node_index, costs);
++              pbqp->nodes[node_index] = node;
++      } else {
++              vector_add(node->costs, costs);
++      }
++}
++
++void add_edge_costs(pbqp_t *pbqp, unsigned src_index, unsigned tgt_index,
++                    pbqp_matrix_t *costs)
++{
++      pbqp_edge_t *edge = get_edge(pbqp, src_index, tgt_index);
++
++      if (tgt_index < src_index) {
++              pbqp_matrix_transpose(pbqp, costs);
++              add_edge_costs(pbqp, tgt_index, src_index, costs);
++              return;
++      }
++
++      if (edge == NULL) {
++              edge = alloc_edge(pbqp, src_index, tgt_index, costs);
++      } else {
++              pbqp_matrix_add(edge->costs, costs);
++      }
++}
++
++num get_node_solution(pbqp_t *pbqp, unsigned node_index)
++{
++      pbqp_node_t *node = get_node(pbqp, node_index);
++      assert(node);
++
++      return node->solution;
++}
++
++num get_solution(pbqp_t *pbqp)
++{
++      return pbqp->solution;
++}
++
++#if   KAPS_DUMP
++void set_dumpfile(pbqp *pbqp, FILE *f)
++{
++      assert(pbqp);
++      pbqp->dump_file = f;
++}
++#endif
diff --cc ir/kaps/kaps.h
index 0000000,0000000..c9097aa
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,61 @@@
++/*
++ * Copyright (C) 1995-2008 University of Karlsruhe.  All right reserved.
++ *
++ * This file is part of libFirm.
++ *
++ * This file may be distributed and/or modified under the terms of the
++ * GNU General Public License version 2 as published by the Free Software
++ * Foundation and appearing in the file LICENSE.GPL included in the
++ * packaging of this file.
++ *
++ * Licensees holding valid libFirm Professional Edition licenses may use
++ * this file in accordance with the libFirm Commercial License.
++ * Agreement provided with the Software.
++ *
++ * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
++ * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
++ * PURPOSE.
++ */
++
++/**
++ * @file
++ * @brief   Partitioned Boolean Quadratic Problem (PBQP) solver.
++ * @date    02.10.2008
++ * @author  Sebastian Buchwald
++ * @version $Id$
++ */
++#ifndef KAPS_KAPS_H
++#define KAPS_KAPS_H
++
++#include "pbqp_t.h"
++
++/**
++ * Create an empty PBQP instance with the given number of nodes.
++ */
++pbqp_t* alloc_pbqp(unsigned number_nodes);
++
++/**
++ * Free the given PBQP.
++ */
++void free_pbqp(pbqp_t *pbqp);
++
++/**
++ * Add costs vector to given node.
++ */
++void add_node_costs(pbqp_t *pbqp, unsigned node_index, vector_t *costs);
++
++/**
++ * Add costs matrix between given nodes.
++ */
++void add_edge_costs(pbqp_t *pbqp, unsigned src_index, unsigned tgt_index,
++                    pbqp_matrix_t *costs);
++
++pbqp_edge_t *get_edge(pbqp_t *pbqp, unsigned src_index, unsigned tgt_index);
++pbqp_node_t *get_node(pbqp_t *pbqp, unsigned index);
++
++num get_node_solution(pbqp_t *pbqp, unsigned node_index);
++num get_solution(pbqp_t *pbqp);
++
++void set_dumpfile(pbqp_t *pbqp, FILE *f);
++
++#endif /* KAPS_KAPS_H */
index 0000000,0000000..8608057
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,386 @@@
++/*
++ * Copyright (C) 1995-2008 University of Karlsruhe.  All right reserved.
++ *
++ * This file is part of libFirm.
++ *
++ * This file may be distributed and/or modified under the terms of the
++ * GNU General Public License version 2 as published by the Free Software
++ * Foundation and appearing in the file LICENSE.GPL included in the
++ * packaging of this file.
++ *
++ * Licensees holding valid libFirm Professional Edition licenses may use
++ * this file in accordance with the libFirm Commercial License.
++ * Agreement provided with the Software.
++ *
++ * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
++ * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
++ * PURPOSE.
++ */
++
++/**
++ * @file
++ * @brief   PBQP matrix.
++ * @date    02.10.2008
++ * @author  Sebastian Buchwald
++ * @version $Id$
++ */
++#include "config.h"
++
++#include <assert.h>
++#include <string.h>
++
++#include "pbqp_t.h"
++#include "vector.h"
++#include "matrix.h"
++
++pbqp_matrix_t *pbqp_matrix_alloc(pbqp_t *pbqp, unsigned rows, unsigned cols)
++{
++      assert(cols> 0);
++      assert(rows> 0);
++
++      unsigned length = rows * cols;
++
++      pbqp_matrix_t *mat = (pbqp_matrix_t*)obstack_alloc(&pbqp->obstack, sizeof(*mat) + sizeof(*mat->entries) * length);
++      assert(mat);
++
++      mat->cols = cols;
++      mat->rows = rows;
++      memset(mat->entries, 0, sizeof(*mat->entries) * length);
++
++      return mat;
++}
++
++pbqp_matrix_t *pbqp_matrix_copy(pbqp_t *pbqp, pbqp_matrix_t *m)
++{
++      unsigned       len  = m->rows * m->cols;
++      pbqp_matrix_t *copy = (pbqp_matrix_t*)obstack_copy(&pbqp->obstack, m, sizeof(*copy) + sizeof(*copy->entries) * len);
++      assert(copy);
++
++      return copy;
++}
++
++pbqp_matrix_t *pbqp_matrix_copy_and_transpose(pbqp_t *pbqp, pbqp_matrix_t *m)
++{
++      unsigned       i;
++      unsigned       j;
++      unsigned       cols = m->cols;
++      unsigned       rows = m->rows;
++      unsigned       len  = rows * cols;
++      pbqp_matrix_t *copy = (pbqp_matrix_t*)obstack_alloc(&pbqp->obstack, sizeof(*copy) + sizeof(*copy->entries) * len);
++      assert(copy);
++
++      for (i = 0; i < rows; ++i) {
++              for (j = 0; j < cols; ++j) {
++                      copy->entries[j*rows+i] = m->entries[i*cols+j];
++              }
++      }
++
++      copy->cols = rows;
++      copy->rows = cols;
++
++      return copy;
++}
++
++void pbqp_matrix_transpose(pbqp_t *pbqp, pbqp_matrix_t *mat)
++{
++      unsigned len;
++
++      assert(mat);
++      len = mat->rows * mat->cols;
++
++      pbqp_matrix_t *tmp = pbqp_matrix_copy_and_transpose(pbqp, mat);
++
++      memcpy(mat, tmp, sizeof(*mat) + sizeof(*mat->entries) * len);
++
++      obstack_free(&pbqp->obstack, tmp);
++}
++
++void pbqp_matrix_add(pbqp_matrix_t *sum, pbqp_matrix_t *summand)
++{
++      int i;
++      int len;
++
++      assert(sum);
++      assert(summand);
++      assert(sum->cols == summand->cols);
++      assert(sum->rows == summand->rows);
++
++      len = sum->rows * sum->cols;
++
++      for (i = 0; i < len; ++i) {
++              sum->entries[i] = pbqp_add(sum->entries[i], summand->entries[i]);
++      }
++}
++
++void pbqp_matrix_set_col_value(pbqp_matrix_t *mat, unsigned col, num value)
++{
++      unsigned row_index;
++      unsigned row_len;
++
++      assert(mat);
++      assert(col < mat->cols);
++
++      row_len = mat->rows;
++
++      for (row_index = 0; row_index < row_len; ++row_index) {
++              mat->entries[row_index * mat->cols + col] = value;
++      }
++}
++
++void pbqp_matrix_set_row_value(pbqp_matrix_t *mat, unsigned row, num value)
++{
++      unsigned col_index;
++      unsigned col_len;
++
++      assert(mat);
++      assert(row < mat->rows);
++
++      col_len = mat->cols;
++
++      for (col_index = 0; col_index < col_len; ++col_index) {
++              mat->entries[row * mat->cols + col_index] = value;
++      }
++}
++
++void pbqp_matrix_set(pbqp_matrix_t *mat, unsigned row, unsigned col, num value)
++{
++      assert(mat);
++      assert(col < mat->cols);
++      assert(row < mat->rows);
++
++      mat->entries[row * mat->cols + col] = value;
++}
++
++num pbqp_matrix_get_col_min(pbqp_matrix_t *matrix, unsigned col_index, vector_t *flags)
++{
++      unsigned row_index;
++      num min = INF_COSTS;
++
++      assert(matrix);
++      assert(flags);
++      assert(matrix->rows == flags->len);
++
++      unsigned col_len = matrix->cols;
++      unsigned row_len = matrix->rows;
++
++      for (row_index = 0; row_index < row_len; ++row_index) {
++              /* Ignore virtual deleted columns. */
++              if (flags->entries[row_index].data == INF_COSTS) continue;
++
++              num elem = matrix->entries[row_index * col_len + col_index];
++
++              if (elem < min) {
++                      min = elem;
++              }
++      }
++
++      return min;
++}
++
++unsigned pbqp_matrix_get_col_min_index(pbqp_matrix_t *matrix, unsigned col_index, vector_t *flags)
++{
++      unsigned row_index;
++      unsigned min_index = 0;
++      num      min       = INF_COSTS;
++
++      assert(matrix);
++      assert(flags);
++      assert(matrix->rows == flags->len);
++
++      unsigned col_len = matrix->cols;
++      unsigned row_len = matrix->rows;
++
++      for (row_index = 0; row_index < row_len; ++row_index) {
++              /* Ignore virtual deleted columns. */
++              if (flags->entries[row_index].data == INF_COSTS) continue;
++
++              num elem = matrix->entries[row_index * col_len + col_index];
++
++              if (elem < min) {
++                      min = elem;
++                      min_index = row_index;
++              }
++      }
++
++      return min_index;
++}
++
++void pbqp_matrix_sub_col_value(pbqp_matrix_t *matrix, unsigned col_index,
++              vector_t *flags, num value)
++{
++      unsigned col_len;
++      unsigned row_index;
++      unsigned row_len;
++
++      assert(matrix);
++      assert(flags);
++      assert(matrix->rows == flags->len);
++
++      col_len = matrix->cols;
++      row_len = matrix->rows;
++
++      for (row_index = 0; row_index < row_len; ++row_index) {
++              if (flags->entries[row_index].data == INF_COSTS) {
++                      matrix->entries[row_index * col_len + col_index] = 0;
++                      continue;
++              }
++              /* inf - x = inf if x < inf */
++              if (matrix->entries[row_index * col_len + col_index] == INF_COSTS && value
++                              != INF_COSTS)
++                      continue;
++              matrix->entries[row_index * col_len + col_index] -= value;
++      }
++}
++
++num pbqp_matrix_get_row_min(pbqp_matrix_t *matrix, unsigned row_index, vector_t *flags)
++{
++      unsigned col_index;
++      num min = INF_COSTS;
++
++      assert(matrix);
++      assert(flags);
++      assert(matrix->cols == flags->len);
++
++      unsigned len = flags->len;
++
++      for (col_index = 0; col_index < len; ++col_index) {
++              /* Ignore virtual deleted columns. */
++              if (flags->entries[col_index].data == INF_COSTS) continue;
++
++              num elem = matrix->entries[row_index * len + col_index];
++
++              if (elem < min) {
++                      min = elem;
++              }
++      }
++
++      return min;
++}
++
++unsigned pbqp_matrix_get_row_min_index(pbqp_matrix_t *matrix, unsigned row_index, vector_t *flags)
++{
++      unsigned col_index;
++      unsigned min_index = 0;
++      num      min       = INF_COSTS;
++
++      assert(matrix);
++      assert(flags);
++      assert(matrix->cols == flags->len);
++
++      unsigned len = flags->len;
++
++      for (col_index = 0; col_index < len; ++col_index) {
++              /* Ignore virtual deleted columns. */
++              if (flags->entries[col_index].data == INF_COSTS) continue;
++
++              num elem = matrix->entries[row_index * len + col_index];
++
++              if (elem < min) {
++                      min = elem;
++                      min_index = col_index;
++              }
++      }
++
++      return min_index;
++}
++
++void pbqp_matrix_sub_row_value(pbqp_matrix_t *matrix, unsigned row_index,
++              vector_t *flags, num value)
++{
++      unsigned col_index;
++      unsigned col_len;
++
++      assert(matrix);
++      assert(flags);
++      assert(matrix->cols == flags->len);
++
++      col_len = matrix->cols;
++
++      for (col_index = 0; col_index < col_len; ++col_index) {
++              if (flags->entries[col_index].data == INF_COSTS) {
++                      matrix->entries[row_index * col_len + col_index] = 0;
++                      continue;
++              }
++              /* inf - x = inf if x < inf */
++              if (matrix->entries[row_index * col_len + col_index] == INF_COSTS && value
++                              != INF_COSTS)
++                      continue;
++              matrix->entries[row_index * col_len + col_index] -= value;
++      }
++}
++
++int pbqp_matrix_is_zero(pbqp_matrix_t *mat, vector_t *src_vec, vector_t *tgt_vec)
++{
++      unsigned col_index;
++      unsigned col_len;
++      unsigned row_index;
++      unsigned row_len;
++
++      assert(mat);
++      assert(src_vec);
++      assert(tgt_vec);
++      assert(mat->cols = tgt_vec->len);
++      assert(mat->rows = src_vec->len);
++
++      col_len = mat->cols;
++      row_len = mat->rows;
++
++      for (row_index = 0; row_index < row_len; ++row_index) {
++              if (src_vec->entries[row_index].data == INF_COSTS) continue;
++              for (col_index = 0; col_index < col_len; ++col_index) {
++                      if (tgt_vec->entries[col_index].data == INF_COSTS) continue;
++
++                      if (mat->entries[row_index * col_len + col_index] != 0) {
++                              return 0;
++                      }
++              }
++      }
++
++      return 1;
++}
++
++void pbqp_matrix_add_to_all_cols(pbqp_matrix_t *mat, vector_t *vec)
++{
++      unsigned col_index;
++      unsigned col_len;
++      unsigned row_index;
++      unsigned row_len;
++
++      assert(mat);
++      assert(vec);
++      assert(mat->rows == vec->len);
++
++      col_len = mat->cols;
++      row_len = mat->rows;
++
++      for (row_index = 0; row_index < row_len; ++row_index) {
++              num value = vec->entries[row_index].data;
++              for (col_index = 0; col_index < col_len; ++col_index) {
++                      mat->entries[row_index * col_len + col_index] = pbqp_add(
++                                      mat->entries[row_index * col_len + col_index], value);
++              }
++      }
++}
++
++void pbqp_matrix_add_to_all_rows(pbqp_matrix_t *mat, vector_t *vec)
++{
++      unsigned col_index;
++      unsigned col_len;
++      unsigned row_index;
++      unsigned row_len;
++
++      assert(mat);
++      assert(vec);
++      assert(mat->cols == vec->len);
++
++      col_len = mat->cols;
++      row_len = mat->rows;
++
++      for (row_index = 0; row_index < row_len; ++row_index) {
++              for (col_index = 0; col_index < col_len; ++col_index) {
++                      num value = vec->entries[col_index].data;
++
++                      mat->entries[row_index * col_len + col_index] = pbqp_add(mat->entries[row_index * col_len + col_index], value);
++              }
++      }
++}
index 0000000,0000000..c87f777
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,65 @@@
++/*
++ * Copyright (C) 1995-2008 University of Karlsruhe.  All right reserved.
++ *
++ * This file is part of libFirm.
++ *
++ * This file may be distributed and/or modified under the terms of the
++ * GNU General Public License version 2 as published by the Free Software
++ * Foundation and appearing in the file LICENSE.GPL included in the
++ * packaging of this file.
++ *
++ * Licensees holding valid libFirm Professional Edition licenses may use
++ * this file in accordance with the libFirm Commercial License.
++ * Agreement provided with the Software.
++ *
++ * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
++ * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
++ * PURPOSE.
++ */
++
++/**
++ * @file
++ * @brief   PBQP matrix.
++ * @date    02.10.2008
++ * @author  Sebastian Buchwald
++ * @version $Id$
++ */
++#ifndef KAPS_MATRIX_H
++#define KAPS_MATRIX_H
++
++#include "matrix_t.h"
++
++pbqp_matrix_t *pbqp_matrix_alloc(pbqp_t *pbqp, unsigned rows, unsigned cols);
++
++/* Copy the given matrix. */
++pbqp_matrix_t *pbqp_matrix_copy(pbqp_t *pbqp, pbqp_matrix_t *m);
++
++pbqp_matrix_t *pbqp_matrix_copy_and_transpose(pbqp_t *pbqp, pbqp_matrix_t *m);
++
++void pbqp_matrix_transpose(pbqp_t *pbqp, pbqp_matrix_t *mat);
++
++/* sum += summand */
++void pbqp_matrix_add(pbqp_matrix_t *sum, pbqp_matrix_t *summand);
++
++void pbqp_matrix_set(pbqp_matrix_t *mat, unsigned row, unsigned col, num value);
++
++num pbqp_matrix_get_col_min(pbqp_matrix_t *matrix, unsigned col_index, vector_t *flags);
++num pbqp_matrix_get_row_min(pbqp_matrix_t *matrix, unsigned row_index, vector_t *flags);
++
++unsigned pbqp_matrix_get_col_min_index(pbqp_matrix_t *matrix, unsigned col_index, vector_t *flags);
++unsigned pbqp_matrix_get_row_min_index(pbqp_matrix_t *matrix, unsigned row_index, vector_t *flags);
++
++void pbqp_matrix_set_col_value(pbqp_matrix_t *mat, unsigned col, num value);
++void pbqp_matrix_set_row_value(pbqp_matrix_t *mat, unsigned row, num value);
++
++void pbqp_matrix_sub_col_value(pbqp_matrix_t *matrix, unsigned col_index,
++                               vector_t *flags, num value);
++void pbqp_matrix_sub_row_value(pbqp_matrix_t *matrix, unsigned row_index,
++                               vector_t *flags, num value);
++
++int pbqp_matrix_is_zero(pbqp_matrix_t *mat, vector_t *src_vec, vector_t *tgt_vec);
++
++void pbqp_matrix_add_to_all_cols(pbqp_matrix_t *mat, vector_t *vec);
++void pbqp_matrix_add_to_all_rows(pbqp_matrix_t *mat, vector_t *vec);
++
++#endif /* KAPS_MATRIX_H */
index 0000000,0000000..f1458c1
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,40 @@@
++/*
++ * Copyright (C) 1995-2008 University of Karlsruhe.  All right reserved.
++ *
++ * This file is part of libFirm.
++ *
++ * This file may be distributed and/or modified under the terms of the
++ * GNU General Public License version 2 as published by the Free Software
++ * Foundation and appearing in the file LICENSE.GPL included in the
++ * packaging of this file.
++ *
++ * Licensees holding valid libFirm Professional Edition licenses may use
++ * this file in accordance with the libFirm Commercial License.
++ * Agreement provided with the Software.
++ *
++ * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
++ * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
++ * PURPOSE.
++ */
++
++/**
++ * @file
++ * @brief   PBQP matrix data types.
++ * @date    02.10.2008
++ * @author  Sebastian Buchwald
++ * @version $Id$
++ */
++#ifndef KAPS_MATRIX_T_H
++#define KAPS_MATRIX_T_H
++
++#include "pbqp_t.h"
++
++typedef struct pbqp_matrix_t pbqp_matrix_t;
++
++struct pbqp_matrix_t {
++      unsigned rows;
++      unsigned cols;
++      num entries[];
++};
++
++#endif /* KAPS_MATRIX_T_H */
index 0000000,0000000..fe82844
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,1465 @@@
++/*
++ * Copyright (C) 1995-2008 University of Karlsruhe.  All right reserved.
++ *
++ * This file is part of libFirm.
++ *
++ * This file may be distributed and/or modified under the terms of the
++ * GNU General Public License version 2 as published by the Free Software
++ * Foundation and appearing in the file LICENSE.GPL included in the
++ * packaging of this file.
++ *
++ * Licensees holding valid libFirm Professional Edition licenses may use
++ * this file in accordance with the libFirm Commercial License.
++ * Agreement provided with the Software.
++ *
++ * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
++ * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
++ * PURPOSE.
++ */
++
++/**
++ * @file
++ * @brief   Optimal reductions and helper functions.
++ * @date    28.12.2009
++ * @author  Sebastian Buchwald
++ * @version $Id$
++ */
++#include "config.h"
++
++#include "adt/array.h"
++#include "assert.h"
++#include "error.h"
++
++#include "bucket.h"
++#if   KAPS_DUMP
++#include "html_dumper.h"
++#endif
++#include "kaps.h"
++#include "matrix.h"
++#include "optimal.h"
++#include "pbqp_edge.h"
++#include "pbqp_edge_t.h"
++#include "pbqp_node.h"
++#include "pbqp_node_t.h"
++#include "vector.h"
++
++#include "plist.h"
++#include "timing.h"
++
++pbqp_edge_t **edge_bucket;
++pbqp_edge_t **rm_bucket;
++pbqp_node_t **node_buckets[4];
++pbqp_node_t **reduced_bucket = NULL;
++pbqp_node_t  *merged_node = NULL;
++static int  buckets_filled = 0;
++
++static void insert_into_edge_bucket(pbqp_edge_t *edge)
++{
++      if (edge_bucket_contains(edge_bucket, edge)) {
++              /* Edge is already inserted. */
++              return;
++      }
++
++      edge_bucket_insert(&edge_bucket, edge);
++}
++
++static void insert_into_rm_bucket(pbqp_edge_t *edge)
++{
++      if (edge_bucket_contains(rm_bucket, edge)) {
++              /* Edge is already inserted. */
++              return;
++      }
++
++      edge_bucket_insert(&rm_bucket, edge);
++}
++
++static void init_buckets(void)
++{
++      int i;
++
++      edge_bucket_init(&edge_bucket);
++      edge_bucket_init(&rm_bucket);
++      node_bucket_init(&reduced_bucket);
++
++      for (i = 0; i < 4; ++i) {
++              node_bucket_init(&node_buckets[i]);
++      }
++}
++
++void free_buckets(void)
++{
++      int i;
++
++      for (i = 0; i < 4; ++i) {
++              node_bucket_free(&node_buckets[i]);
++      }
++
++      edge_bucket_free(&edge_bucket);
++      edge_bucket_free(&rm_bucket);
++      node_bucket_free(&reduced_bucket);
++
++      buckets_filled = 0;
++}
++
++void fill_node_buckets(pbqp_t *pbqp)
++{
++      unsigned node_index;
++      unsigned node_len;
++
++      assert(pbqp);
++      node_len = pbqp->num_nodes;
++
++      #if KAPS_TIMING
++              ir_timer_t *t_fill_buckets = ir_timer_new();
++              ir_timer_start(t_fill_buckets);
++      #endif
++
++      for (node_index = 0; node_index < node_len; ++node_index) {
++              unsigned     degree;
++              pbqp_node_t *node = get_node(pbqp, node_index);
++
++              if (!node) continue;
++
++              degree = pbqp_node_get_degree(node);
++
++              /* We have only one bucket for nodes with arity >= 3. */
++              if (degree > 3) {
++                      degree = 3;
++              }
++
++              node_bucket_insert(&node_buckets[degree], node);
++      }
++
++      buckets_filled = 1;
++
++      #if KAPS_TIMING
++              ir_timer_stop(t_fill_buckets);
++              printf("PBQP Fill Nodes into buckets: %10.3lf msec\n", (double)ir_timer_elapsed_usec(t_fill_buckets) / 1000.0);
++      #endif
++}
++
++static void normalize_towards_source(pbqp_edge_t *edge)
++{
++      pbqp_matrix_t  *mat;
++      pbqp_node_t    *src_node;
++      pbqp_node_t    *tgt_node;
++      vector_t       *src_vec;
++      vector_t       *tgt_vec;
++      unsigned        src_len;
++      unsigned        tgt_len;
++      unsigned        src_index;
++      unsigned        new_infinity = 0;
++
++      assert(edge);
++
++      src_node = edge->src;
++      tgt_node = edge->tgt;
++      assert(src_node);
++      assert(tgt_node);
++
++      src_vec = src_node->costs;
++      tgt_vec = tgt_node->costs;
++      assert(src_vec);
++      assert(tgt_vec);
++
++      src_len = src_vec->len;
++      tgt_len = tgt_vec->len;
++      assert(src_len > 0);
++      assert(tgt_len > 0);
++
++      mat = edge->costs;
++      assert(mat);
++
++      /* Normalize towards source node. */
++      for (src_index = 0; src_index < src_len; ++src_index) {
++              num min = pbqp_matrix_get_row_min(mat, src_index, tgt_vec);
++
++              if (min != 0) {
++                      if (src_vec->entries[src_index].data == INF_COSTS) {
++                              pbqp_matrix_set_row_value(mat, src_index, 0);
++                              continue;
++                      }
++
++                      pbqp_matrix_sub_row_value(mat, src_index, tgt_vec, min);
++                      src_vec->entries[src_index].data = pbqp_add(
++                                      src_vec->entries[src_index].data, min);
++
++                      if (min == INF_COSTS) {
++                              new_infinity = 1;
++                      }
++              }
++      }
++
++      if (new_infinity) {
++              unsigned edge_index;
++              unsigned edge_len = pbqp_node_get_degree(src_node);
++
++              for (edge_index = 0; edge_index < edge_len; ++edge_index) {
++                      pbqp_edge_t *edge_candidate = src_node->edges[edge_index];
++
++                      if (edge_candidate != edge) {
++                              insert_into_edge_bucket(edge_candidate);
++                      }
++              }
++      }
++}
++
++static void normalize_towards_target(pbqp_edge_t *edge)
++{
++      pbqp_matrix_t  *mat;
++      pbqp_node_t    *src_node;
++      pbqp_node_t    *tgt_node;
++      vector_t       *src_vec;
++      vector_t       *tgt_vec;
++      unsigned        src_len;
++      unsigned        tgt_len;
++      unsigned        tgt_index;
++      unsigned        new_infinity = 0;
++
++      assert(edge);
++
++      src_node = edge->src;
++      tgt_node = edge->tgt;
++      assert(src_node);
++      assert(tgt_node);
++
++      src_vec = src_node->costs;
++      tgt_vec = tgt_node->costs;
++      assert(src_vec);
++      assert(tgt_vec);
++
++      src_len = src_vec->len;
++      tgt_len = tgt_vec->len;
++      assert(src_len > 0);
++      assert(tgt_len > 0);
++
++      mat = edge->costs;
++      assert(mat);
++
++      /* Normalize towards target node. */
++      for (tgt_index = 0; tgt_index < tgt_len; ++tgt_index) {
++              num min = pbqp_matrix_get_col_min(mat, tgt_index, src_vec);
++
++              if (min != 0) {
++                      if (tgt_vec->entries[tgt_index].data == INF_COSTS) {
++                              pbqp_matrix_set_col_value(mat, tgt_index, 0);
++                              continue;
++                      }
++
++                      pbqp_matrix_sub_col_value(mat, tgt_index, src_vec, min);
++                      tgt_vec->entries[tgt_index].data = pbqp_add(
++                                      tgt_vec->entries[tgt_index].data, min);
++
++                      if (min == INF_COSTS) {
++                              new_infinity = 1;
++                      }
++              }
++      }
++
++      if (new_infinity) {
++              unsigned edge_index;
++              unsigned edge_len = pbqp_node_get_degree(tgt_node);
++
++              for (edge_index = 0; edge_index < edge_len; ++edge_index) {
++                      pbqp_edge_t *edge_candidate = tgt_node->edges[edge_index];
++
++                      if (edge_candidate != edge) {
++                              insert_into_edge_bucket(edge_candidate);
++                      }
++              }
++      }
++}
++
++/**
++ * Tries to apply RM for the source node of the given edge.
++ *
++ * Checks whether the source node of edge can be merged into the target node of
++ * edge, and performs the merge, if possible.
++ */
++static void merge_source_into_target(pbqp_t *pbqp, pbqp_edge_t *edge)
++{
++      pbqp_matrix_t  *mat;
++      pbqp_node_t    *src_node;
++      pbqp_node_t    *tgt_node;
++      vector_t       *src_vec;
++      vector_t       *tgt_vec;
++      unsigned       *mapping;
++      unsigned        src_len;
++      unsigned        tgt_len;
++      unsigned        src_index;
++      unsigned        tgt_index;
++      unsigned        edge_index;
++      unsigned        edge_len;
++
++      assert(pbqp);
++      assert(edge);
++
++      src_node = edge->src;
++      tgt_node = edge->tgt;
++      assert(src_node);
++      assert(tgt_node);
++
++      src_vec = src_node->costs;
++      tgt_vec = tgt_node->costs;
++      assert(src_vec);
++      assert(tgt_vec);
++
++      src_len = src_vec->len;
++      tgt_len = tgt_vec->len;
++
++      /* Matrizes are normalized. */
++      assert(src_len > 1);
++      assert(tgt_len > 1);
++
++      mat = edge->costs;
++      assert(mat);
++
++      mapping = NEW_ARR_F(unsigned, tgt_len);
++
++      /* Check that each column has at most one zero entry. */
++      for (tgt_index = 0; tgt_index < tgt_len; ++tgt_index) {
++              unsigned onlyOneZero = 0;
++
++              if (tgt_vec->entries[tgt_index].data == INF_COSTS)
++                      continue;
++
++              for (src_index = 0; src_index < src_len; ++src_index) {
++                      if (src_vec->entries[src_index].data == INF_COSTS)
++                              continue;
++
++                      if (mat->entries[src_index * tgt_len + tgt_index] == INF_COSTS)
++                              continue;
++
++                      /* Matrix entry is finite. */
++                      if (onlyOneZero) {
++                              DEL_ARR_F(mapping);
++                              return;
++                      }
++
++                      onlyOneZero = 1;
++                      mapping[tgt_index] = src_index;
++              }
++      }
++
++      /* We know that we can merge the source node into the target node. */
++      edge_len = pbqp_node_get_degree(src_node);
++
++#if KAPS_STATISTIC
++      pbqp->num_rm++;
++#endif
++
++#if   KAPS_DUMP
++      if (pbqp->dump_file) {
++              char txt[100];
++              sprintf(txt, "Merging n%d into n%d", src_node->index, tgt_node->index);
++              dump_section(pbqp->dump_file, 3, txt);
++      }
++#endif
++
++      /* Reconnect the source's edges with the target node. */
++      for (edge_index = 0; edge_index < edge_len; ++edge_index) {
++              pbqp_edge_t   *old_edge = src_node->edges[edge_index];
++              pbqp_edge_t   *new_edge;
++              pbqp_matrix_t *old_matrix;
++              pbqp_matrix_t *new_matrix;
++              pbqp_node_t   *other_node;
++              vector_t      *other_vec;
++              unsigned       other_len;
++              unsigned       other_index;
++              unsigned       tgt_index;
++
++              assert(old_edge);
++
++              if (old_edge == edge)
++                      continue;
++
++              old_matrix = old_edge->costs;
++              assert(old_matrix);
++
++              if (old_edge->tgt == src_node) {
++                      other_node = old_edge->src;
++                      other_len  = old_matrix->rows;
++              }
++              else {
++                      other_node = old_edge->tgt;
++                      other_len = old_matrix->cols;
++              }
++              assert(other_node);
++              other_vec = other_node->costs;
++
++              new_matrix = pbqp_matrix_alloc(pbqp, tgt_len, other_len);
++
++              /* Source node selects the column of the old_matrix. */
++              if (old_edge->tgt == src_node) {
++                      for (tgt_index = 0; tgt_index < tgt_len; ++tgt_index) {
++                              unsigned src_index = mapping[tgt_index];
++
++                              if (tgt_vec->entries[tgt_index].data == INF_COSTS)
++                                      continue;
++
++                              for (other_index = 0; other_index < other_len; ++other_index) {
++                                      if (other_vec->entries[other_index].data == INF_COSTS)
++                                              continue;
++
++                                      new_matrix->entries[tgt_index*other_len+other_index] = old_matrix->entries[other_index*src_len+src_index];
++                              }
++                      }
++              }
++              /* Source node selects the row of the old_matrix. */
++              else {
++                      for (tgt_index = 0; tgt_index < tgt_len; ++tgt_index) {
++                              unsigned src_index = mapping[tgt_index];
++
++                              if (tgt_vec->entries[tgt_index].data == INF_COSTS)
++                                      continue;
++
++                              for (other_index = 0; other_index < other_len; ++other_index) {
++                                      if (other_vec->entries[other_index].data == INF_COSTS)
++                                              continue;
++
++                                      new_matrix->entries[tgt_index*other_len+other_index] = old_matrix->entries[src_index*other_len+other_index];
++                              }
++                      }
++              }
++
++              new_edge = get_edge(pbqp, tgt_node->index, other_node->index);
++
++              add_edge_costs(pbqp, tgt_node->index, other_node->index, new_matrix);
++
++              if (new_edge == NULL) {
++                      reorder_node_after_edge_insertion(tgt_node);
++                      reorder_node_after_edge_insertion(other_node);
++              }
++
++              delete_edge(old_edge);
++
++              new_edge = get_edge(pbqp, tgt_node->index, other_node->index);
++              simplify_edge(pbqp, new_edge);
++
++              insert_into_rm_bucket(new_edge);
++      }
++
++#if KAPS_STATISTIC
++      pbqp->num_r1--;
++#endif
++}
++
++/**
++ * Tries to apply RM for the target node of the given edge.
++ *
++ * Checks whether the target node of edge can be merged into the source node of
++ * edge, and performs the merge, if possible.
++ */
++static void merge_target_into_source(pbqp_t *pbqp, pbqp_edge_t *edge)
++{
++      pbqp_matrix_t  *mat;
++      pbqp_node_t    *src_node;
++      pbqp_node_t    *tgt_node;
++      vector_t       *src_vec;
++      vector_t       *tgt_vec;
++      unsigned       *mapping;
++      unsigned        src_len;
++      unsigned        tgt_len;
++      unsigned        src_index;
++      unsigned        tgt_index;
++      unsigned        edge_index;
++      unsigned        edge_len;
++
++      assert(pbqp);
++      assert(edge);
++
++      src_node = edge->src;
++      tgt_node = edge->tgt;
++      assert(src_node);
++      assert(tgt_node);
++
++      src_vec = src_node->costs;
++      tgt_vec = tgt_node->costs;
++      assert(src_vec);
++      assert(tgt_vec);
++
++      src_len = src_vec->len;
++      tgt_len = tgt_vec->len;
++
++      /* Matrizes are normalized. */
++      assert(src_len > 1);
++      assert(tgt_len > 1);
++
++      mat = edge->costs;
++      assert(mat);
++
++      mapping = NEW_ARR_F(unsigned, src_len);
++
++      /* Check that each row has at most one zero entry. */
++      for (src_index = 0; src_index < src_len; ++src_index) {
++              unsigned onlyOneZero = 0;
++
++              if (src_vec->entries[src_index].data == INF_COSTS)
++                      continue;
++
++              for (tgt_index = 0; tgt_index < tgt_len; ++tgt_index) {
++                      if (tgt_vec->entries[tgt_index].data == INF_COSTS)
++                              continue;
++
++                      if (mat->entries[src_index * tgt_len + tgt_index] == INF_COSTS)
++                              continue;
++
++                      /* Matrix entry is finite. */
++                      if (onlyOneZero) {
++                              DEL_ARR_F(mapping);
++                              return;
++                      }
++
++                      onlyOneZero = 1;
++                      mapping[src_index] = tgt_index;
++              }
++      }
++
++      /* We know that we can merge the target node into the source node. */
++      edge_len = pbqp_node_get_degree(tgt_node);
++
++#if KAPS_STATISTIC
++      pbqp->num_rm++;
++#endif
++
++#if   KAPS_DUMP
++      if (pbqp->dump_file) {
++              char txt[100];
++              sprintf(txt, "Merging n%d into n%d", tgt_node->index, src_node->index);
++              dump_section(pbqp->dump_file, 3, txt);
++      }
++#endif
++
++      /* Reconnect the target's edges with the source node. */
++      for (edge_index = 0; edge_index < edge_len; ++edge_index) {
++              pbqp_edge_t   *old_edge = tgt_node->edges[edge_index];
++              pbqp_edge_t   *new_edge;
++              pbqp_matrix_t *old_matrix;
++              pbqp_matrix_t *new_matrix;
++              pbqp_node_t   *other_node;
++              vector_t      *other_vec;
++              unsigned       other_len;
++              unsigned       other_index;
++              unsigned       src_index;
++
++              assert(old_edge);
++
++              if (old_edge == edge)
++                      continue;
++
++              old_matrix = old_edge->costs;
++              assert(old_matrix);
++
++              if (old_edge->tgt == tgt_node) {
++                      other_node = old_edge->src;
++                      other_len  = old_matrix->rows;
++              }
++              else {
++                      other_node = old_edge->tgt;
++                      other_len = old_matrix->cols;
++              }
++              assert(other_node);
++              other_vec = other_node->costs;
++
++              new_matrix = pbqp_matrix_alloc(pbqp, src_len, other_len);
++
++              /* Target node selects the column of the old_matrix. */
++              if (old_edge->tgt == tgt_node) {
++                      for (src_index = 0; src_index < src_len; ++src_index) {
++                              unsigned tgt_index = mapping[src_index];
++
++                              if (src_vec->entries[src_index].data == INF_COSTS)
++                                      continue;
++
++                              for (other_index = 0; other_index < other_len; ++other_index) {
++                                      if (other_vec->entries[other_index].data == INF_COSTS)
++                                              continue;
++
++                                      new_matrix->entries[src_index*other_len+other_index] = old_matrix->entries[other_index*tgt_len+tgt_index];
++                              }
++                      }
++              }
++              /* Source node selects the row of the old_matrix. */
++              else {
++                      for (src_index = 0; src_index < src_len; ++src_index) {
++                              unsigned tgt_index = mapping[src_index];
++
++                              if (src_vec->entries[src_index].data == INF_COSTS)
++                                      continue;
++
++                              for (other_index = 0; other_index < other_len; ++other_index) {
++                                      if (other_vec->entries[other_index].data == INF_COSTS)
++                                              continue;
++
++                                      new_matrix->entries[src_index*other_len+other_index] = old_matrix->entries[tgt_index*other_len+other_index];
++                              }
++                      }
++              }
++
++              new_edge = get_edge(pbqp, src_node->index, other_node->index);
++
++              add_edge_costs(pbqp, src_node->index, other_node->index, new_matrix);
++
++              if (new_edge == NULL) {
++                      reorder_node_after_edge_insertion(src_node);
++                      reorder_node_after_edge_insertion(other_node);
++              }
++
++              delete_edge(old_edge);
++
++              new_edge = get_edge(pbqp, src_node->index, other_node->index);
++              simplify_edge(pbqp, new_edge);
++
++              insert_into_rm_bucket(new_edge);
++      }
++
++#if KAPS_STATISTIC
++      pbqp->num_r1--;
++#endif
++}
++
++/**
++ * Merge neighbors into the given node.
++ */
++void apply_RM(pbqp_t *pbqp, pbqp_node_t *node)
++{
++      pbqp_edge_t **edges;
++      unsigned      edge_index;
++      unsigned      edge_len;
++
++      assert(node);
++      assert(pbqp);
++
++      edges    = node->edges;
++      edge_len = pbqp_node_get_degree(node);
++
++      /* Check all incident edges. */
++      for (edge_index = 0; edge_index < edge_len; ++edge_index) {
++              pbqp_edge_t *edge = edges[edge_index];
++
++              insert_into_rm_bucket(edge);
++      }
++
++      /* ALAP: Merge neighbors into given node. */
++      while(edge_bucket_get_length(rm_bucket) > 0) {
++              pbqp_edge_t *edge = edge_bucket_pop(&rm_bucket);
++              assert(edge);
++
++              /* If the edge is not deleted: Try a merge. */
++              if (edge->src == node)
++                      merge_target_into_source(pbqp, edge);
++              else if (edge->tgt == node)
++                      merge_source_into_target(pbqp, edge);
++      }
++
++      merged_node = node;
++}
++
++void reorder_node_after_edge_deletion(pbqp_node_t *node)
++{
++      unsigned    degree     = pbqp_node_get_degree(node);
++      /* Assume node lost one incident edge. */
++      unsigned    old_degree = degree + 1;
++
++      if (!buckets_filled) return;
++
++      /* Same bucket as before */
++      if (degree > 2) return;
++
++      /* Delete node from old bucket... */
++      node_bucket_remove(&node_buckets[old_degree], node);
++
++      /* ..and add to new one. */
++      node_bucket_insert(&node_buckets[degree], node);
++}
++
++void reorder_node_after_edge_insertion(pbqp_node_t *node)
++{
++      unsigned    degree     = pbqp_node_get_degree(node);
++      /* Assume node lost one incident edge. */
++      unsigned    old_degree = degree - 1;
++
++      if (!buckets_filled) return;
++
++      /* Same bucket as before */
++      if (old_degree > 2) return;
++
++      /* Delete node from old bucket... */
++      node_bucket_remove(&node_buckets[old_degree], node);
++
++      /* ..and add to new one. */
++      node_bucket_insert(&node_buckets[degree], node);
++}
++
++void simplify_edge(pbqp_t *pbqp, pbqp_edge_t *edge)
++{
++      pbqp_matrix_t *mat;
++      pbqp_node_t   *src_node;
++      pbqp_node_t   *tgt_node;
++      vector_t      *src_vec;
++      vector_t      *tgt_vec;
++      int            src_len;
++      int            tgt_len;
++
++      assert(pbqp);
++      assert(edge);
++
++      (void) pbqp;
++
++      src_node = edge->src;
++      tgt_node = edge->tgt;
++      assert(src_node);
++      assert(tgt_node);
++
++      /* If edge are already deleted, we have nothing to do. */
++      if (is_deleted(edge))
++              return;
++
++#if   KAPS_DUMP
++      if (pbqp->dump_file) {
++              char txt[100];
++              sprintf(txt, "Simplification of Edge n%d-n%d", src_node->index, tgt_node->index);
++              dump_section(pbqp->dump_file, 3, txt);
++      }
++#endif
++
++      src_vec = src_node->costs;
++      tgt_vec = tgt_node->costs;
++      assert(src_vec);
++      assert(tgt_vec);
++
++      src_len = src_vec->len;
++      tgt_len = tgt_vec->len;
++      assert(src_len > 0);
++      assert(tgt_len > 0);
++
++      mat = edge->costs;
++      assert(mat);
++
++#if   KAPS_DUMP
++      if (pbqp->dump_file) {
++              fputs("Input:<br>\n", pbqp->dump_file);
++              dump_simplifyedge(pbqp, edge);
++      }
++#endif
++
++      normalize_towards_source(edge);
++      normalize_towards_target(edge);
++
++#if   KAPS_DUMP
++      if (pbqp->dump_file) {
++              fputs("<br>\nOutput:<br>\n", pbqp->dump_file);
++              dump_simplifyedge(pbqp, edge);
++      }
++#endif
++
++      if (pbqp_matrix_is_zero(mat, src_vec, tgt_vec)) {
++#if   KAPS_DUMP
++              if (pbqp->dump_file) {
++                      fputs("edge has been eliminated<br>\n", pbqp->dump_file);
++              }
++#endif
++
++#if KAPS_STATISTIC
++              pbqp->num_edges++;
++#endif
++
++              delete_edge(edge);
++      }
++}
++
++void initial_simplify_edges(pbqp_t *pbqp)
++{
++      unsigned node_index;
++      unsigned node_len;
++
++      assert(pbqp);
++
++      #if KAPS_TIMING
++              ir_timer_t *t_int_simpl = ir_timer_new();
++              ir_timer_start(t_int_simpl);
++      #endif
++
++#if   KAPS_DUMP
++      if (pbqp->dump_file) {
++              pbqp_dump_input(pbqp);
++              dump_section(pbqp->dump_file, 1, "2. Simplification of Cost Matrices");
++      }
++#endif
++
++      node_len = pbqp->num_nodes;
++
++      init_buckets();
++
++      /* First simplify all edges. */
++      for (node_index = 0; node_index < node_len; ++node_index) {
++              unsigned      edge_index;
++              pbqp_node_t  *node = get_node(pbqp, node_index);
++              pbqp_edge_t **edges;
++              unsigned      edge_len;
++
++              if (!node) continue;
++
++              edges = node->edges;
++              edge_len = pbqp_node_get_degree(node);
++
++              for (edge_index = 0; edge_index < edge_len; ++edge_index) {
++                      pbqp_edge_t *edge = edges[edge_index];
++
++                      /* Simplify only once per edge. */
++                      if (node != edge->src) continue;
++
++                      simplify_edge(pbqp, edge);
++              }
++      }
++
++      #if KAPS_TIMING
++              ir_timer_stop(t_int_simpl);
++              printf("PBQP Initial simplify edges:  %10.3lf msec\n", (double)ir_timer_elapsed_usec(t_int_simpl) / 1000.0);
++      #endif
++}
++
++num determine_solution(pbqp_t *pbqp)
++{
++      unsigned node_index;
++      unsigned node_len;
++      num      solution   = 0;
++
++      #if KAPS_TIMING
++              ir_timer_t *t_det_solution = ir_timer_new();
++              ir_timer_reset_and_start(t_det_solution);
++      #endif
++
++#if   KAPS_DUMP
++      FILE     *file;
++#endif
++
++      assert(pbqp);
++
++      (void) pbqp;
++
++#if   KAPS_DUMP
++      file = pbqp->dump_file;
++
++      if (file) {
++              dump_section(file, 1, "4. Determine Solution/Minimum");
++              dump_section(file, 2, "4.1. Trivial Solution");
++      }
++#endif
++
++      /* Solve trivial nodes and calculate solution. */
++      node_len = node_bucket_get_length(node_buckets[0]);
++
++#if KAPS_STATISTIC
++      pbqp->num_r0 = node_len;
++#endif
++
++      for (node_index = 0; node_index < node_len; ++node_index) {
++              pbqp_node_t *node = node_buckets[0][node_index];
++              assert(node);
++
++              node->solution = vector_get_min_index(node->costs);
++              solution       = pbqp_add(solution,
++                              node->costs->entries[node->solution].data);
++
++#if   KAPS_DUMP
++              if (file) {
++                      fprintf(file, "node n%d is set to %d<br>\n", node->index, node->solution);
++                      dump_node(file, node);
++              }
++#endif
++      }
++
++#if   KAPS_DUMP
++      if (file) {
++              dump_section(file, 2, "Minimum");
++#if KAPS_USE_UNSIGNED
++              fprintf(file, "Minimum is equal to %u.", solution);
++#else
++              fprintf(file, "Minimum is equal to %lld.", solution);
++#endif
++      }
++#endif
++
++      #if KAPS_TIMING
++              ir_timer_stop(t_det_solution);
++              printf("PBQP Determine Solution:      %10.3lf msec\n", (double)ir_timer_elapsed_usec(t_det_solution) / 1000.0);
++      #endif
++
++      return solution;
++}
++
++static void back_propagate_RI(pbqp_t *pbqp, pbqp_node_t *node)
++{
++      pbqp_edge_t   *edge;
++      pbqp_node_t   *other;
++      pbqp_matrix_t *mat;
++      vector_t      *vec;
++      int            is_src;
++
++      assert(pbqp);
++      assert(node);
++
++      (void) pbqp;
++
++      edge = node->edges[0];
++      mat = edge->costs;
++      is_src = edge->src == node;
++      vec = node->costs;
++
++      if (is_src) {
++              other = edge->tgt;
++              assert(other);
++
++              node->solution = pbqp_matrix_get_col_min_index(mat, other->solution, vec);
++      } else {
++              other = edge->src;
++              assert(other);
++
++              node->solution = pbqp_matrix_get_row_min_index(mat, other->solution, vec);
++      }
++
++#if   KAPS_DUMP
++      if (pbqp->dump_file) {
++              fprintf(pbqp->dump_file, "node n%d is set to %d<br>\n", node->index, node->solution);
++      }
++#endif
++}
++
++static void back_propagate_RII(pbqp_t *pbqp, pbqp_node_t *node)
++{
++      pbqp_edge_t   *src_edge   = node->edges[0];
++      pbqp_edge_t   *tgt_edge   = node->edges[1];
++      int            src_is_src = src_edge->src == node;
++      int            tgt_is_src = tgt_edge->src == node;
++      pbqp_matrix_t *src_mat;
++      pbqp_matrix_t *tgt_mat;
++      pbqp_node_t   *src_node;
++      pbqp_node_t   *tgt_node;
++      vector_t      *vec;
++      vector_t      *node_vec;
++      unsigned       col_index;
++      unsigned       row_index;
++
++      assert(pbqp);
++
++      if (src_is_src) {
++              src_node = src_edge->tgt;
++      } else {
++              src_node = src_edge->src;
++      }
++
++      if (tgt_is_src) {
++              tgt_node = tgt_edge->tgt;
++      } else {
++              tgt_node = tgt_edge->src;
++      }
++
++      /* Swap nodes if necessary. */
++      if (tgt_node->index < src_node->index) {
++              pbqp_node_t *tmp_node;
++              pbqp_edge_t *tmp_edge;
++
++              tmp_node = src_node;
++              src_node = tgt_node;
++              tgt_node = tmp_node;
++
++              tmp_edge = src_edge;
++              src_edge = tgt_edge;
++              tgt_edge = tmp_edge;
++
++              src_is_src = src_edge->src == node;
++              tgt_is_src = tgt_edge->src == node;
++      }
++
++      src_mat = src_edge->costs;
++      tgt_mat = tgt_edge->costs;
++
++      node_vec = node->costs;
++
++      row_index = src_node->solution;
++      col_index = tgt_node->solution;
++
++      vec = vector_copy(pbqp, node_vec);
++
++      if (src_is_src) {
++              vector_add_matrix_col(vec, src_mat, row_index);
++      } else {
++              vector_add_matrix_row(vec, src_mat, row_index);
++      }
++
++      if (tgt_is_src) {
++              vector_add_matrix_col(vec, tgt_mat, col_index);
++      } else {
++              vector_add_matrix_row(vec, tgt_mat, col_index);
++      }
++
++      node->solution = vector_get_min_index(vec);
++
++#if   KAPS_DUMP
++      if (pbqp->dump_file) {
++              fprintf(pbqp->dump_file, "node n%d is set to %d<br>\n", node->index, node->solution);
++      }
++#endif
++
++      obstack_free(&pbqp->obstack, vec);
++}
++
++void back_propagate(pbqp_t *pbqp)
++{
++      unsigned node_index;
++      unsigned node_len   = node_bucket_get_length(reduced_bucket);
++
++      assert(pbqp);
++
++#if   KAPS_DUMP
++      if (pbqp->dump_file) {
++              dump_section(pbqp->dump_file, 2, "Back Propagation");
++      }
++#endif
++
++      for (node_index = node_len; node_index > 0; --node_index) {
++              pbqp_node_t *node = reduced_bucket[node_index - 1];
++
++              switch (pbqp_node_get_degree(node)) {
++                      case 1:
++                              back_propagate_RI(pbqp, node);
++                              break;
++                      case 2:
++                              back_propagate_RII(pbqp, node);
++                              break;
++                      default:
++                              panic("Only nodes with degree one or two should be in this bucket");
++                              break;
++              }
++      }
++}
++
++void apply_edge(pbqp_t *pbqp)
++{
++      pbqp_edge_t *edge = edge_bucket_pop(&edge_bucket);
++
++      simplify_edge(pbqp, edge);
++}
++
++void apply_RI(pbqp_t *pbqp)
++{
++      pbqp_node_t   *node   = node_bucket_pop(&node_buckets[1]);
++      pbqp_edge_t   *edge   = node->edges[0];
++      pbqp_matrix_t *mat    = edge->costs;
++      int            is_src = edge->src == node;
++      pbqp_node_t   *other_node;
++
++      (void ) pbqp;
++      assert(pbqp_node_get_degree(node) == 1);
++
++      if (is_src) {
++              other_node = edge->tgt;
++      } else {
++              other_node = edge->src;
++      }
++
++#if   KAPS_DUMP
++      if (pbqp->dump_file) {
++              char     txt[100];
++              sprintf(txt, "RI-Reduction of Node n%d", node->index);
++              dump_section(pbqp->dump_file, 2, txt);
++              pbqp_dump_graph(pbqp);
++              fputs("<br>\nBefore reduction:<br>\n", pbqp->dump_file);
++              dump_node(pbqp->dump_file, node);
++              dump_node(pbqp->dump_file, other_node);
++              dump_edge(pbqp->dump_file, edge);
++      }
++#endif
++
++      if (is_src) {
++              pbqp_matrix_add_to_all_cols(mat, node->costs);
++              normalize_towards_target(edge);
++      } else {
++              pbqp_matrix_add_to_all_rows(mat, node->costs);
++              normalize_towards_source(edge);
++      }
++      disconnect_edge(other_node, edge);
++
++#if   KAPS_DUMP
++      if (pbqp->dump_file) {
++              fputs("<br>\nAfter reduction:<br>\n", pbqp->dump_file);
++              dump_node(pbqp->dump_file, other_node);
++      }
++#endif
++
++      reorder_node_after_edge_deletion(other_node);
++
++#if KAPS_STATISTIC
++      pbqp->num_r1++;
++#endif
++
++      /* Add node to back propagation list. */
++      node_bucket_insert(&reduced_bucket, node);
++}
++
++void apply_RII(pbqp_t *pbqp)
++{
++      pbqp_node_t   *node       = node_bucket_pop(&node_buckets[2]);
++      pbqp_edge_t   *src_edge   = node->edges[0];
++      pbqp_edge_t   *tgt_edge   = node->edges[1];
++      int            src_is_src = src_edge->src == node;
++      int            tgt_is_src = tgt_edge->src == node;
++      pbqp_matrix_t *src_mat;
++      pbqp_matrix_t *tgt_mat;
++      pbqp_node_t   *src_node;
++      pbqp_node_t   *tgt_node;
++      pbqp_matrix_t *mat;
++      vector_t      *vec;
++      vector_t      *node_vec;
++      vector_t      *src_vec;
++      vector_t      *tgt_vec;
++      unsigned       col_index;
++      unsigned       col_len;
++      unsigned       row_index;
++      unsigned       row_len;
++      unsigned       node_len;
++
++      assert(pbqp);
++      assert(pbqp_node_get_degree(node) == 2);
++
++      if (src_is_src) {
++              src_node = src_edge->tgt;
++      } else {
++              src_node = src_edge->src;
++      }
++
++      if (tgt_is_src) {
++              tgt_node = tgt_edge->tgt;
++      } else {
++              tgt_node = tgt_edge->src;
++      }
++
++      /* Swap nodes if necessary. */
++      if (tgt_node->index < src_node->index) {
++              pbqp_node_t *tmp_node;
++              pbqp_edge_t *tmp_edge;
++
++              tmp_node = src_node;
++              src_node = tgt_node;
++              tgt_node = tmp_node;
++
++              tmp_edge = src_edge;
++              src_edge = tgt_edge;
++              tgt_edge = tmp_edge;
++
++              src_is_src = src_edge->src == node;
++              tgt_is_src = tgt_edge->src == node;
++      }
++
++#if   KAPS_DUMP
++      if (pbqp->dump_file) {
++              char     txt[100];
++              sprintf(txt, "RII-Reduction of Node n%d", node->index);
++              dump_section(pbqp->dump_file, 2, txt);
++              pbqp_dump_graph(pbqp);
++              fputs("<br>\nBefore reduction:<br>\n", pbqp->dump_file);
++              dump_node(pbqp->dump_file, src_node);
++              dump_edge(pbqp->dump_file, src_edge);
++              dump_node(pbqp->dump_file, node);
++              dump_edge(pbqp->dump_file, tgt_edge);
++              dump_node(pbqp->dump_file, tgt_node);
++      }
++#endif
++
++      src_mat = src_edge->costs;
++      tgt_mat = tgt_edge->costs;
++
++      src_vec  = src_node->costs;
++      tgt_vec  = tgt_node->costs;
++      node_vec = node->costs;
++
++      row_len  = src_vec->len;
++      col_len  = tgt_vec->len;
++      node_len = node_vec->len;
++
++      mat = pbqp_matrix_alloc(pbqp, row_len, col_len);
++
++      for (row_index = 0; row_index < row_len; ++row_index) {
++              for (col_index = 0; col_index < col_len; ++col_index) {
++                      vec = vector_copy(pbqp, node_vec);
++
++                      if (src_is_src) {
++                              vector_add_matrix_col(vec, src_mat, row_index);
++                      } else {
++                              vector_add_matrix_row(vec, src_mat, row_index);
++                      }
++
++                      if (tgt_is_src) {
++                              vector_add_matrix_col(vec, tgt_mat, col_index);
++                      } else {
++                              vector_add_matrix_row(vec, tgt_mat, col_index);
++                      }
++
++                      mat->entries[row_index * col_len + col_index] = vector_get_min(vec);
++
++                      obstack_free(&pbqp->obstack, vec);
++              }
++      }
++
++      pbqp_edge_t *edge = get_edge(pbqp, src_node->index, tgt_node->index);
++
++      /* Disconnect node. */
++      disconnect_edge(src_node, src_edge);
++      disconnect_edge(tgt_node, tgt_edge);
++
++#if KAPS_STATISTIC
++      pbqp->num_r2++;
++#endif
++
++      /* Add node to back propagation list. */
++      node_bucket_insert(&reduced_bucket, node);
++
++      if (edge == NULL) {
++              edge = alloc_edge(pbqp, src_node->index, tgt_node->index, mat);
++      } else {
++              // matrix
++              pbqp_matrix_add(edge->costs, mat);
++
++              /* Free local matrix. */
++              obstack_free(&pbqp->obstack, mat);
++
++              reorder_node_after_edge_deletion(src_node);
++              reorder_node_after_edge_deletion(tgt_node);
++      }
++
++#if   KAPS_DUMP
++      if (pbqp->dump_file) {
++              fputs("<br>\nAfter reduction:<br>\n", pbqp->dump_file);
++              dump_edge(pbqp->dump_file, edge);
++      }
++#endif
++
++      /* Edge has changed so we simplify it. */
++      simplify_edge(pbqp, edge);
++}
++
++static void select_column(pbqp_edge_t *edge, unsigned col_index)
++{
++      pbqp_matrix_t  *mat;
++      pbqp_node_t    *src_node;
++      pbqp_node_t    *tgt_node;
++      vector_t       *src_vec;
++      vector_t       *tgt_vec;
++      unsigned        src_len;
++      unsigned        tgt_len;
++      unsigned        src_index;
++      unsigned        new_infinity = 0;
++
++      assert(edge);
++
++      src_node = edge->src;
++      tgt_node = edge->tgt;
++      assert(src_node);
++      assert(tgt_node);
++
++      src_vec = src_node->costs;
++      tgt_vec = tgt_node->costs;
++      assert(src_vec);
++      assert(tgt_vec);
++
++      src_len = src_vec->len;
++      tgt_len = tgt_vec->len;
++      assert(src_len > 0);
++      assert(tgt_len > 0);
++
++      mat = edge->costs;
++      assert(mat);
++
++      for (src_index = 0; src_index < src_len; ++src_index) {
++              num elem = mat->entries[src_index * tgt_len + col_index];
++
++              if (elem != 0) {
++                      if (elem == INF_COSTS && src_vec->entries[src_index].data != INF_COSTS)
++                              new_infinity = 1;
++
++                      src_vec->entries[src_index].data = pbqp_add(
++                                      src_vec->entries[src_index].data, elem);
++              }
++      }
++
++      if (new_infinity) {
++              unsigned edge_index;
++              unsigned edge_len = pbqp_node_get_degree(src_node);
++
++              for (edge_index = 0; edge_index < edge_len; ++edge_index) {
++                      pbqp_edge_t *edge_candidate = src_node->edges[edge_index];
++
++                      if (edge_candidate != edge) {
++                              insert_into_edge_bucket(edge_candidate);
++                      }
++              }
++      }
++
++      delete_edge(edge);
++}
++
++static void select_row(pbqp_edge_t *edge, unsigned row_index)
++{
++      pbqp_matrix_t  *mat;
++      pbqp_node_t    *src_node;
++      pbqp_node_t    *tgt_node;
++      vector_t       *tgt_vec;
++      unsigned        tgt_len;
++      unsigned        tgt_index;
++      unsigned        new_infinity = 0;
++
++      assert(edge);
++
++      src_node = edge->src;
++      tgt_node = edge->tgt;
++      assert(tgt_node);
++
++      tgt_vec = tgt_node->costs;
++      assert(tgt_vec);
++
++      tgt_len = tgt_vec->len;
++      assert(tgt_len > 0);
++
++      mat = edge->costs;
++      assert(mat);
++
++      for (tgt_index = 0; tgt_index < tgt_len; ++tgt_index) {
++              num elem = mat->entries[row_index * tgt_len + tgt_index];
++
++              if (elem != 0) {
++                      if (elem == INF_COSTS && tgt_vec->entries[tgt_index].data != INF_COSTS)
++                              new_infinity = 1;
++
++                      tgt_vec->entries[tgt_index].data = pbqp_add(
++                                      tgt_vec->entries[tgt_index].data, elem);
++              }
++      }
++
++      if (new_infinity) {
++              unsigned edge_index;
++              unsigned edge_len = pbqp_node_get_degree(tgt_node);
++
++              for (edge_index = 0; edge_index < edge_len; ++edge_index) {
++                      pbqp_edge_t *edge_candidate = tgt_node->edges[edge_index];
++
++                      if (edge_candidate != edge) {
++                              insert_into_edge_bucket(edge_candidate);
++                      }
++              }
++      }
++
++      delete_edge(edge);
++}
++
++void select_alternative(pbqp_node_t *node, unsigned selected_index)
++{
++      unsigned  edge_index;
++      unsigned  node_index;
++      unsigned  node_len;
++      vector_t *node_vec;
++      unsigned  max_degree = pbqp_node_get_degree(node);
++
++      assert(node);
++      node->solution = selected_index;
++      node_vec = node->costs;
++      node_len = node_vec->len;
++      assert(selected_index < node_len);
++
++      /* Set all other costs to infinity. */
++      for (node_index = 0; node_index < node_len; ++node_index) {
++              if (node_index != selected_index) {
++                      node_vec->entries[node_index].data = INF_COSTS;
++              }
++      }
++
++      /* Select corresponding row/column for incident edges. */
++      for (edge_index = 0; edge_index < max_degree; ++edge_index) {
++              pbqp_edge_t *edge = node->edges[edge_index];
++
++              if (edge->src == node)
++                      select_row(edge, selected_index);
++              else
++                      select_column(edge, selected_index);
++      }
++}
++
++pbqp_node_t *get_node_with_max_degree(void)
++{
++      pbqp_node_t **bucket       = node_buckets[3];
++      unsigned      bucket_len   = node_bucket_get_length(bucket);
++      unsigned      bucket_index;
++      unsigned      max_degree   = 0;
++      pbqp_node_t  *result       = NULL;
++
++      for (bucket_index = 0; bucket_index < bucket_len; ++bucket_index) {
++              pbqp_node_t *candidate = bucket[bucket_index];
++              unsigned     degree    = pbqp_node_get_degree(candidate);
++
++              if (degree > max_degree) {
++                      result = candidate;
++                      max_degree = degree;
++              }
++      }
++
++      return result;
++}
++
++unsigned get_local_minimal_alternative(pbqp_t *pbqp, pbqp_node_t *node)
++{
++      pbqp_edge_t   *edge;
++      vector_t      *node_vec;
++      vector_t      *vec;
++      pbqp_matrix_t *mat;
++      unsigned       edge_index;
++      unsigned       max_degree;
++      unsigned       node_index;
++      unsigned       node_len;
++      unsigned       min_index    = 0;
++      num            min          = INF_COSTS;
++      int            is_src;
++
++      assert(pbqp);
++      assert(node);
++      node_vec   = node->costs;
++      node_len   = node_vec->len;
++      max_degree = pbqp_node_get_degree(node);
++
++      for (node_index = 0; node_index < node_len; ++node_index) {
++              num value = node_vec->entries[node_index].data;
++
++              for (edge_index = 0; edge_index < max_degree; ++edge_index) {
++                      edge   = node->edges[edge_index];
++                      mat    = edge->costs;
++                      is_src = edge->src == node;
++
++                      if (is_src) {
++                              vec = vector_copy(pbqp, edge->tgt->costs);
++                              vector_add_matrix_row(vec, mat, node_index);
++                      } else {
++                              vec = vector_copy(pbqp, edge->src->costs);
++                              vector_add_matrix_col(vec, mat, node_index);
++                      }
++
++                      value = pbqp_add(value, vector_get_min(vec));
++
++                      obstack_free(&pbqp->obstack, vec);
++              }
++
++              if (value < min) {
++                      min = value;
++                      min_index = node_index;
++              }
++      }
++
++      return min_index;
++}
++
++int node_is_reduced(pbqp_node_t *node)
++{
++      if (!reduced_bucket) return 0;
++
++      if (pbqp_node_get_degree(node) == 0) return 1;
++
++      return node_bucket_contains(reduced_bucket, node);
++}
index 0000000,0000000..ec7b026
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,57 @@@
++/*
++ * Copyright (C) 1995-2008 University of Karlsruhe.  All right reserved.
++ *
++ * This file is part of libFirm.
++ *
++ * This file may be distributed and/or modified under the terms of the
++ * GNU General Public License version 2 as published by the Free Software
++ * Foundation and appearing in the file LICENSE.GPL included in the
++ * packaging of this file.
++ *
++ * Licensees holding valid libFirm Professional Edition licenses may use
++ * this file in accordance with the libFirm Commercial License.
++ * Agreement provided with the Software.
++ *
++ * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
++ * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
++ * PURPOSE.
++ */
++
++/**
++ * @file
++ * @brief   Heuristic PBQP solver.
++ * @date    28.12.2009
++ * @author  Sebastian Buchwald
++ * @version $Id$
++ */
++#ifndef KAPS_OPTIMAL_H
++#define KAPS_OPTIMAL_H
++
++#include "pbqp_t.h"
++
++extern pbqp_edge_t **edge_bucket;
++extern pbqp_node_t **node_buckets[4];
++extern pbqp_node_t **reduced_bucket;
++extern pbqp_node_t  *merged_node;
++
++void apply_edge(pbqp_t *pbqp);
++
++void apply_RI(pbqp_t *pbqp);
++void apply_RII(pbqp_t *pbqp);
++void apply_RM(pbqp_t *pbqp, pbqp_node_t *node);
++
++void back_propagate(pbqp_t *pbqp);
++num determine_solution(pbqp_t *pbqp);
++void fill_node_buckets(pbqp_t *pbqp);
++void free_buckets(void);
++unsigned get_local_minimal_alternative(pbqp_t *pbqp, pbqp_node_t *node);
++pbqp_node_t *get_node_with_max_degree(void);
++void initial_simplify_edges(pbqp_t *pbqp);
++void select_alternative(pbqp_node_t *node, unsigned selected_index);
++void simplify_edge(pbqp_t *pbqp, pbqp_edge_t *edge);
++void reorder_node_after_edge_deletion(pbqp_node_t *node);
++void reorder_node_after_edge_insertion(pbqp_node_t *node);
++
++int node_is_reduced(pbqp_node_t *node);
++
++#endif /* KAPS_OPTIMAL_H */
index 0000000,0000000..8a1d0c4
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,130 @@@
++/*
++ * Copyright (C) 1995-2008 University of Karlsruhe.  All right reserved.
++ *
++ * This file is part of libFirm.
++ *
++ * This file may be distributed and/or modified under the terms of the
++ * GNU General Public License version 2 as published by the Free Software
++ * Foundation and appearing in the file LICENSE.GPL included in the
++ * packaging of this file.
++ *
++ * Licensees holding valid libFirm Professional Edition licenses may use
++ * this file in accordance with the libFirm Commercial License.
++ * Agreement provided with the Software.
++ *
++ * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
++ * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
++ * PURPOSE.
++ */
++
++/**
++ * @file
++ * @brief   PBQP edges.
++ * @date    02.10.2008
++ * @author  Sebastian Buchwald
++ * @version $Id$
++ */
++#include "config.h"
++
++#include "adt/array.h"
++#include "assert.h"
++
++#include "kaps.h"
++#include "matrix.h"
++#include "optimal.h"
++#include "pbqp_edge.h"
++#include "pbqp_edge_t.h"
++#include "pbqp_node.h"
++#include "pbqp_node_t.h"
++#include "pbqp_t.h"
++
++pbqp_edge_t *alloc_edge(pbqp_t *pbqp, int src_index, int tgt_index,
++                        pbqp_matrix_t *costs)
++{
++      int transpose = 0;
++
++      if (tgt_index < src_index) {
++              int tmp = src_index;
++              src_index = tgt_index;
++              tgt_index = tmp;
++
++              transpose = 1;
++      }
++
++      pbqp_edge_t *edge = OALLOC(&pbqp->obstack, pbqp_edge_t);
++      assert(edge);
++
++      pbqp_node_t *src_node = get_node(pbqp, src_index);
++      assert(src_node);
++
++      pbqp_node_t *tgt_node = get_node(pbqp, tgt_index);
++      assert(tgt_node);
++
++      if (transpose) {
++              edge->costs = pbqp_matrix_copy_and_transpose(pbqp, costs);
++      } else {
++              edge->costs = pbqp_matrix_copy(pbqp, costs);
++      }
++
++      /*
++       * Connect edge with incident nodes. Since the edge is allocated, we know
++       * that it don't appear in the edge lists of the nodes.
++       */
++      ARR_APP1(pbqp_edge_t *, src_node->edges, edge);
++      edge->src = src_node;
++      ARR_APP1(pbqp_edge_t *, tgt_node->edges, edge);
++      edge->tgt = tgt_node;
++      edge->bucket_index = UINT_MAX;
++
++      return edge;
++}
++
++void delete_edge(pbqp_edge_t *edge)
++{
++      pbqp_node_t  *src_node;
++      pbqp_node_t  *tgt_node;
++
++      assert(edge);
++
++      src_node = edge->src;
++      tgt_node = edge->tgt;
++      assert(src_node);
++      assert(tgt_node);
++
++      disconnect_edge(src_node, edge);
++      disconnect_edge(tgt_node, edge);
++
++      edge->src = NULL;
++      edge->tgt = NULL;
++
++      reorder_node_after_edge_deletion(src_node);
++      reorder_node_after_edge_deletion(tgt_node);
++}
++
++unsigned is_deleted(pbqp_edge_t *edge)
++{
++      unsigned deleted;
++
++      assert(edge);
++
++      deleted = (edge->src == NULL) && (edge-> tgt == NULL);
++
++      return deleted;
++}
++
++pbqp_edge_t *pbqp_edge_deep_copy(pbqp_t *pbqp, pbqp_edge_t *edge,
++                                 pbqp_node_t *src_node, pbqp_node_t *tgt_node)
++{
++      pbqp_edge_t *copy = OALLOC(&pbqp->obstack, pbqp_edge_t);
++      assert(src_node);
++      assert(tgt_node);
++
++      copy->costs = pbqp_matrix_copy(pbqp, edge->costs);
++
++      /* Connect edge with incident nodes. */
++      copy->src = src_node;
++      copy->tgt = tgt_node;
++      copy->bucket_index = UINT_MAX;
++
++      return copy;
++}
index 0000000,0000000..1e649a2
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,41 @@@
++/*
++ * Copyright (C) 1995-2008 University of Karlsruhe.  All right reserved.
++ *
++ * This file is part of libFirm.
++ *
++ * This file may be distributed and/or modified under the terms of the
++ * GNU General Public License version 2 as published by the Free Software
++ * Foundation and appearing in the file LICENSE.GPL included in the
++ * packaging of this file.
++ *
++ * Licensees holding valid libFirm Professional Edition licenses may use
++ * this file in accordance with the libFirm Commercial License.
++ * Agreement provided with the Software.
++ *
++ * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
++ * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
++ * PURPOSE.
++ */
++
++/**
++ * @file
++ * @brief   PBQP edges.
++ * @date    02.10.2008
++ * @author  Sebastian Buchwald
++ * @version $Id$
++ */
++#ifndef KAPS_PBQP_EDGE_H
++#define KAPS_PBQP_EDGE_H
++
++#include "pbqp_t.h"
++
++pbqp_edge_t *alloc_edge(pbqp_t *pbqp, int src_index, int tgt_index,
++                        pbqp_matrix_t *costs);
++
++pbqp_edge_t *pbqp_edge_deep_copy(pbqp_t *pbqp, pbqp_edge_t *edge,
++                                 pbqp_node_t *src_node, pbqp_node_t *tgt_node);
++
++void delete_edge(pbqp_edge_t *edge);
++unsigned is_deleted(pbqp_edge_t *edge);
++
++#endif /* KAPS_PBQP_EDGE_H */
index 0000000,0000000..02f0248
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,39 @@@
++/*
++ * Copyright (C) 1995-2008 University of Karlsruhe.  All right reserved.
++ *
++ * This file is part of libFirm.
++ *
++ * This file may be distributed and/or modified under the terms of the
++ * GNU General Public License version 2 as published by the Free Software
++ * Foundation and appearing in the file LICENSE.GPL included in the
++ * packaging of this file.
++ *
++ * Licensees holding valid libFirm Professional Edition licenses may use
++ * this file in accordance with the libFirm Commercial License.
++ * Agreement provided with the Software.
++ *
++ * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
++ * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
++ * PURPOSE.
++ */
++
++/**
++ * @file
++ * @brief   PBQP edge data types.
++ * @date    02.10.2008
++ * @author  Sebastian Buchwald
++ * @version $Id$
++ */
++#ifndef KAPS_PBQP_EDGE_T_H
++#define KAPS_PBQP_EDGE_T_H
++
++#include "pbqp_t.h"
++
++struct pbqp_edge_t {
++      pbqp_node_t   *src;                  /* Source index. */
++      pbqp_node_t   *tgt;                  /* Target index. */
++      pbqp_matrix_t *costs;                /* Cost matrix. */
++      unsigned       bucket_index;         /* Index of edge bucket. */
++};
++
++#endif /* KAPS_PBQP_EDGE_T_H */
index 0000000,0000000..bb8a352
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,165 @@@
++/*
++ * Copyright (C) 1995-2008 University of Karlsruhe.  All right reserved.
++ *
++ * This file is part of libFirm.
++ *
++ * This file may be distributed and/or modified under the terms of the
++ * GNU General Public License version 2 as published by the Free Software
++ * Foundation and appearing in the file LICENSE.GPL included in the
++ * packaging of this file.
++ *
++ * Licensees holding valid libFirm Professional Edition licenses may use
++ * this file in accordance with the libFirm Commercial License.
++ * Agreement provided with the Software.
++ *
++ * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
++ * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
++ * PURPOSE.
++ */
++
++/**
++ * @file
++ * @brief   PBQP nodes.
++ * @date    02.10.2008
++ * @author  Sebastian Buchwald
++ * @version $Id$
++ */
++#include "config.h"
++
++#include "adt/array.h"
++
++#include "assert.h"
++
++#include "bucket.h"
++#include "pbqp_edge.h"
++#include "pbqp_edge_t.h"
++#include "pbqp_node.h"
++#include "pbqp_node_t.h"
++#include "vector.h"
++
++pbqp_node_t *alloc_node(pbqp_t *pbqp, unsigned node_index, vector_t *costs)
++{
++      pbqp_node_t *node = OALLOC(&pbqp->obstack, pbqp_node_t);
++      assert(node);
++
++      node->edges = NEW_ARR_F(pbqp_edge_t *, 0);
++      node->costs = vector_copy(pbqp, costs);
++      node->bucket_index = UINT_MAX;
++      node->solution = UINT_MAX;
++      node->index = node_index;
++
++      return node;
++}
++
++int is_connected(pbqp_node_t *node, pbqp_edge_t *edge)
++{
++      pbqp_edge_t **edges;
++      unsigned      edge_index;
++      unsigned      edge_len;
++
++      assert(node);
++      assert(edge);
++
++      if (edge->src != node && edge->tgt != node) return 0;
++
++      edges = node->edges;
++      edge_len = ARR_LEN(edges);
++
++      for (edge_index = 0; edge_index < edge_len; ++edge_index) {
++              pbqp_edge_t *edge_candidate = edges[edge_index];
++              if (edge_candidate == edge) {
++                      return 1;
++              }
++      }
++
++      return 0;
++}
++
++void disconnect_edge(pbqp_node_t *node, pbqp_edge_t *edge)
++{
++      pbqp_edge_t **edges;
++      unsigned      edge_index;
++      unsigned      edge_len;
++
++      edges = node->edges;
++      edge_len = ARR_LEN(edges);
++
++      for (edge_index = 0; edge_index < edge_len; ++edge_index) {
++              pbqp_edge_t *edge_candidate = edges[edge_index];
++              if (edge_candidate == edge) {
++                      edges[edge_index] = edges[edge_len - 1];
++                      ARR_SHRINKLEN(edges, (int)edge_len - 1);
++                      break;
++              }
++      }
++}
++
++unsigned pbqp_node_get_degree(pbqp_node_t *node)
++{
++      assert(node);
++      return ARR_LEN(node->edges);
++}
++
++pbqp_node_t *pbqp_node_deep_copy(pbqp_t *pbqp, pbqp_node_bucket_t new_bucket,
++                                 pbqp_node_t *node)
++{
++      unsigned     edge_index;
++      unsigned     edge_length = pbqp_node_get_degree(node);
++      pbqp_node_t *copy        = OALLOC(&pbqp->obstack, pbqp_node_t);
++
++      assert(copy);
++
++      copy->edges        = NEW_ARR_F(pbqp_edge_t *, 0);
++      for (edge_index = 0; edge_index < edge_length; ++edge_index) {
++              pbqp_edge_t *edge_copy = NULL;
++              pbqp_edge_t *edge      = node->edges[edge_index];
++              int          is_src    = edge->src == node;
++
++              if (is_src) {
++                      unsigned other_index = edge->tgt->bucket_index;
++                      unsigned is_copied   = other_index < node->bucket_index;
++
++                      if (is_copied) {
++                              pbqp_node_t *other_copy = new_bucket[other_index];
++                              unsigned     degree     = pbqp_node_get_degree(other_copy);
++                              unsigned     index;
++
++                              for (index = 0; index < degree; ++index) {
++                                      if (other_copy->edges[index]->src == node) {
++                                              edge_copy      = other_copy->edges[index];
++                                              edge_copy->src = copy;
++                                              break;
++                                      }
++                              }
++                      } else {
++                              edge_copy = pbqp_edge_deep_copy(pbqp, edge, copy, edge->tgt);
++                      }
++              } else {
++                      unsigned other_index = edge->src->bucket_index;
++                      unsigned is_copied   = other_index < node->bucket_index;
++
++                      if (is_copied) {
++                              pbqp_node_t *other_copy = new_bucket[other_index];
++                              unsigned     degree     = pbqp_node_get_degree(other_copy);
++                              unsigned     index;
++
++                              for (index = 0; index < degree; ++index) {
++                                      if (other_copy->edges[index]->tgt == node) {
++                                              edge_copy      = other_copy->edges[index];
++                                              edge_copy->tgt = copy;
++                                              break;
++                                      }
++                              }
++                      } else {
++                              edge_copy = pbqp_edge_deep_copy(pbqp, edge, edge->src, copy);
++                      }
++              }
++              ARR_APP1(pbqp_edge_t *, copy->edges, edge_copy);
++      }
++      copy->costs        = vector_copy(pbqp, node->costs);
++      copy->bucket_index = node->bucket_index;
++      copy->solution     = node->solution;
++      copy->index   = node->index;
++
++      return copy;
++}
index 0000000,0000000..a543907
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,44 @@@
++/*
++ * Copyright (C) 1995-2008 University of Karlsruhe.  All right reserved.
++ *
++ * This file is part of libFirm.
++ *
++ * This file may be distributed and/or modified under the terms of the
++ * GNU General Public License version 2 as published by the Free Software
++ * Foundation and appearing in the file LICENSE.GPL included in the
++ * packaging of this file.
++ *
++ * Licensees holding valid libFirm Professional Edition licenses may use
++ * this file in accordance with the libFirm Commercial License.
++ * Agreement provided with the Software.
++ *
++ * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
++ * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
++ * PURPOSE.
++ */
++
++/**
++ * @file
++ * @brief   PBQP nodes.
++ * @date    02.10.2008
++ * @author  Sebastian Buchwald
++ * @version $Id$
++ */
++#ifndef KAPS_PBQP_NODE_H
++#define KAPS_PBQP_NODE_H
++
++#include "bucket_t.h"
++#include "pbqp_t.h"
++
++pbqp_node_t *alloc_node(pbqp_t *pbqp, unsigned node_index, vector_t *costs);
++
++void disconnect_edge(pbqp_node_t *node, pbqp_edge_t *edge);
++
++int is_connected(pbqp_node_t *node, pbqp_edge_t *edge);
++
++unsigned pbqp_node_get_degree(pbqp_node_t *node);
++
++pbqp_node_t *pbqp_node_deep_copy(pbqp_t *pbqp, pbqp_node_bucket_t new_bucket,
++                                 pbqp_node_t *node);
++
++#endif /* KAPS_PBQP_NODE_H */
index 0000000,0000000..4cd06fa
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,40 @@@
++/*
++ * Copyright (C) 1995-2008 University of Karlsruhe.  All right reserved.
++ *
++ * This file is part of libFirm.
++ *
++ * This file may be distributed and/or modified under the terms of the
++ * GNU General Public License version 2 as published by the Free Software
++ * Foundation and appearing in the file LICENSE.GPL included in the
++ * packaging of this file.
++ *
++ * Licensees holding valid libFirm Professional Edition licenses may use
++ * this file in accordance with the libFirm Commercial License.
++ * Agreement provided with the Software.
++ *
++ * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
++ * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
++ * PURPOSE.
++ */
++
++/**
++ * @file
++ * @brief   PBQP node data types.
++ * @date    02.10.2008
++ * @author  Sebastian Buchwald
++ * @version $Id$
++ */
++#ifndef KAPS_PBQP_NODE_T_H
++#define KAPS_PBQP_NODE_T_H
++
++#include "pbqp_t.h"
++
++struct pbqp_node_t {
++      pbqp_edge_t **edges;
++      vector_t     *costs;
++      unsigned      bucket_index;
++      unsigned      solution;
++      unsigned      index;
++};
++
++#endif /* KAPS_PBQP_NODE_T_H */
index 0000000,0000000..11cb51c
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,74 @@@
++/*
++ * Copyright (C) 1995-2008 University of Karlsruhe.  All right reserved.
++ *
++ * This file is part of libFirm.
++ *
++ * This file may be distributed and/or modified under the terms of the
++ * GNU General Public License version 2 as published by the Free Software
++ * Foundation and appearing in the file LICENSE.GPL included in the
++ * packaging of this file.
++ *
++ * Licensees holding valid libFirm Professional Edition licenses may use
++ * this file in accordance with the libFirm Commercial License.
++ * Agreement provided with the Software.
++ *
++ * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
++ * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
++ * PURPOSE.
++ */
++
++/**
++ * @file
++ * @brief   PBQP data types.
++ * @date    02.10.2008
++ * @author  Sebastian Buchwald
++ * @version $Id$
++ */
++#ifndef KAPS_PBQP_T_H
++#define KAPS_PBQP_T_H
++
++#include <limits.h>
++#include <stdint.h>
++#include <stdio.h>
++
++#include "adt/obstack.h"
++
++#define KAPS_DUMP 0
++#define KAPS_ENABLE_VECTOR_NAMES 0
++#define KAPS_STATISTIC 0
++#define KAPS_TIMING 0
++#define KAPS_USE_UNSIGNED 1
++
++#if KAPS_USE_UNSIGNED
++      typedef unsigned num;
++      static const num INF_COSTS = UINT_MAX;
++#else
++      typedef intmax_t num;
++      static const num INF_COSTS = INTMAX_MAX;
++#endif
++
++#include "matrix_t.h"
++#include "vector_t.h"
++
++typedef struct pbqp_edge_t pbqp_edge_t;
++typedef struct pbqp_node_t pbqp_node_t;
++typedef struct pbqp_t      pbqp_t;
++
++struct pbqp_t {
++      struct obstack obstack;            /* Obstack. */
++      num            solution;           /* Computed solution. */
++      size_t         num_nodes;          /* Number of PBQP nodes. */
++      pbqp_node_t  **nodes;              /* Nodes of PBQP. */
++      FILE          *dump_file;          /* File to dump in. */
++#if KAPS_STATISTIC
++      unsigned       num_bf;             /* Number of brute force reductions. */
++      unsigned       num_edges;          /* Number of independent edges. */
++      unsigned       num_r0;             /* Number of trivial solved nodes. */
++      unsigned       num_r1;             /* Number of R1 reductions. */
++      unsigned       num_r2;             /* Number of R2 reductions. */
++      unsigned       num_rm;             /* Number of RM reductions. */
++      unsigned       num_rn;             /* Number of RN reductions. */
++#endif
++};
++
++#endif /* KAPS_PBQP_T_H */
index 0000000,0000000..04d58e6
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,202 @@@
++/*
++ * Copyright (C) 1995-2008 University of Karlsruhe.  All right reserved.
++ *
++ * This file is part of libFirm.
++ *
++ * This file may be distributed and/or modified under the terms of the
++ * GNU General Public License version 2 as published by the Free Software
++ * Foundation and appearing in the file LICENSE.GPL included in the
++ * packaging of this file.
++ *
++ * Licensees holding valid libFirm Professional Edition licenses may use
++ * this file in accordance with the libFirm Commercial License.
++ * Agreement provided with the Software.
++ *
++ * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
++ * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
++ * PURPOSE.
++ */
++
++/**
++ * @file
++ * @brief   PBQP vector.
++ * @date    02.10.2008
++ * @author  Sebastian Buchwald
++ * @version $Id$
++ */
++#include "config.h"
++
++#include <string.h>
++
++#include "adt/array.h"
++
++#include "vector.h"
++
++num pbqp_add(num x, num y)
++{
++      if (x == INF_COSTS || y == INF_COSTS) return INF_COSTS;
++
++      num res = x + y;
++
++#if !KAPS_USE_UNSIGNED
++      /* No positive overflow. */
++      assert(x < 0 || y < 0 || res >= x);
++      assert(x < 0 || y < 0 || res >= y);
++#endif
++
++      /* No negative overflow. */
++      assert(x > 0 || y > 0 || res <= x);
++      assert(x > 0 || y > 0 || res <= y);
++
++      /* Result is not infinity.*/
++      assert(res < INF_COSTS);
++
++      return res;
++}
++
++vector_t *vector_alloc(pbqp_t *pbqp, unsigned length)
++{
++      assert(length > 0);
++      vector_t *vec = (vector_t*)obstack_alloc(&pbqp->obstack, sizeof(*vec) + sizeof(*vec->entries) * length);
++      assert(vec);
++
++      vec->len = length;
++      memset(vec->entries, 0, sizeof(*vec->entries) * length);
++
++      return vec;
++}
++
++vector_t *vector_copy(pbqp_t *pbqp, vector_t *v)
++{
++      unsigned  len  = v->len;
++      vector_t *copy = (vector_t*)obstack_copy(&pbqp->obstack, v, sizeof(*copy) + sizeof(*copy->entries) * len);
++      assert(copy);
++
++      return copy;
++}
++
++void vector_add(vector_t *sum, vector_t *summand)
++{
++      int i;
++      int len;
++
++      assert(sum);
++      assert(summand);
++      assert(sum->len == summand->len);
++
++      len = sum->len;
++
++      for (i = 0; i < len; ++i) {
++              sum->entries[i].data = pbqp_add(sum->entries[i].data,
++                              summand->entries[i].data);
++      }
++}
++
++void vector_set(vector_t *vec, unsigned index, num value)
++{
++      assert(index < vec->len);
++      vec->entries[index].data = value;
++}
++
++#if KAPS_ENABLE_VECTOR_NAMES
++void vector_set_description(vector_t *vec, unsigned index, const char *name)
++{
++      assert(index < vec->len);
++      vec->entries[index].name = name;
++}
++#endif
++
++void vector_add_value(vector_t *vec, num value)
++{
++      unsigned index;
++      unsigned len;
++
++      assert(vec);
++
++      len = vec->len;
++
++      for (index = 0; index < len; ++index) {
++              vec->entries[index].data = pbqp_add(vec->entries[index].data, value);
++      }
++}
++
++void vector_add_matrix_col(vector_t *vec, pbqp_matrix_t *mat, unsigned col_index)
++{
++      unsigned index;
++      unsigned len;
++
++      assert(vec);
++      assert(mat);
++      assert(vec->len == mat->rows);
++      assert(col_index < mat->cols);
++
++      len = vec->len;
++
++      for (index = 0; index < len; ++index) {
++              vec->entries[index].data = pbqp_add(vec->entries[index].data, mat->entries[index * mat->cols + col_index]);
++      }
++}
++
++void vector_add_matrix_row(vector_t *vec, pbqp_matrix_t *mat, unsigned row_index)
++{
++      unsigned index;
++      unsigned len;
++
++      assert(vec);
++      assert(mat);
++      assert(vec->len == mat->cols);
++      assert(row_index < mat->rows);
++
++      len = vec->len;
++
++      for (index = 0; index < len; ++index) {
++              vec->entries[index].data = pbqp_add(vec->entries[index].data,
++                              mat->entries[row_index * mat->cols + index]);
++      }
++}
++
++num vector_get_min(vector_t *vec)
++{
++      unsigned index;
++      unsigned len;
++      num      min = INF_COSTS;
++
++      assert(vec);
++
++      len = vec->len;
++      assert(len > 0);
++
++      for (index = 0; index < len; ++index) {
++              num elem = vec->entries[index].data;
++
++              if (elem < min) {
++                      min = elem;
++              }
++      }
++
++      return min;
++}
++
++unsigned vector_get_min_index(vector_t *vec)
++{
++      unsigned index;
++      unsigned len;
++      unsigned min_index = 0;
++      num      min       = INF_COSTS;
++
++      assert(vec);
++
++      len = vec->len;
++      assert(len > 0);
++
++      for (index = 0; index < len; ++index) {
++              num elem = vec->entries[index].data;
++
++              if (elem < min) {
++                      min = elem;
++                      min_index = index;
++              }
++      }
++
++      return min_index;
++}
index 0000000,0000000..d54aaea
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,56 @@@
++/*
++ * Copyright (C) 1995-2008 University of Karlsruhe.  All right reserved.
++ *
++ * This file is part of libFirm.
++ *
++ * This file may be distributed and/or modified under the terms of the
++ * GNU General Public License version 2 as published by the Free Software
++ * Foundation and appearing in the file LICENSE.GPL included in the
++ * packaging of this file.
++ *
++ * Licensees holding valid libFirm Professional Edition licenses may use
++ * this file in accordance with the libFirm Commercial License.
++ * Agreement provided with the Software.
++ *
++ * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
++ * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
++ * PURPOSE.
++ */
++
++/**
++ * @file
++ * @brief   PBQP vector.
++ * @date    02.10.2008
++ * @author  Sebastian Buchwald
++ * @version $Id$
++ */
++#ifndef KAPS_VECTOR_H
++#define KAPS_VECTOR_H
++
++#include "vector_t.h"
++
++num pbqp_add(num x, num y);
++
++vector_t *vector_alloc(pbqp_t *pbqp, unsigned length);
++
++/* Copy the given vector. */
++vector_t *vector_copy(pbqp_t *pbqp, vector_t *v);
++
++/* sum += summand */
++void vector_add(vector_t *sum, vector_t *summand);
++
++void vector_set(vector_t *vec, unsigned index, num value);
++
++#if KAPS_ENABLE_VECTOR_NAMES
++void vector_set_description(vector_t *vec, unsigned index, const char *name);
++#endif
++
++void vector_add_value(vector_t *vec, num value);
++
++void vector_add_matrix_col(vector_t *vec, pbqp_matrix_t *mat, unsigned col_index);
++void vector_add_matrix_row(vector_t *vec, pbqp_matrix_t *mat, unsigned row_index);
++
++num vector_get_min(vector_t *vec);
++unsigned vector_get_min_index(vector_t *vec);
++
++#endif /* KAPS_VECTOR_H */
index 0000000,0000000..03692d1
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,49 @@@
++/*
++ * Copyright (C) 1995-2008 University of Karlsruhe.  All right reserved.
++ *
++ * This file is part of libFirm.
++ *
++ * This file may be distributed and/or modified under the terms of the
++ * GNU General Public License version 2 as published by the Free Software
++ * Foundation and appearing in the file LICENSE.GPL included in the
++ * packaging of this file.
++ *
++ * Licensees holding valid libFirm Professional Edition licenses may use
++ * this file in accordance with the libFirm Commercial License.
++ * Agreement provided with the Software.
++ *
++ * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
++ * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
++ * PURPOSE.
++ */
++
++/**
++ * @file
++ * @brief   PBQP vector data types.
++ * @date    02.10.2008
++ * @author  Sebastian Buchwald
++ * @version $Id$
++ */
++#include "config.h"
++#ifndef KAPS_VECTOR_T_H
++#define KAPS_VECTOR_T_H
++
++#include "pbqp_t.h"
++
++typedef struct vec_elem_t vec_elem_t;
++
++struct vec_elem_t {
++      num data;
++#if KAPS_ENABLE_VECTOR_NAMES
++      const char *name;
++#endif
++};
++
++typedef struct vector_t vector_t;
++
++struct vector_t {
++      unsigned   len;
++      vec_elem_t entries[];
++};
++
++#endif /* KAPS_VECTOR_T_H */