becopyilp2.c 17.1 KB
Newer Older
Christian Würdig's avatar
Christian Würdig committed
1
/*
Michael Beck's avatar
Michael Beck committed
2
 * Copyright (C) 1995-2008 University of Karlsruhe.  All right reserved.
Christian Würdig's avatar
Christian Würdig committed
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
 *
 * 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.
 */

20
/**
Christian Würdig's avatar
Christian Würdig committed
21
22
23
24
 * @file
 * @brief       ILP based copy minimization.
 * @author      Daniel Grund
 * @date        28.02.2006
Daniel Grund's avatar
Daniel Grund committed
25
 *
26
 * ILP formalization using G=(V, E, Q):
Daniel Grund's avatar
Daniel Grund committed
27
 *  - 2 class of variables: coloring vars x_ic   and   equal color vars y_ij
28
 *  - Path constraints
Daniel Grund's avatar
Daniel Grund committed
29
 *  - Clique-star constraints
30
31
 *
 *
32
 * \min \sum_{ (i,j) \in Q }  w_ij y_ij
33
 *
34
 *     \sum_c x_nc           =  1           n \in N, c \in C
35
 *
36
 *     x_nc                  =  0           n \in N, c \not\in C(n)
37
 *
38
 *     \sum x_nc            <=  1           x_nc \in Clique \in AllCliques,  c \in C
39
 *
40
 *     \sum_{e \in p} y_e   >=  1           p \in P      path constraints
41
 *
42
 *     \sum_{e \in cs} y_e  >= |cs| - 1     cs \in CP    clique-star constraints
43
 *
44
 *     x_nc, y_ij \in N,   w_ij \in R^+
45
 */
yb9976's avatar
yb9976 committed
46
#include "config.h"
Christian Würdig's avatar
Christian Würdig committed
47

Matthias Braun's avatar
Matthias Braun committed
48
#include "bitset.h"
49
#include "error.h"
Matthias Braun's avatar
Matthias Braun committed
50
#include "raw_bitset.h"
51
52
#include "pdeq.h"

53
#include "util.h"
Daniel Grund's avatar
Daniel Grund committed
54
#include "irgwalk.h"
55
#include "becopyilp_t.h"
56
#include "beifg.h"
57
#include "besched.h"
58
#include "bemodule.h"
59

Matthias Braun's avatar
Matthias Braun committed
60
DEBUG_ONLY(static firm_dbg_module_t *dbg;)
Daniel Grund's avatar
Daniel Grund committed
61

62
typedef struct local_env_t {
63
64
65
	int             first_x_var;
	int             last_x_var;
	const unsigned *allocatable_colors;
Daniel Grund's avatar
Daniel Grund committed
66
} local_env_t;
Daniel Grund's avatar
Daniel Grund committed
67

68
69
70
71
72
73
74
75
76
77
78
static unsigned check_alignment_constraints(ir_node *node)
{
	const arch_register_req_t *req = arch_get_irn_register_req(node);
	// For larger than 1 variables, support only aligned constraints
	assert(((!(req->type & arch_register_req_type_aligned)
			 && req->width == 1)
			|| (req->type & arch_register_req_type_aligned))
		   && "Unaligned large (width > 1) variables not supported");
	return (req->type & arch_register_req_type_aligned) && req->width > 1;
}

Matthias Braun's avatar
Matthias Braun committed
79
80
81
82
83
84
85
static void make_color_var_name(char *buf, size_t buf_size,
                                const ir_node *node, unsigned color)
{
	unsigned node_idx = get_irn_idx(node);
	snprintf(buf, buf_size, "x_%u_%u", node_idx, color);
}

86
87
static void build_coloring_cstr(ilp_env_t *ienv)
{
88
	local_env_t    *lenv   = (local_env_t*)ienv->env;
89
90
91
92
93
94
95
	be_ifg_t       *ifg    = ienv->co->cenv->ifg;
	unsigned        n_regs = arch_register_class_n_regs(ienv->co->cls);
	const unsigned *allocatable_colors = lenv->allocatable_colors;
	nodes_iter_t    iter;
	unsigned       *colors;
	ir_node        *irn;
	char            buf[32];
Daniel Grund's avatar
Daniel Grund committed
96

Matthias Braun's avatar
Matthias Braun committed
97
	rbitset_alloca(colors, n_regs);
Daniel Grund's avatar
Daniel Grund committed
98

Matthias Braun's avatar
Matthias Braun committed
99
100
101
102
103
	be_ifg_foreach_node(ifg, &iter, irn) {
		const arch_register_req_t *req;
		unsigned                   col;
		int                        cst_idx;
		unsigned                   curr_node_color;
104
		unsigned                   has_alignment_cstr;
Daniel Grund's avatar
Daniel Grund committed
105

Matthias Braun's avatar
Matthias Braun committed
106
107
		if (sr_is_removed(ienv->sr, irn))
			continue;
Daniel Grund's avatar
Daniel Grund committed
108

109
110
		has_alignment_cstr = check_alignment_constraints(irn);

Matthias Braun's avatar
Matthias Braun committed
111
		req = arch_get_irn_register_req(irn);
Daniel Grund's avatar
Daniel Grund committed
112

Matthias Braun's avatar
Matthias Braun committed
113
114
115
116
		/* get assignable colors */
		if (arch_register_req_is(req, limited)) {
			rbitset_copy(colors, req->limited, n_regs);
		} else {
117
			rbitset_copy(colors, allocatable_colors, n_regs);
Matthias Braun's avatar
Matthias Braun committed
118
		}
Sebastian Hack's avatar
Sebastian Hack committed
119

Matthias Braun's avatar
Matthias Braun committed
120
121
		/* add the coloring constraint */
		cst_idx = lpp_add_cst(ienv->lp, NULL, lpp_equal, 1.0);
Daniel Grund's avatar
Daniel Grund committed
122

Matthias Braun's avatar
Matthias Braun committed
123
124
125
126
		curr_node_color = get_irn_col(irn);
		for (col = 0; col < n_regs; ++col) {
			int    var_idx;
			double val;
127
128
			if (!rbitset_is_set(colors, col)
				|| (has_alignment_cstr && ((col % req->width) != 0)))
Matthias Braun's avatar
Matthias Braun committed
129
				continue;
Daniel Grund's avatar
Daniel Grund committed
130

Matthias Braun's avatar
Matthias Braun committed
131
132
133
			make_color_var_name(buf, sizeof(buf), irn, col);
			var_idx = lpp_add_var(ienv->lp, buf, lpp_binary, 0.0);
			lpp_set_factor_fast(ienv->lp, cst_idx, var_idx, 1);
Daniel Grund's avatar
Daniel Grund committed
134

Matthias Braun's avatar
Matthias Braun committed
135
136
			val = (col == curr_node_color) ? 1.0 : 0.0;
			lpp_set_start_value(ienv->lp, var_idx, val);
Daniel Grund's avatar
Daniel Grund committed
137

Matthias Braun's avatar
Matthias Braun committed
138
139
140
141
			lenv->last_x_var = var_idx;
			if (lenv->first_x_var == -1)
				lenv->first_x_var = var_idx;
		}
Daniel Grund's avatar
Daniel Grund committed
142

Matthias Braun's avatar
Matthias Braun committed
143
144
145
146
		/* add register constraint constraints */
		for (col = 0; col < n_regs; ++col) {
			int cst_idx;
			int var_idx;
147
148
149
			if (rbitset_is_set(colors, col)
				// for aligned variable, we set the unaligned part to 0
				&& (!has_alignment_cstr || ((col % req->width) == 0)))
Matthias Braun's avatar
Matthias Braun committed
150
151
152
153
154
155
156
157
158
				continue;

			make_color_var_name(buf, sizeof(buf), irn, col);
			cst_idx = lpp_add_cst(ienv->lp, NULL, lpp_equal, 0.0);
			var_idx = lpp_add_var(ienv->lp, buf, lpp_binary, 0.0);
			lpp_set_start_value(ienv->lp, var_idx, 0.0);
			lpp_set_factor_fast(ienv->lp, cst_idx, var_idx, 1);

			lenv->last_x_var = var_idx;
Daniel Grund's avatar
Daniel Grund committed
159
		}
Matthias Braun's avatar
Matthias Braun committed
160
	}
Daniel Grund's avatar
Daniel Grund committed
161
162
}

163
164
static void build_interference_cstr(ilp_env_t *ienv)
{
165
	lpp_t          *lpp      = ienv->lp;
166
	local_env_t    *lenv     = (local_env_t*)ienv->env;
167
168
169
170
	be_ifg_t       *ifg      = ienv->co->cenv->ifg;
	unsigned        n_colors = arch_register_class_n_regs(ienv->co->cls);
	ir_node       **clique   = ALLOCAN(ir_node*, n_colors);
	const unsigned *allocatable_colors = lenv->allocatable_colors;
171
	cliques_iter_t iter;
Matthias Braun's avatar
Matthias Braun committed
172
173
174
	int            size;
	unsigned       col;
	int            i;
Daniel Grund's avatar
Daniel Grund committed
175
176

	/* for each maximal clique */
177
	be_ifg_foreach_clique(ifg, &iter, clique, &size) {
Matthias Braun's avatar
Matthias Braun committed
178
		unsigned realsize = 0;
179

Matthias Braun's avatar
Matthias Braun committed
180
		for (i=0; i<size; ++i) {
181
182
			if (!sr_is_removed(ienv->sr, clique[i]))
				++realsize;
Matthias Braun's avatar
Matthias Braun committed
183
		}
Daniel Grund's avatar
Daniel Grund committed
184

185
		if (realsize < 2)
Daniel Grund's avatar
Daniel Grund committed
186
187
188
189
			continue;

		/* for all colors */
		for (col=0; col<n_colors; ++col) {
190
191
192
193
194
			int cst_idx;
			if (!rbitset_is_set(allocatable_colors, col))
				continue;

			cst_idx = lpp_add_cst(lpp, NULL, lpp_less_equal, 1.0);
Daniel Grund's avatar
Daniel Grund committed
195
196

			/* for each member of this clique */
Daniel Grund's avatar
Fixes    
Daniel Grund committed
197
			for (i=0; i<size; ++i) {
Daniel Grund's avatar
Daniel Grund committed
198
				ir_node *irn = clique[i];
Matthias Braun's avatar
Matthias Braun committed
199
200
				char     buf[32];
				int      var_idx;
201
				unsigned aligment_offset = 0;
Daniel Grund's avatar
Daniel Grund committed
202

Matthias Braun's avatar
Matthias Braun committed
203
204
205
				if (sr_is_removed(ienv->sr, irn))
					continue;

206
207
208
209
210
211
212
213
214
215
				// Use the first part of the large registers for all
				// interference, since it is the only colorable one.
				if (check_alignment_constraints(irn)) {
					const arch_register_req_t *req
						= arch_get_irn_register_req(irn);
					aligment_offset = col % req->width;
				}

				make_color_var_name(buf, sizeof(buf), irn,
									col - aligment_offset);
Matthias Braun's avatar
Matthias Braun committed
216
217
				var_idx = lpp_get_var_idx(lpp, buf);
				lpp_set_factor_fast(lpp, cst_idx, var_idx, 1);
Daniel Grund's avatar
Daniel Grund committed
218
219
220
221
222
			}
		}
	}
}

Matthias Braun's avatar
Matthias Braun committed
223
224
225
226
227
228
229
230
231
232
233
234
static void make_affinity_var_name(char *buf, size_t buf_size,
                                   const ir_node *node1, const ir_node *node2)
{
	unsigned n1 = get_irn_idx(node1);
	unsigned n2 = get_irn_idx(node2);
	if (n1 < n2) {
		snprintf(buf, buf_size, "y_%u_%u", n1, n2);
	} else {
		snprintf(buf, buf_size, "y_%u_%u", n2, n1);
	}
}

Daniel Grund's avatar
Daniel Grund committed
235
236
237
238
239
240

/**
 * TODO: Remove the dependency of the opt-units data structure
 *       by walking over all affinity edges. Graph structure
 *       does not provide this walker, yet.
 */
241
242
static void build_affinity_cstr(ilp_env_t *ienv)
{
243
	unsigned  n_colors = arch_register_class_n_regs(ienv->co->cls);
Daniel Grund's avatar
Daniel Grund committed
244
245
246

	/* for all optimization units */
	list_for_each_entry(unit_t, curr, &ienv->co->units, units) {
Matthias Braun's avatar
Matthias Braun committed
247
248
249
		ir_node *root     = curr->nodes[0];
		unsigned root_col = get_irn_col(root);
		int      i;
Daniel Grund's avatar
Daniel Grund committed
250
251

		for (i = 1; i < curr->node_count; ++i) {
Matthias Braun's avatar
Matthias Braun committed
252
253
254
255
256
257
			ir_node *arg     = curr->nodes[i];
			unsigned arg_col = get_irn_col(arg);
			double   val;
			char     buf[32];
			unsigned col;
			int      y_idx;
Daniel Grund's avatar
Daniel Grund committed
258
259

			/* add a new affinity variable */
Matthias Braun's avatar
Matthias Braun committed
260
261
262
263
			make_affinity_var_name(buf, sizeof(buf), arg, root);
			y_idx = lpp_add_var(ienv->lp, buf, lpp_binary, curr->costs[i]);
			val   = (root_col == arg_col) ? 0.0 : 1.0;
			lpp_set_start_value(ienv->lp, y_idx, val);
Daniel Grund's avatar
Daniel Grund committed
264
265
266

			/* add constraints relating the affinity var to the color vars */
			for (col=0; col<n_colors; ++col) {
267
				int cst_idx = lpp_add_cst(ienv->lp, NULL, lpp_less_equal, 0.0);
Matthias Braun's avatar
Matthias Braun committed
268
269
270
271
272
273
274
				int root_idx;
				int arg_idx;

				make_color_var_name(buf, sizeof(buf), root, col);
				root_idx = lpp_get_var_idx(ienv->lp, buf);
				make_color_var_name(buf, sizeof(buf), arg, col);
				arg_idx  = lpp_get_var_idx(ienv->lp, buf);
Daniel Grund's avatar
Daniel Grund committed
275
276
277

				lpp_set_factor_fast(ienv->lp, cst_idx, root_idx,  1.0);
				lpp_set_factor_fast(ienv->lp, cst_idx, arg_idx,  -1.0);
278
				lpp_set_factor_fast(ienv->lp, cst_idx, y_idx, -1.0);
Daniel Grund's avatar
Daniel Grund committed
279
280
281
282
283
			}
		}
	}
}

Daniel Grund's avatar
Daniel Grund committed
284
/**
285
286
 * Helping stuff for build_clique_star_cstr
 */
287
typedef struct edge_t {
Matthias Braun's avatar
Matthias Braun committed
288
289
	ir_node *n1;
	ir_node *n2;
290
291
} edge_t;

292
293
static int compare_edge_t(const void *k1, const void *k2, size_t size)
{
294
295
	const edge_t *e1 = (const edge_t*)k1;
	const edge_t *e2 = (const edge_t*)k2;
296
	(void) size;
297

Matthias Braun's avatar
Matthias Braun committed
298
	return ! (e1->n1 == e2->n1 && e1->n2 == e2->n2);
299
300
}

301
#define HASH_EDGE(e) (hash_irn((e)->n1) ^ hash_irn((e)->n2))
302

Matthias Braun's avatar
Matthias Braun committed
303
static inline edge_t *add_edge(set *edges, ir_node *n1, ir_node *n2, size_t *counter)
304
{
305
306
307
308
309
310
311
312
313
	edge_t new_edge;

	if (PTR_TO_INT(n1) < PTR_TO_INT(n2)) {
		new_edge.n1 = n1;
		new_edge.n2 = n2;
	} else {
		new_edge.n1 = n2;
		new_edge.n2 = n1;
	}
314
	(*counter)++;
315
	return set_insert(edge_t, edges, &new_edge, sizeof(new_edge), HASH_EDGE(&new_edge));
316
317
}

318
319
static inline edge_t *find_edge(set *edges, ir_node *n1, ir_node *n2)
{
320
321
322
323
324
325
326
327
328
	edge_t new_edge;

	if (PTR_TO_INT(n1) < PTR_TO_INT(n2)) {
		new_edge.n1 = n1;
		new_edge.n2 = n2;
	} else {
		new_edge.n1 = n2;
		new_edge.n2 = n1;
	}
329
	return set_find(edge_t, edges, &new_edge, sizeof(new_edge), HASH_EDGE(&new_edge));
330
331
}

Matthias Braun's avatar
Matthias Braun committed
332
static inline void remove_edge(set *edges, ir_node *n1, ir_node *n2, size_t *counter)
333
{
334
335
336
337
338
339
340
341
342
	edge_t new_edge, *e;

	if (PTR_TO_INT(n1) < PTR_TO_INT(n2)) {
		new_edge.n1 = n1;
		new_edge.n2 = n2;
	} else {
		new_edge.n1 = n2;
		new_edge.n2 = n1;
	}
343
	e = set_find(edge_t, edges, &new_edge, sizeof(new_edge), HASH_EDGE(&new_edge));
344
345
346
	if (e) {
		e->n1 = NULL;
		e->n2 = NULL;
347
		(*counter)--;
348
349
350
	}
}

351
#define pset_foreach(pset, irn) foreach_pset((pset), ir_node, (irn))
352
353
354
355
356

/**
 * Search for an interference clique and an external node
 * with affinity edges to all nodes of the clique.
 * At most 1 node of the clique can be colored equally with the external node.
Daniel Grund's avatar
Daniel Grund committed
357
 */
358
359
static void build_clique_star_cstr(ilp_env_t *ienv)
{
360
	/* for each node with affinity edges */
361
	co_gs_foreach_aff_node(ienv->co, aff) {
362
		struct obstack ob;
363
		const ir_node *center = aff->irn;
364
365
		ir_node **nodes;
		set *edges;
Matthias Braun's avatar
Matthias Braun committed
366
367
		int i, o, n_nodes;
		size_t n_edges;
368

369
		if (arch_irn_is_ignore(aff->irn))
Sebastian Hack's avatar
Sebastian Hack committed
370
371
			continue;

372
373
374
375
376
		obstack_init(&ob);
		edges = new_set(compare_edge_t, 8);

		/* get all affinity neighbours */
		n_nodes = 0;
377
		co_gs_foreach_neighb(aff, nbr) {
378
			if (!arch_irn_is_ignore(nbr->irn)) {
Sebastian Hack's avatar
Sebastian Hack committed
379
380
381
				obstack_ptr_grow(&ob, nbr->irn);
				++n_nodes;
			}
382
		}
383
		nodes = (ir_node**)obstack_finish(&ob);
384
385
386

		/* get all interference edges between these */
		n_edges = 0;
Matthias Braun's avatar
Matthias Braun committed
387
388
		for (i=0; i<n_nodes; ++i) {
			for (o=0; o<i; ++o) {
389
390
				if (be_ifg_connected(ienv->co->cenv->ifg, nodes[i], nodes[o]))
					add_edge(edges, nodes[i], nodes[o], &n_edges);
Matthias Braun's avatar
Matthias Braun committed
391
392
			}
		}
393
394
395
396

		/* cover all these interference edges with maximal cliques */
		while (n_edges) {
			edge_t *e;
Matthias Braun's avatar
Matthias Braun committed
397
398
			pset   *clique = pset_new_ptr(8);
			bool    growed;
399
400

			/* get 2 starting nodes to form a clique */
401
			for (e = set_first(edge_t, edges); !e->n1; e = set_next(edge_t, edges)) {}
402

Sebastian Hack's avatar
Sebastian Hack committed
403
404
405
			/* we could be stepped out of the loop before the set iterated to the end */
			set_break(edges);

406
407
			pset_insert_ptr(clique, e->n1);
			pset_insert_ptr(clique, e->n2);
408
			remove_edge(edges, e->n1, e->n2, &n_edges);
409
410
411

			/* while the clique is growing */
			do {
Matthias Braun's avatar
Matthias Braun committed
412
				growed = false;
413
414
415

				/* search for a candidate to extend the clique */
				for (i=0; i<n_nodes; ++i) {
Matthias Braun's avatar
Matthias Braun committed
416
417
					ir_node *cand = nodes[i];
					bool     is_cand;
418
419
420
421
422
423

					/* if its already in the clique try the next */
					if (pset_find_ptr(clique, cand))
						continue;

					/* are there all necessary interferences? */
Matthias Braun's avatar
Matthias Braun committed
424
					is_cand = true;
425
426
					pset_foreach(clique, member) {
						if (!find_edge(edges, cand, member)) {
Matthias Braun's avatar
Matthias Braun committed
427
							is_cand = false;
428
429
430
431
432
433
434
435
436
437
438
439
440
							pset_break(clique);
							break;
						}
					}

					/* now we know if we have a clique extender */
					if (is_cand) {
						/* first remove all covered edges */
						pset_foreach(clique, member)
							remove_edge(edges, cand, member, &n_edges);

						/* insert into clique */
						pset_insert_ptr(clique, cand);
Matthias Braun's avatar
Matthias Braun committed
441
						growed = true;
442
443
444
445
						break;
					}
				}
			} while (growed);
Daniel Grund's avatar
Daniel Grund committed
446

447
448
			/* now the clique is maximal. Finally add the constraint */
			{
449
450
451
				int  var_idx;
				int  cst_idx;
				char buf[32];
452

453
				cst_idx = lpp_add_cst(ienv->lp, NULL, lpp_greater_equal, pset_count(clique)-1);
454
455

				pset_foreach(clique, member) {
Matthias Braun's avatar
Matthias Braun committed
456
457
					make_affinity_var_name(buf, sizeof(buf), center, member);
					var_idx = lpp_get_var_idx(ienv->lp, buf);
458
459
460
461
462
463
464
465
466
467
					lpp_set_factor_fast(ienv->lp, cst_idx, var_idx, 1.0);
				}
			}

			del_pset(clique);
		}

		del_set(edges);
		obstack_free(&ob, NULL);
	}
Daniel Grund's avatar
Daniel Grund committed
468
469
}

470
471
static void extend_path(ilp_env_t *ienv, pdeq *path, const ir_node *irn)
{
472
473
474
	be_ifg_t *ifg = ienv->co->cenv->ifg;
	int i, len;
	ir_node **curr_path;
Daniel Grund's avatar
Daniel Grund committed
475
	affinity_node_t *aff;
476
477
478
479
480

	/* do not walk backwards or in circles */
	if (pdeq_contains(path, irn))
		return;

481
	if (arch_irn_is_ignore(irn))
Sebastian Hack's avatar
Sebastian Hack committed
482
483
		return;

484
485
486
487
	/* insert the new irn */
	pdeq_putr(path, irn);

	/* check for forbidden interferences */
488
489
	len       = pdeq_len(path);
	curr_path = ALLOCAN(ir_node*, len);
Christian Würdig's avatar
Christian Würdig committed
490
	pdeq_copyl(path, (const void **)curr_path);
491

Matthias Braun's avatar
Matthias Braun committed
492
	for (i=1; i<len; ++i) {
493
494
		if (be_ifg_connected(ifg, irn, curr_path[i]))
			goto end;
Matthias Braun's avatar
Matthias Braun committed
495
	}
496
497
498
499
500
501
502

	/* check for terminating interference */
	if (be_ifg_connected(ifg, irn, curr_path[0])) {
		/* One node is not a path. */
		/* And a path of length 2 is covered by a clique star constraint. */
		if (len > 2) {
			/* finally build the constraint */
503
			int cst_idx = lpp_add_cst(ienv->lp, NULL, lpp_greater_equal, 1.0);
504
			for (i=1; i<len; ++i) {
Matthias Braun's avatar
Matthias Braun committed
505
506
507
508
509
				char buf[32];
				int  var_idx;

				make_affinity_var_name(buf, sizeof(buf), curr_path[i-1], curr_path[i]);
				var_idx = lpp_get_var_idx(ienv->lp, buf);
510
511
512
513
514
515
516
517
518
519
				lpp_set_factor_fast(ienv->lp, cst_idx, var_idx, 1.0);
			}
		}

		/* this path cannot be extended anymore */
		goto end;
	}

	/* recursively extend the path */
	aff = get_affinity_info(ienv->co, irn);
Matthias Braun's avatar
Matthias Braun committed
520
	co_gs_foreach_neighb(aff, nbr) {
521
		extend_path(ienv, path, nbr->irn);
Matthias Braun's avatar
Matthias Braun committed
522
	}
523
524
525
526
527
528

end:
	/* remove the irn */
	pdeq_getr(path);
}

Daniel Grund's avatar
Daniel Grund committed
529
/**
530
531
532
533
 * Search a path of affinity edges, whose ends are connected
 * by an interference edge and there are no other interference
 * edges in between.
 * Then at least one of these affinity edges must break.
Daniel Grund's avatar
Daniel Grund committed
534
 */
535
536
static void build_path_cstr(ilp_env_t *ienv)
{
537
538
539
	/* for each node with affinity edges */
	co_gs_foreach_aff_node(ienv->co, aff_info) {
		pdeq *path = new_pdeq();
Daniel Grund's avatar
Daniel Grund committed
540

541
542
543
544
		extend_path(ienv, path, aff_info->irn);

		del_pdeq(path);
	}
Daniel Grund's avatar
Daniel Grund committed
545
}
Daniel Grund's avatar
Daniel Grund committed
546

547
548
static void ilp2_build(ilp_env_t *ienv)
{
Daniel Grund's avatar
Daniel Grund committed
549
550
	int lower_bound;

551
	ienv->lp = lpp_new(ienv->co->name, lpp_minimize);
Daniel Grund's avatar
Daniel Grund committed
552
553
554
	build_coloring_cstr(ienv);
	build_interference_cstr(ienv);
	build_affinity_cstr(ienv);
Daniel Grund's avatar
Daniel Grund committed
555
	build_clique_star_cstr(ienv);
Daniel Grund's avatar
Daniel Grund committed
556
	build_path_cstr(ienv);
Daniel Grund's avatar
Daniel Grund committed
557

Daniel Grund's avatar
Daniel Grund committed
558
559
	lower_bound = co_get_lower_bound(ienv->co) - co_get_inevit_copy_costs(ienv->co);
	lpp_set_bound(ienv->lp, lower_bound);
Daniel Grund's avatar
Daniel Grund committed
560
561
}

562
563
static void ilp2_apply(ilp_env_t *ienv)
{
564
	local_env_t *lenv = (local_env_t*)ienv->env;
Matthias Braun's avatar
Matthias Braun committed
565
	ir_graph    *irg  = ienv->co->irg;
Daniel Grund's avatar
Daniel Grund committed
566

567
568
	/* first check if there was sth. to optimize */
	if (lenv->first_x_var >= 0) {
569
570
571
		int              count = lenv->last_x_var - lenv->first_x_var + 1;
		double          *sol   = XMALLOCN(double, count);
		lpp_sol_state_t  state = lpp_get_solution(ienv->lp, sol, lenv->first_x_var, lenv->last_x_var);
Matthias Braun's avatar
Matthias Braun committed
572
		int              i;
573
574

		if (state != lpp_optimal) {
575
576
577
578
579
			printf("WARNING %s: Solution state is not 'optimal': %d\n",
			       ienv->co->name, (int)state);
			if (state < lpp_feasible) {
				panic("Copy coalescing solution not feasible!");
			}
580
		}
Daniel Grund's avatar
Daniel Grund committed
581

582
		for (i=0; i<count; ++i) {
Matthias Braun's avatar
Matthias Braun committed
583
584
585
586
587
588
589
590
591
592
593
594
595
			unsigned nodenr;
			unsigned color;
			char     var_name[32];
			if (sol[i] <= 1-EPSILON)
				continue;
			/* split variable name into components */
			lpp_get_var_name(ienv->lp, lenv->first_x_var+i, var_name, sizeof(var_name));

			if (sscanf(var_name, "x_%u_%u", &nodenr, &color) == 2) {
				ir_node *irn = get_idx_irn(irg, nodenr);
				set_irn_col(ienv->co->cls, irn, color);
			} else {
				panic("This should be a x-var");
596
			}
Daniel Grund's avatar
Daniel Grund committed
597
		}
Christoph Mallon's avatar
Christoph Mallon committed
598
599

		xfree(sol);
Daniel Grund's avatar
Daniel Grund committed
600
601
602
603
604
605
606
607
608
	}

#ifdef COPYOPT_STAT
	/* TODO adapt to multiple possible ILPs */
	copystat_add_ilp_time((int)(1000.0*lpp_get_sol_time(pi->curr_lp)));  //now we have ms
	copystat_add_ilp_vars(lpp_get_var_count(pi->curr_lp));
	copystat_add_ilp_csts(lpp_get_cst_count(pi->curr_lp));
	copystat_add_ilp_iter(lpp_get_iter_cnt(pi->curr_lp));
#endif
Daniel Grund's avatar
Daniel Grund committed
609
610
}

611
612
613
614
615
616
617
/**
 * Solves the problem using mixed integer programming
 * @returns 1 iff solution state was optimal
 * Uses the OU and the GRAPH data structure
 * Dependency of the OU structure can be removed
 */
static int co_solve_ilp2(copy_opt_t *co)
618
{
619
	unsigned       *allocatable_colors;
Matthias Braun's avatar
Matthias Braun committed
620
	unsigned        n_regs = arch_register_class_n_regs(co->cls);
Daniel Grund's avatar
Daniel Grund committed
621
	lpp_sol_state_t sol_state;
Matthias Braun's avatar
Matthias Braun committed
622
623
	ilp_env_t      *ienv;
	local_env_t     my;
Daniel Grund's avatar
Daniel Grund committed
624

Daniel Grund's avatar
Daniel Grund committed
625
626
627
	ASSERT_OU_AVAIL(co); //See build_clique_st
	ASSERT_GS_AVAIL(co);

Daniel Grund's avatar
Daniel Grund committed
628
629
	my.first_x_var = -1;
	my.last_x_var  = -1;
Matthias Braun's avatar
Matthias Braun committed
630
	FIRM_DBG_REGISTER(dbg, "firm.be.coilp2");
Daniel Grund's avatar
Daniel Grund committed
631

632
633
634
	rbitset_alloca(allocatable_colors, n_regs);
	be_set_allocatable_regs(co->irg, co->cls, allocatable_colors);
	my.allocatable_colors = allocatable_colors;
Sebastian Hack's avatar
Sebastian Hack committed
635

Daniel Grund's avatar
Daniel Grund committed
636
	ienv = new_ilp_env(co, ilp2_build, ilp2_apply, &my);
Daniel Grund's avatar
Daniel Grund committed
637

Daniel Grund's avatar
Daniel Grund committed
638
	sol_state = ilp_go(ienv);
Daniel Grund's avatar
Daniel Grund committed
639
640

	free_ilp_env(ienv);
641

Daniel Grund's avatar
Daniel Grund committed
642
	return sol_state == lpp_optimal;
643
}
644
645
646
647
648
649
650
651
652
653

BE_REGISTER_MODULE_CONSTRUCTOR(be_init_copyilp2)
void be_init_copyilp2(void)
{
	static co_algo_info copyheur = {
		co_solve_ilp2, 1
	};

	be_register_copyopt("ilp", &copyheur);
}