+#include "beifg_impl.h"
+#include "irphase_t.h"
+#include "error.h"
+#include "xmalloc.h"
+
+#include "becopystat.h"
+#include "becopyopt.h"
+#include "beirg_t.h"
+#include "bemodule.h"
+
+/** Defines values for the ifg performance test */
+#define BE_CH_PERFORMANCETEST_MIN_NODES (50)
+#define BE_CH_PERFORMANCETEST_COUNT (500)
+
+typedef struct _coloring_t coloring_t;
+
+struct _coloring_t {
+ ir_phase ph;
+ ir_graph *irg;
+};
+
+size_t (be_ifg_nodes_iter_size)(const be_ifg_t *ifg)
+{
+ return ifg->impl->nodes_iter_size;
+}
+
+size_t (be_ifg_neighbours_iter_size)(const be_ifg_t *ifg)
+{
+ return ifg->impl->neighbours_iter_size;
+}
+
+size_t (be_ifg_cliques_iter_size)(const be_ifg_t *ifg)
+{
+ return ifg->impl->cliques_iter_size;
+}
+
+static void *regs_irn_data_init(ir_phase *ph, const ir_node *irn, void *data)
+{
+ (void)ph;
+ (void)data;
+
+ return (void*)arch_get_irn_register(irn);
+}
+
+static coloring_t *coloring_init(coloring_t *c, ir_graph *irg)
+{
+ phase_init(&c->ph, "regs_map", irg, PHASE_DEFAULT_GROWTH, regs_irn_data_init, NULL);
+ c->irg = irg;
+ return c;
+}
+
+static void get_irn_color(ir_node *irn, void *c)
+{
+ coloring_t *coloring = c;
+ phase_get_or_set_irn_data(&coloring->ph, irn);
+}
+
+static void restore_irn_color(ir_node *irn, void *c)
+{
+ coloring_t *coloring = c;
+ const arch_register_t *reg = phase_get_irn_data(&coloring->ph, irn);
+ if(reg)
+ arch_set_irn_register(irn, reg);
+}
+
+static void coloring_save(coloring_t *c)
+{
+ irg_walk_graph(c->irg, NULL, get_irn_color, c);
+}
+
+static void coloring_restore(coloring_t *c)
+{
+ irg_walk_graph(c->irg, NULL, restore_irn_color, c);
+}
+
+void (be_ifg_free)(be_ifg_t *ifg)
+{
+ ifg->impl->free(ifg);
+}
+
+int (be_ifg_connected)(const be_ifg_t *ifg, const ir_node *a, const ir_node *b)
+{
+ return ifg->impl->connected(ifg, a, b);
+}
+
+ir_node *(be_ifg_neighbours_begin)(const be_ifg_t *ifg, void *iter, const ir_node *irn)
+{
+ return ifg->impl->neighbours_begin(ifg, iter, irn);
+}
+
+ir_node *(be_ifg_neighbours_next)(const be_ifg_t *ifg, void *iter)
+{
+ return ifg->impl->neighbours_next(ifg, iter);
+}
+
+void (be_ifg_neighbours_break)(const be_ifg_t *ifg, void *iter)
+{
+ ifg->impl->neighbours_break(ifg, iter);
+}
+
+ir_node *(be_ifg_nodes_begin)(const be_ifg_t *ifg, void *iter)
+{
+ return ifg->impl->nodes_begin(ifg, iter);
+}
+
+ir_node *(be_ifg_nodes_next)(const be_ifg_t *ifg, void *iter)
+{
+ return ifg->impl->nodes_next(ifg, iter);
+}
+
+void (be_ifg_nodes_break)(const be_ifg_t *ifg, void *iter)
+{
+ ifg->impl->nodes_break(ifg, iter);
+}
+
+int (be_ifg_cliques_begin)(const be_ifg_t *ifg, void *iter, ir_node **buf)
+{
+ return ifg->impl->cliques_begin(ifg, iter, buf);
+}
+
+int (be_ifg_cliques_next)(const be_ifg_t *ifg, void *iter)
+{
+ return ifg->impl->cliques_next(ifg, iter);
+}
+
+void (be_ifg_cliques_break)(const be_ifg_t *ifg, void *iter)
+{
+ ifg->impl->cliques_break(ifg, iter);
+}
+
+int (be_ifg_degree)(const be_ifg_t *ifg, const ir_node *irn)
+{
+ return ifg->impl->degree(ifg, irn);
+}
+
+
+int be_ifg_is_simplicial(const be_ifg_t *ifg, const ir_node *irn)
+{
+ int degree = be_ifg_degree(ifg, irn);
+ void *iter = be_ifg_neighbours_iter_alloca(ifg);
+
+ ir_node **neighbours = XMALLOCN(ir_node*, degree);
+
+ ir_node *curr;
+ int i, j;
+
+ i = 0;
+ be_ifg_foreach_neighbour(ifg, iter, irn, curr)
+ neighbours[i++] = curr;
+
+ for(i = 0; i < degree; ++i) {
+ for(j = 0; j < i; ++j)
+ if(!be_ifg_connected(ifg, neighbours[i], neighbours[j])) {
+ free(neighbours);
+ return 0;
+ }
+ }
+
+
+ free(neighbours);
+ return 1;
+}
+
+void be_ifg_check(const be_ifg_t *ifg)
+{
+ void *iter1 = be_ifg_nodes_iter_alloca(ifg);
+ void *iter2 = be_ifg_neighbours_iter_alloca(ifg);
+
+ ir_node *n, *m;
+ int node_count = 0;
+ int neighbours_count = 0;
+ int degree = 0;
+
+ /* count all nodes */
+ ir_printf("\n\nFound the following nodes in the graph %+F:\n\n", current_ir_graph);
+ be_ifg_foreach_node(ifg,iter1,n)
+ {
+ node_count++;
+ degree = be_ifg_degree(ifg, n);
+ ir_printf("%d. %+F with degree: %d\n", node_count, n, degree);
+ }
+
+ ir_printf("\n\nNumber of nodes: %d\n\n", node_count);
+
+ /* Check, if all neighbours are indeed connected to the node. */
+ be_ifg_foreach_node(ifg, iter1, n)
+ {
+ ir_printf("\n%+F; ", n);
+ be_ifg_foreach_neighbour(ifg, iter2, n, m)
+ {
+ ir_printf("%+F; ", m);
+ neighbours_count++;
+ if(!be_ifg_connected(ifg, n, m))
+ ir_fprintf(stderr, "%+F is a neighbour of %+F but they are not connected!\n", n, m);
+ }
+ }
+ ir_printf("\n\nFound %d nodes in the 'check neighbour section'\n", neighbours_count);
+}
+
+int be_ifg_check_get_node_count(const be_ifg_t *ifg)
+{
+ void *iter = be_ifg_nodes_iter_alloca(ifg);
+ int node_count = 0;
+ ir_node *n;
+
+ be_ifg_foreach_node(ifg, iter, n)
+ {
+ node_count++;
+ }
+
+ return node_count;
+}
+
+static int be_ifg_check_cmp_nodes(const void *a, const void *b)
+{
+ const ir_node *node_a = *(ir_node **)a;
+ const ir_node *node_b = *(ir_node **)b;
+
+ long nr_a = get_irn_idx(node_a);
+ long nr_b = get_irn_idx(node_b);
+
+ return QSORT_CMP(nr_a, nr_b);
+}
+
+void be_ifg_check_sorted(const be_ifg_t *ifg)
+{
+ void *iter1 = be_ifg_nodes_iter_alloca(ifg);
+ void *iter2 = be_ifg_neighbours_iter_alloca(ifg);
+
+ ir_node *n, *m;
+ const int node_count = be_ifg_check_get_node_count(ifg);
+ int i = 0;
+
+ ir_node **all_nodes = XMALLOCN(ir_node*, node_count);
+
+ be_ifg_foreach_node(ifg, iter1, n)
+ {
+ if(!node_is_in_irgs_storage(ifg->env->irg, n))
+ {
+ ir_printf("+%F is in ifg but not in the current irg!", n);
+ assert (node_is_in_irgs_storage(ifg->env->irg, n));
+ }
+
+ all_nodes[i] = n;
+ i++;
+ }
+
+ qsort(all_nodes, node_count, sizeof(all_nodes[0]), be_ifg_check_cmp_nodes);
+
+ for (i = 0; i < node_count; i++)
+ {
+ ir_node **neighbours = XMALLOCN(ir_node*, node_count);
+ int j = 0;
+ int k = 0;
+ int degree = 0;
+
+ degree = be_ifg_degree(ifg, all_nodes[i]);
+
+ be_ifg_foreach_neighbour(ifg, iter2, all_nodes[i], m)
+ {
+ neighbours[j] = m;
+ j++;
+ }
+
+ qsort(neighbours, j, sizeof(neighbours[0]), be_ifg_check_cmp_nodes);
+
+ ir_printf("%d. %+F's neighbours(%d): ", i+1, all_nodes[i], degree);
+
+ for(k = 0; k < j; k++)
+ {
+ ir_printf("%+F, ", neighbours[k]);
+ }
+
+ ir_printf("\n");
+
+ free(neighbours);
+ }
+
+ free(all_nodes);
+
+}
+
+void be_ifg_check_sorted_to_file(const be_ifg_t *ifg, FILE *f)
+{
+ void *iter1 = be_ifg_nodes_iter_alloca(ifg);
+ void *iter2 = be_ifg_neighbours_iter_alloca(ifg);
+
+ ir_node *n, *m;
+ const int node_count = be_ifg_check_get_node_count(ifg);
+ int i = 0;
+
+ ir_node **all_nodes = XMALLOCN(ir_node*, node_count);
+
+ be_ifg_foreach_node(ifg, iter1, n)
+ {
+ if(!node_is_in_irgs_storage(ifg->env->irg, n))
+ {
+ ir_fprintf (f,"+%F is in ifg but not in the current irg!",n);
+ assert (node_is_in_irgs_storage(ifg->env->irg, n));
+ }
+
+ all_nodes[i] = n;
+ i++;
+ }
+
+ qsort(all_nodes, node_count, sizeof(all_nodes[0]), be_ifg_check_cmp_nodes);
+
+ for (i = 0; i < node_count; i++)
+ {
+ ir_node **neighbours = XMALLOCN(ir_node*, node_count);
+ int j = 0;
+ int k = 0;
+ int degree = 0;
+
+ degree = be_ifg_degree(ifg, all_nodes[i]);
+
+ be_ifg_foreach_neighbour(ifg, iter2, all_nodes[i], m)
+ {
+ neighbours[j] = m;
+ j++;
+ }
+
+ qsort(neighbours, j, sizeof(neighbours[0]), be_ifg_check_cmp_nodes);