2 * This is the C implementation of the trivial mst algo
3 * originally written in Java by Sebastian Hack.
4 * Performs simple copy minimzation.
6 * @author Christian Wuerdig
14 #endif /* HAVE_CONFIG_H */
19 #include "raw_bitset.h"
20 #include "irphase_t.h"
26 typedef struct _aff_chunk_t {
31 typedef struct _aff_edge_t {
37 /* main coalescing environment*/
38 typedef struct _co_mst_safe_env_t {
39 int n_regs; /**< number of regs in class */
40 int k; /**< number of non-ignore registers in class */
41 bitset_t *ignore_regs; /**< set containing all global ignore registers */
42 ir_phase ph; /**< phase object holding data for nodes */
43 pqueue *chunks; /**< priority queue for chunks */
44 be_ifg_t *ifg; /**< the interference graph */
45 const arch_env_t *aenv; /**< the arch environment */
48 /* stores coalescing related information for a node */
49 typedef struct _co_mst_safe_irn_t {
59 #define get_co_mst_safe_irn(mst_env, irn) (phase_get_or_set_irn_data(&(mst_env)->ph, (irn)))
61 /* compares two affinity edges */
62 static int cmp_aff_edge(const void *a, const void *b) {
63 const aff_edge_t * const *e1 = d1;
64 const aff_edge_t * const *e2 = d2;
66 /* sort in descending order */
67 return (*e1)->weight < (*e2)->weight ? 1 : -1;
71 * In case there is no phase information for irn, initialize it.
73 static void *co_mst_safe_irn_init(ir_phase *ph, ir_node *irn, void *old) {
74 co_mst_safe_irn_t *res = old ? old : phase_alloc(ph, sizeof(res[0]));
75 co_mst_safe_env_t *env = ph->priv;
78 void *neigh_it = be_ifg_neighbours_iter_alloca(env->ifg);
79 const arch_register_req_t *req;
87 res->init_col = arch_register_get_index(arch_get_irn_register(env->aenv, irn));
89 /* set admissible registers */
90 res->adm_colors = bitset_obstack_alloc(phase_obst(ph), env->n_regs);
92 /* Exclude colors not assignable to the irn */
93 req = arch_get_register_req(env->aenv, irn, -1);
94 if (arch_register_req_is(req, limited))
95 rbitset_copy_to_bitset(req->limited, res->adm_colors);
97 /* exclude global ignore registers as well */
98 bitset_andnot(res->adm_colors, env->ignore_regs);
100 /* calculate the number of interfering neigbours */
101 be_ifg_foreach_neighbour(env->ifg, neigh_it, irn, m) {
102 if (! arch_irn_is(env->aenv, m, ignore))
112 * Build chunks of nodes connected by affinity edges.
113 * We start at the heaviest affinity edge.
114 * The chunks of the two edge-defining nodes will be
115 * merged if there are no interference edges from one
116 * chunk to the other.
118 static void build_affinity_chunks(co_mst_safe_env_t *env) {
119 void *nodes_it = be_ifg_nodes_iter_alloca(env->ifg);
120 aff_edge_t **edges = NEW_ARR_F(aff_edge_t *, 0);
123 /* at first we create the affinity edge objects */
124 be_ifg_foreach_node(env->ifg, nodes_it, n) {
125 int n_idx = get_irn_idx(n);
126 co_mst_safe_irn_t *n1;
129 if (arch_irn_is(env->aenv, n, ignore))
132 n1 = get_co_mst_safe_irn(env, n);
133 an = get_affinity_info(co, n);
137 co_gs_foreach_neighb(an, neigh) {
138 ir_node *m = neigh->irn;
139 int m_idx = get_irn_idx(m);
140 co_mst_safe_irn_t *n2;
142 if (arch_irn_is(env->aenv, m, ignore))
145 n2 = get_co_mst_safe_irn(env, m);
147 /* record the edge in only one direction and only to non-ignore nodes */
149 aff_edge_t *edge = phase_alloc(&env->ph, sizeof(*edge));
153 edge->weight = (double)neigh->cost / (double)(1 + n1->int_neigh + n2->int_neigh);
154 ARR_APP1(aff_edge_t *, edges, edge);
160 /* now: sort edges and build the chunks */
161 qsort(edges, ARR_LEN(edges), sizeof(edges[0]), cmp_aff_edge);
162 for (i = 0; i < ARR_LEN(edges); ++i) {
170 * Main driver for mst safe coalescing algorithm.
172 int co_solve_heuristic_mst_safe(copy_opt_t *co)
174 be_ifg_t *ifg = co->cenv->ifg;
175 unsigned n_regs = co->cenv->cls->n_regs;
176 bitset_t *ignore_regs = bitset_alloca(n_regs);
178 co_mst_safe_env_t mst_env;
181 phase_init(&mst_env.ph, "co_mst_safe", co->irg, PHASE_DEFAULT_GROWTH, co_mst_safe_irn_init, &mst_env);
183 k = be_put_ignore_regs(co->cenv->birg, co->cenv->cls, ignore_regs);
186 mst_env.n_regs = n_regs;
188 mst_env.chunks = new_pqueue();
191 /* build affinity chunks */
192 build_affinity_chunks(&mst_env);
194 /* color chunks as long as there are some */
195 while (! pqueue_empty(mst_env.chunks)) {
196 aff_chunk_t *chunk = pqueue_get(mst_env.chunks);
197 color_aff_chunk(&mst_env, chunk);
200 /* free allocated memory */
201 del_pqueue(mst_env.chunks);
202 phase_free(&mst_env.ph);