* @brief Simple copy minimization heuristics.
* @author Christian Wuerdig
* @date 27.04.2007
- * @version $Id$
*
* This is the C implementation of the mst algorithm
* originally written in Java by Sebastian Hack.
#include "irnode_t.h"
#include "bitset.h"
#include "raw_bitset.h"
-#include "irphase_t.h"
+#include "irnodemap.h"
#include "pqueue.h"
#include "xmalloc.h"
#include "pdeq.h"
#include "irprintf.h"
-#include "irbitset.h"
+#include "util.h"
+#include "irtools.h"
#include "error.h"
#include "list.h"
#include "statev.h"
-#include "irbitset.h"
-
#include "bearch.h"
#include "beifg.h"
#include "be_t.h"
int n_regs; /**< number of regs in class */
int k; /**< number of non-ignore registers in class */
bitset_t *allocatable_regs; /**< set containing all global ignore registers */
- ir_phase ph; /**< phase object holding data for nodes */
+ ir_nodemap map; /**< phase object holding data for nodes */
+ struct obstack obst;
pqueue_t *chunks; /**< priority queue for chunks */
list_head chunklist; /**< list holding all chunks */
be_ifg_t *ifg; /**< the interference graph */
real_t constr_factor;
} co_mst_irn_t;
+/**
+ * In case there is no phase information for irn, initialize it.
+ */
+static co_mst_irn_t *co_mst_irn_init(co_mst_env_t *env, const ir_node *irn)
+{
+ co_mst_irn_t *res = OALLOC(&env->obst, co_mst_irn_t);
+
+ const arch_register_req_t *req;
+ neighbours_iter_t nodes_it;
+ ir_node *neigh;
+ unsigned len;
+
+ res->irn = irn;
+ res->chunk = NULL;
+ res->fixed = 0;
+ res->tmp_col = -1;
+ res->int_neighs = NULL;
+ res->int_aff_neigh = 0;
+ res->col = arch_register_get_index(arch_get_irn_register(irn));
+ res->init_col = res->col;
+ INIT_LIST_HEAD(&res->list);
+
+ DB((dbg, LEVEL_4, "Creating phase info for %+F\n", irn));
+
+ /* set admissible registers */
+ res->adm_colors = bitset_obstack_alloc(&env->obst, env->n_regs);
+
+ /* Exclude colors not assignable to the irn */
+ req = arch_get_irn_register_req(irn);
+ if (arch_register_req_is(req, limited)) {
+ rbitset_copy_to_bitset(req->limited, res->adm_colors);
+ } else {
+ bitset_set_all(res->adm_colors);
+ }
+
+ /* exclude global ignore registers as well */
+ bitset_and(res->adm_colors, env->allocatable_regs);
+
+ /* compute the constraint factor */
+ res->constr_factor = (real_t) (1 + env->n_regs - bitset_popcount(res->adm_colors)) / env->n_regs;
+
+ /* set the number of interfering affinity neighbours to -1, they are calculated later */
+ res->int_aff_neigh = -1;
+
+ /* build list of interfering neighbours */
+ len = 0;
+ be_ifg_foreach_neighbour(env->ifg, &nodes_it, irn, neigh) {
+ if (!arch_irn_is_ignore(neigh)) {
+ obstack_ptr_grow(&env->obst, neigh);
+ ++len;
+ }
+ }
+ res->int_neighs = (ir_node**)obstack_finish(&env->obst);
+ res->n_neighs = len;
+ return res;
+}
+
static co_mst_irn_t *get_co_mst_irn(co_mst_env_t *env, const ir_node *node)
{
- return (co_mst_irn_t*)phase_get_or_set_irn_data(&env->ph, node);
+ co_mst_irn_t *res = ir_nodemap_get(co_mst_irn_t, &env->map, node);
+ if (res == NULL) {
+ res = co_mst_irn_init(env, node);
+ ir_nodemap_insert(&env->map, node, res);
+ }
+ return res;
}
typedef int decide_func_t(const co_mst_irn_t *node, int col);
*/
static void dbg_admissible_colors(const co_mst_env_t *env, const co_mst_irn_t *node)
{
- size_t idx;
(void) env;
if (bitset_popcount(node->adm_colors) < 1)
const col_cost_t *c1 = (const col_cost_t*)a;
const col_cost_t *c2 = (const col_cost_t*)b;
real_t diff = c1->cost - c2->cost;
- return (diff > 0) - (diff < 0);
+
+ if (diff < 0)
+ return 1;
+ if (diff > 0)
+ return -1;
+
+ return QSORT_CMP(c1->col, c2->col);
}
static int cmp_col_cost_gt(const void *a, const void *b)
const col_cost_t *c2 = (const col_cost_t*)b;
real_t diff = c2->cost - c1->cost;
- if (diff == 0.0)
- return QSORT_CMP(c1->col, c2->col);
+ if (diff > 0)
+ return 1;
+ if (diff < 0)
+ return -1;
- return (diff > 0) - (diff < 0);
+ return QSORT_CMP(c1->col, c2->col);
}
/**
}
}
-/**
- * In case there is no phase information for irn, initialize it.
- */
-static void *co_mst_irn_init(ir_phase *ph, const ir_node *irn)
-{
- co_mst_irn_t *res = (co_mst_irn_t*)phase_alloc(ph, sizeof(res[0]));
- co_mst_env_t *env = (co_mst_env_t*)ph->priv;
-
- const arch_register_req_t *req;
- neighbours_iter_t nodes_it;
- ir_node *neigh;
- unsigned len;
-
- res->irn = irn;
- res->chunk = NULL;
- res->fixed = 0;
- res->tmp_col = -1;
- res->int_neighs = NULL;
- res->int_aff_neigh = 0;
- res->col = arch_register_get_index(arch_get_irn_register(irn));
- res->init_col = res->col;
- INIT_LIST_HEAD(&res->list);
-
- DB((dbg, LEVEL_4, "Creating phase info for %+F\n", irn));
-
- /* set admissible registers */
- res->adm_colors = bitset_obstack_alloc(phase_obst(ph), env->n_regs);
-
- /* Exclude colors not assignable to the irn */
- req = arch_get_register_req_out(irn);
- if (arch_register_req_is(req, limited))
- rbitset_copy_to_bitset(req->limited, res->adm_colors);
- else
- bitset_set_all(res->adm_colors);
-
- /* exclude global ignore registers as well */
- bitset_and(res->adm_colors, env->allocatable_regs);
-
- /* compute the constraint factor */
- res->constr_factor = (real_t) (1 + env->n_regs - bitset_popcount(res->adm_colors)) / env->n_regs;
-
- /* set the number of interfering affinity neighbours to -1, they are calculated later */
- res->int_aff_neigh = -1;
-
- /* build list of interfering neighbours */
- len = 0;
- be_ifg_foreach_neighbour(env->ifg, &nodes_it, irn, neigh) {
- if (!arch_irn_is_ignore(neigh)) {
- obstack_ptr_grow(phase_obst(ph), neigh);
- ++len;
- }
- }
- res->int_neighs = (ir_node**)obstack_finish(phase_obst(ph));
- res->n_neighs = len;
- return res;
-}
-
/**
* Check if affinity chunk @p chunk interferes with node @p irn.
*/
node->chunk = c;
if (node->constr_factor > REAL(0.0)) {
- size_t col;
bitset_foreach (node->adm_colors, col)
c->color_affinity[col].cost += node->constr_factor;
}
if (an != NULL) {
- neighb_t *neigh;
co_gs_foreach_neighb(an, neigh) {
const ir_node *m = neigh->irn;
*/
static int count_interfering_aff_neighs(co_mst_env_t *env, const affinity_node_t *an)
{
- const neighb_t *neigh;
const ir_node *irn = an->irn;
const co_mst_irn_t *node = get_co_mst_irn(env, irn);
int res = 0;
ir_node *n;
int i, len;
aff_chunk_t *curr_chunk;
+ size_t pn;
/* at first we create the affinity edge objects */
be_ifg_foreach_node(env->ifg, &nodes_it, n) {
an = get_affinity_info(env->co, n);
if (an != NULL) {
- neighb_t *neigh;
-
if (n1->int_aff_neigh < 0)
n1->int_aff_neigh = count_interfering_aff_neighs(env, an);
pqueue_put(env->chunks, curr_chunk, curr_chunk->weight);
}
- foreach_phase_irn(&env->ph, n) {
- co_mst_irn_t *mirn = get_co_mst_irn(env, n);
+ for (pn = 0; pn < ARR_LEN(env->map.data); ++pn) {
+ co_mst_irn_t *mirn = (co_mst_irn_t*)env->map.data[pn];
+ if (mirn == NULL)
+ continue;
+ if (mirn->chunk != NULL)
+ continue;
- if (mirn->chunk == NULL) {
- /* no chunk is allocated so far, do it now */
- aff_chunk_t *curr_chunk = new_aff_chunk(env);
- aff_chunk_add_node(curr_chunk, mirn);
+ /* no chunk is allocated so far, do it now */
+ aff_chunk_t *curr_chunk = new_aff_chunk(env);
+ aff_chunk_add_node(curr_chunk, mirn);
- aff_chunk_assure_weight(env, curr_chunk);
+ aff_chunk_assure_weight(env, curr_chunk);
- DBG((dbg, LEVEL_1, "entry #%u", curr_chunk->id));
- DBG_AFF_CHUNK(env, LEVEL_1, curr_chunk);
- DBG((dbg, LEVEL_1, "\n"));
+ DBG((dbg, LEVEL_1, "entry #%u", curr_chunk->id));
+ DBG_AFF_CHUNK(env, LEVEL_1, curr_chunk);
+ DBG((dbg, LEVEL_1, "\n"));
- pqueue_put(env->chunks, curr_chunk, curr_chunk->weight);
- }
+ pqueue_put(env->chunks, curr_chunk, curr_chunk->weight);
}
DEL_ARR_F(edges);
const ir_node *irn = chunk->n[--i];
affinity_node_t *an = get_affinity_info(env->co, irn);
int w = 0;
- neighb_t *neigh;
if (arch_irn_is_ignore(irn))
continue;
}
if (max_node) {
- bitset_t *visited = bitset_irg_malloc(env->co->irg);
+ bitset_t *visited = bitset_malloc(get_irg_last_idx(env->co->irg));
for (i = ARR_LEN(chunk->n); i != 0;)
- bitset_add_irn(visited, chunk->n[--i]);
+ bitset_set(visited, get_irn_idx(chunk->n[--i]));
pqueue_put(grow, (void *) max_node, max_weight);
- bitset_remv_irn(visited, max_node);
+ bitset_clear(visited, get_irn_idx(max_node));
i = 0;
while (!pqueue_empty(grow)) {
ir_node *irn = (ir_node*)pqueue_pop_front(grow);
affinity_node_t *an = get_affinity_info(env->co, irn);
- neighb_t *neigh;
if (arch_irn_is_ignore(irn))
continue;
co_gs_foreach_neighb(an, neigh) {
co_mst_irn_t *node = get_co_mst_irn(env, neigh->irn);
- if (bitset_contains_irn(visited, node->irn)) {
+ if (bitset_is_set(visited, get_irn_idx(node->irn))) {
pqueue_put(grow, (void *) neigh->irn, neigh->costs);
- bitset_remv_irn(visited, node->irn);
+ bitset_clear(visited, get_irn_idx(node->irn));
}
}
}
/* check all affinity neighbors */
if (an != NULL) {
- neighb_t *neigh;
co_gs_foreach_neighb(an, neigh) {
const ir_node *m = neigh->irn;
int m_idx = get_irn_idx(m);
*/
static aff_chunk_t *fragment_chunk(co_mst_env_t *env, int col, aff_chunk_t *c, waitq *tmp)
{
- bitset_t *visited = bitset_irg_malloc(env->co->irg);
+ bitset_t *visited = bitset_malloc(get_irg_last_idx(env->co->irg));
int idx, len;
aff_chunk_t *best = NULL;
*/
for (i = 0; i < env->k; ++i) {
int col = order[i].col;
- waitq *good_starts = new_waitq();
+ waitq *good_starts;
aff_chunk_t *local_best;
int n_succeeded;
DB((dbg, LEVEL_2, "\ttrying color %d\n", col));
n_succeeded = 0;
+ good_starts = new_waitq();
/* try to bring all nodes of given chunk to the current color. */
for (idx = 0, len = ARR_LEN(c->n); idx < len; ++idx) {
}
/* try next color when failed */
- if (n_succeeded == 0)
+ if (n_succeeded == 0) {
+ del_waitq(good_starts);
continue;
+ }
/* fragment the chunk according to the coloring */
local_best = fragment_chunk(env, col, c, tmp_chunks);
}
/* fragment the remaining chunk */
- visited = bitset_irg_malloc(env->co->irg);
+ visited = bitset_malloc(get_irg_last_idx(env->co->irg));
for (idx = 0, len = ARR_LEN(best_chunk->n); idx < len; ++idx)
bitset_set(visited, get_irn_idx(best_chunk->n[idx]));
bitset_t *allocatable_regs = bitset_alloca(n_regs);
unsigned i, j;
size_t k;
+ size_t pn;
ir_node *irn;
co_mst_env_t mst_env;
stat_ev_tim_push();
/* init phase */
- phase_init(&mst_env.ph, co->irg, co_mst_irn_init);
- phase_set_private(&mst_env.ph, &mst_env);
+ ir_nodemap_init(&mst_env.map, co->irg);
+ obstack_init(&mst_env.obst);
be_put_allocatable_regs(co->cenv->irg, co->cls, allocatable_regs);
k = bitset_popcount(allocatable_regs);
mst_env.ifg = co->cenv->ifg;
INIT_LIST_HEAD(&mst_env.chunklist);
mst_env.chunk_visited = 0;
- mst_env.single_cols = (col_cost_t**)phase_alloc(&mst_env.ph, sizeof(*mst_env.single_cols) * n_regs);
+ mst_env.single_cols = OALLOCN(&mst_env.obst, col_cost_t*, n_regs);
for (i = 0; i < n_regs; ++i) {
- col_cost_t *vec = (col_cost_t*)phase_alloc(&mst_env.ph, sizeof(*vec) * n_regs);
+ col_cost_t *vec = OALLOCN(&mst_env.obst, col_cost_t, n_regs);
mst_env.single_cols[i] = vec;
for (j = 0; j < n_regs; ++j) {
}
/* apply coloring */
- foreach_phase_irn(&mst_env.ph, irn) {
- co_mst_irn_t *mirn;
+ for (pn = 0; pn < ARR_LEN(mst_env.map.data); ++pn) {
+ co_mst_irn_t *mirn = (co_mst_irn_t*)mst_env.map.data[pn];
const arch_register_t *reg;
-
+ if (mirn == NULL)
+ continue;
+ irn = get_idx_irn(co->irg, pn);
if (arch_irn_is_ignore(irn))
continue;
- mirn = get_co_mst_irn(&mst_env, irn);
- // assert(mirn->fixed && "Node should have fixed color");
-
/* skip nodes where color hasn't changed */
if (mirn->init_col == mirn->col)
continue;
/* free allocated memory */
del_pqueue(mst_env.chunks);
- phase_deinit(&mst_env.ph);
+ obstack_free(&mst_env.obst, NULL);
+ ir_nodemap_destroy(&mst_env.map);
stat_ev_tim_pop("heur4_total");