Commit a74dd232 authored by Sebastian Hack's avatar Sebastian Hack
Browse files

Moved to new lpp library

Moved to new libcore
parent 8ad8020b
......@@ -26,7 +26,7 @@ SOURCES += Makefile.in besched.h belistsched.h belistsched.c \
becopyoptmain.c becopyopt.c becopyheur.c \
becopyilp.c becopystat.c bearch_firm.c bearch.c bechordal_draw.c \
bechordal_draw.h beirgmod.c beirgmod.h benode.c benode_t.h \
bessadestr.c beifg.c bedupl.c bedupl.h
bessadestr.c beifg.c bedupl.c
include $(topdir)/MakeRules
......
......@@ -43,7 +43,7 @@ arch_env_t *arch_env_add_irn_handler(arch_env_t *env,
static const arch_irn_ops_t *fallback_irn_ops = NULL;
int arch_register_class_put(const arch_register_class_t *cls, struct _bitset_t *bs)
int arch_register_class_put(const arch_register_class_t *cls, bitset_t *bs)
{
if(bs) {
int i, n;
......
......@@ -7,14 +7,13 @@
#include "irnode.h"
#include "irmode.h"
#include "bitset.h"
#include "hashptr.h"
#include "fourcc.h"
#include "set.h"
#include "list.h"
#include "ident.h"
struct _bitset_t;
typedef struct _arch_register_class_t arch_register_class_t;
typedef struct _arch_register_t arch_register_t;
typedef struct _arch_enum_t arch_enum_t;
......@@ -81,8 +80,7 @@ struct _arch_register_class_t {
* @param bs The bitset. May be NULL.
* @return The number of registers in the class.
*/
extern int arch_register_class_put(const arch_register_class_t *cls,
struct _bitset_t *bs);
extern int arch_register_class_put(const arch_register_class_t *cls, bitset_t *bs);
static INLINE const arch_register_t *
_arch_register_for_index(const arch_register_class_t *cls, int idx)
......@@ -170,7 +168,7 @@ typedef struct _arch_register_req_t {
const arch_register_class_t *cls; /** The register class this
constraint belongs to. */
union {
int (*limited)(const ir_node *irn, int pos, struct _bitset_t *bs);
int (*limited)(const ir_node *irn, int pos, bitset_t *bs);
/** In case of the 'limited'
constraint, this function
must put all allowable
......@@ -348,7 +346,7 @@ extern int arch_is_register_operand(const arch_env_t *env,
* @return The amount of registers allocatable for that operand.
*/
extern int arch_get_allocatable_regs(const arch_env_t *env, const ir_node *irn,
int pos, const arch_register_class_t *cls, struct _bitset_t *bs);
int pos, const arch_register_class_t *cls, bitset_t *bs);
/**
* Check, if a register is assignable to an operand of a node.
......
......@@ -13,7 +13,7 @@
#include "irreflect.h"
#define N_REGS 64
#define N_REGS 4
static arch_register_t datab_regs[N_REGS];
......
......@@ -153,9 +153,21 @@ static void be_main_loop(void)
be_liveness(irg);
dump_ir_block_graph_sched(irg, "-sched");
copystat_reset();
copystat_collect_irg(irg, env.arch_env);
/*
* Spilling changed the liveness information.
* Recompute it now.
*/
be_liveness(irg);
/*
* Verifying the schedule once again cannot hurt.
*/
sched_verify_irg(irg);
/* Perform the following for each register class. */
for(j = 0, m = isa->get_n_reg_class(); j < m; ++j) {
be_chordal_env_t *chordal_env;
......@@ -176,8 +188,9 @@ static void be_main_loop(void)
be_ra_chordal_done(chordal_env);
}
copystat_dump_pretty(irg);
be_numbering_done(irg);
be_numbering_done(irg);
}
}
......
/**
* Author: Daniel Grund
* Date: Fri 13.05.2005
* Copyright: (c) Universitaet Karlsruhe
* Licence: This file protected by GPL - GNU GENERAL PUBLIC LICENSE.
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#ifdef HAVE_IO_H
#include <io.h>
#endif
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "xmalloc.h"
#include "debug.h"
#include "assert.h"
#include "hashptr.h"
#include "mps.h"
#include "lpp.h"
#define DEBUG_LVL SET_LEVEL_1
static firm_dbg_module_t *dbg = NULL;
#define HASH_NAME_T(n) HASH_STR((n)->name, strlen((n)->name))
static int cmp_name_t(const void *x, const void *y, size_t size) {
const name_t *n = x;
const name_t *m = y;
return strcmp(n->name, m->name);
}
#define INITIAL_SIZE 64
lpp_t *new_lpp(const char *name, opt_t opt_type) {
lpp_t *lpp;
dbg = firm_dbg_register("ir.be.lpp");
firm_dbg_set_mask(dbg, DEBUG_LVL);
lpp = xcalloc(1, sizeof(*lpp));
lpp->name = xstrdup(name);
lpp->opt_type = opt_type;
lpp->cst2nr = new_set(cmp_name_t, INITIAL_SIZE);
lpp->var2nr = new_set(cmp_name_t, INITIAL_SIZE);
lpp->cst_size = INITIAL_SIZE;
lpp->var_size = INITIAL_SIZE;
lpp->csts = xcalloc(INITIAL_SIZE, sizeof(*lpp->csts));
lpp->vars = xcalloc(INITIAL_SIZE, sizeof(*lpp->vars));
lpp->m = new_matrix(INITIAL_SIZE, INITIAL_SIZE);
lpp_add_cst(lpp, "obj", objective, 0);
lpp_add_var(lpp, "rhs", rhs, 0);
return lpp;
}
void free_lpp(lpp_t *lpp) {
int i;
for(i=0;i<lpp->cst_next;++i)
free(lpp->csts[i]->name);
for(i=0;i<lpp->var_next;++i)
free(lpp->vars[i]->name);
del_set(lpp->cst2nr);
del_set(lpp->var2nr);
del_matrix(lpp->m);
free(lpp->name);
free(lpp->csts);
free(lpp->vars);
if (lpp->error)
free(lpp->error);
free(lpp);
}
static INLINE int name2nr(set *where, char *name) {
name_t find, *found;
find.name = name;
found = set_find(where, &find, sizeof(find), HASH_NAME_T(&find));
return (found ? found->nr : -1);
}
#define cst_nr(lpp, name) name2nr(lpp->cst2nr, name)
#define var_nr(lpp, name) name2nr(lpp->var2nr, name)
static INLINE char *get_next_name(lpp_t *lpp) {
char *res = xmalloc(12);
snprintf(res, 12, "_%d", lpp->next_name_number++);
return res;
}
int lpp_add_cst(lpp_t *lpp, char *cst_name, cst_t cst_type, double rhs) {
name_t n, *inner;
DBG((dbg, LEVEL_2, "%s %d %g\n", cst_name, cst_type, rhs));
if (cst_name && cst_name[0] == '_')
return ERR_NAME_NOT_ALLOWED;
if (cst_name)
n.name = xstrdup(cst_name);
else
n.name = get_next_name(lpp);
n.nr = -1;
inner = set_insert(lpp->cst2nr, &n, sizeof(n), HASH_NAME_T(&n));
assert(inner);
if (inner->nr == -1) {
inner->nr = lpp->cst_next;
inner->type.cst_type = cst_type;
if (lpp->cst_next == lpp->cst_size) {
lpp->cst_size *= 2;
lpp->csts = xrealloc(lpp->csts, lpp->cst_size * sizeof(*lpp->csts));
}
lpp->csts[lpp->cst_next] = inner;
lpp->cst_next++;
matrix_set(lpp->m, inner->nr, 0, rhs);
}
return inner->nr;
}
int lpp_get_cst_idx(lpp_t *lpp, char *cst_name) {
DBG((dbg, LEVEL_2, "%s --> %d\n", cst_name, cst_nr(lpp, cst_name)));
return cst_nr(lpp, cst_name);
}
void lpp_get_cst_name(lpp_t *lpp, int index, char *buf, size_t buf_size) {
DBG((dbg, LEVEL_2, "%d --> %s\n", index, lpp->csts[index]->name));
strncpy(buf, lpp->csts[index]->name, buf_size);
}
int lpp_add_var(lpp_t *lpp, char *var_name, var_t var_type, double obj) {
name_t n, *inner;
DBG((dbg, LEVEL_2, "%s %d %g\n", var_name, var_type, obj));
assert(var_type != invalid && "invalid is for internal use only");
if (var_name && var_name[0] == '_')
return ERR_NAME_NOT_ALLOWED;
if (var_name)
n.name = xstrdup(var_name);
else
n.name = get_next_name(lpp);
n.nr = -1;
inner = set_insert(lpp->var2nr, &n, sizeof(n), HASH_NAME_T(&n));
assert(inner);
if (inner->nr == -1) {
inner->nr = lpp->var_next;
inner->value_kind = 0;
inner->value = 0;
inner->type.var_type = var_type;
if (lpp->var_next == lpp->var_size) {
lpp->var_size *= 2;
lpp->vars = xrealloc(lpp->vars, lpp->var_size * sizeof(*lpp->vars));
}
lpp->vars[lpp->var_next] = inner;
lpp->var_next++;
matrix_set(lpp->m, 0, inner->nr, obj);
}
return inner->nr;
}
int lpp_get_var_idx(lpp_t *lpp, char *var_name) {
DBG((dbg, LEVEL_2, "%s --> %d\n", var_name, var_nr(lpp, var_name)));
return var_nr(lpp, var_name);
}
void lpp_get_var_name(lpp_t *lpp, int index, char *buf, size_t buf_size) {
DBG((dbg, LEVEL_2, "%d --> %s\n", index, lpp->vars[index]->name));
strncpy(buf, lpp->vars[index]->name, buf_size);
}
int lpp_set_factor(lpp_t *lpp, char *cst_name, char *var_name, double value) {
int cst, var;
cst = cst_nr(lpp, cst_name);
var = var_nr(lpp, var_name);
assert(cst != -1 && var != -1);
DBG((dbg, LEVEL_2, "%s[%d] %s[%d] %g\n", cst_name, cst, var_name, var, value));
matrix_set(lpp->m, cst, var, value);
return 0;
}
int lpp_set_factor_fast(lpp_t *lpp, int cst_idx, int var_idx, double value) {
assert(cst_idx >= 0 && var_idx >= 0);
assert(cst_idx < lpp->cst_next && var_idx < lpp->var_next);
DBG((dbg, LEVEL_2, "%s[%d] %s[%d] %g\n", lpp->csts[cst_idx]->name, cst_idx, lpp->vars[var_idx]->name, var_idx, value));
matrix_set(lpp->m, cst_idx, var_idx, value);
return 0;
}
void lpp_set_start_value(lpp_t *lpp, int var_idx, double value) {
assert(var_idx > 0 && var_idx < lpp->var_next);
DBG((dbg, LEVEL_2, "%d %s %g\n", var_idx, lpp->vars[var_idx]->name, value));
lpp->vars[var_idx]->value = value;
lpp->vars[var_idx]->value_kind = value_start;
}
sol_state_t lpp_get_solution(lpp_t *lpp, double *values, int begin, int end) {
int i;
if (lpp->sol_state < feasible)
return lpp->sol_state;
/* here we are feasible or optimal */
for (i=0; i<end-begin+1; ++i)
values[i] = lpp->vars[begin+i]->value;
return lpp->sol_state;
}
void lpp_dump(lpp_t *lpp, const char *filename) {
FILE *out = fopen(filename, "wt");
mps_write_mps(lpp, s_mps_fixed, out);
fclose(out);
}
/**
* Author: Daniel Grund
* Date: 16.05.2005
* Copyright: (c) Universitaet Karlsruhe
* Licence: This file protected by GPL - GNU GENERAL PUBLIC LICENSE.
*
* Interface for specifying an milp. Does not define a solution method.
*/
#ifndef _LPP_H
#define _LPP_H
#include <stdio.h>
#include "set.h"
#include "sp_matrix.h"
typedef enum _opt_t {minimize, maximize} opt_t;
typedef enum _cst_t {objective=0, equal=1, less=2, greater=3} cst_t;
typedef enum _var_t {invalid=0, rhs=1, continous=2, binary=3} var_t;
typedef enum _sol_state_t {unknown=0, infeasible=1, inforunb=2, unbounded=3, feasible=4, optimal=5} sol_state_t;
typedef enum _value_kind_t {none=0, value_start, value_solution} value_kind_t;
typedef struct _name_t name_t;
struct _name_t {
char *name; /**< the name of the var/constraint supplied by user */
int nr; /**< the col/row number in the matrix */
value_kind_t value_kind;
double value;
union _type {
var_t var_type;
cst_t cst_type;
} type;
};
typedef struct _lpp_t {
/* The problem data */
char *name; /**< A textual name for this problem */
opt_t opt_type; /**< Optimization direction */
sp_matrix_t *m; /**< The matrix holding objective, constraints and rhs */
/* Cst/Var to Nr mapping */
set *cst2nr; /**< Holds name_t's for constraints */
set *var2nr; /**< Holds name_t's for variables */
/* Nr to Cst/Var mapping */
int cst_size, var_size; /**< Size of the csts/vars-arrays below */
int cst_next, var_next; /**< Next free position in arrays below */
name_t **csts; /**< Pointers to the elements in the cst2nr set */
name_t **vars; /**< Pointers to the elements in the var2nr set */
/* Solution stuff */
sol_state_t sol_state;
double sol_time; /**< Time in seconds */
unsigned iterations;
char *error;
unsigned next_name_number;
} lpp_t;
#define ERR_NAME_NOT_ALLOWED -2
/**
* Creates a new problem. Optimization type is minimize or maximize.
* Implicit row with name "obj" is inserted.
* Implicit col with name "rhs" is inserted.
*/
lpp_t *new_lpp(const char *name, opt_t opt_type);
void free_lpp(lpp_t *lpp);
/**
* Adds a constraint to a problem. If a constraint with the same name already
* exists nothing is altered, and the index of the existing entry is returned.
* @param cst_name The name of the constraint (1st char only alpha-numeric!). If NULL, a default name will be used.
* @param cst_type The type of constraint: objective, equality, less-or-equal, greater-or-equal
* @param rhs The right hand side value to set for this constraint.
* @return The (new or existing) index of the constraint
*/
int lpp_add_cst(lpp_t *lpp, char *cst_name, cst_t cst_type, double rhs);
/**
* Returns the internal index of a constraint.
* @param cst_name The name of the constraint
* @return The internal index of constraint @p cst_name or -1 if it does not exist.
*/
int lpp_get_cst_idx(lpp_t *lpp, char *cst_name);
/**
* Returns the name of a constraint.
* @param index The internal index of a constraint.
* @param buf A buffer to hold the name of the constraint
* @param buf_size Size of the buffer
*/
void lpp_get_cst_name(lpp_t *lpp, int index, char *buf, size_t buf_size);
/**
* Adds a variable to a problem. If a variable with the same name already
* exists nothing is altered, and the index of the existing entry is returned.
* @param var_name The name of the constraint (1st char only alpha-numeric!). If NULL, a default name will be used.
* @param var_type The type of variable: real, binary
* @param obj The objactive value coefficient for this variable.
* @return The (new or existing) index of the variable
*
* NOTE: common integer or semi-continous vars are not (yet) implemented
*/
int lpp_add_var(lpp_t *lpp, char *var_name, var_t var_type, double obj);
/**
* Returns the internal index of a variable.
* @param cst_name The name of the variable
* @return The internal index of variable @p var_name or -1 if it does not exist.
*/
int lpp_get_var_idx(lpp_t *lpp, char *var_name);
/**
* Returns the name of a variable.
* @param index The internal index of a variable.
* @param buf A buffer to hold the name of the variable
* @param buf_size Size of the buffer
*/
void lpp_get_var_name(lpp_t *lpp, int index, char *buf, size_t buf_size);
/**
* Sets the factor of the variable @p var_name in constraint @p cst_name to @p value.
* @return -1 if constraint or variable name does not exist.
* 0 otherwise
*/
int lpp_set_factor(lpp_t *lpp, char *cst_name, char *var_name, double value);
/**
* Same as lpp_set_factor but uses the internal indices instead of names.
* @return -1 if an index was invalid
* 0 otherwise
*/
int lpp_set_factor_fast(lpp_t *lpp, int cst_idx, int var_idx, double value);
/**
* Set a starting value for a var.
* @param var_idx The index of the variable to set the value for.
* @param value The value to set.
*/
void lpp_set_start_value(lpp_t *lpp, int var_idx, double value);
/**
* @return The solution values of the variables from index begin to index end.
*/
sol_state_t lpp_get_solution(lpp_t *lpp, double *values, int begin, int end);
/**
* Dumps the lpp into a file with name @p filename in MPS-format
*/
void lpp_dump(lpp_t *lpp, const char *filename);
#define lpp_get_iter_cnt(lpp) ((lpp)->iterations)
#define lpp_get_sol_time(lpp) ((lpp)->sol_time)
#endif
/**
* Author: Daniel Grund
* Date: 02.06.2005
* Copyright: (c) Universitaet Karlsruhe
* Licence: This file protected by GPL - GNU GENERAL PUBLIC LICENSE.
*/
#undef HAVE_CPLEX
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include "lpp_local.h"
#include <stdio.h>
#ifdef HAVE_CPLEX
#include <alloca.h>
#include <sys/time.h>
#include "xmalloc.h"
#include "assert.h"
#include "sp_matrix.h"
#include "ilcplex/cplex.h"
#undef LOGFILE //stdout
#define TIME_LIMIT 5*60 /* in sec. 0 for none */
static char cpx_cst_encoding[4] = {'?', 'E', 'L', 'G'};
static char cpx_var_encoding[4] = {'?', '?', 'C', 'B'};
typedef struct _cpx_t {
lpp_t *lpp;
CPXENVptr env;
CPXLPptr prob;
int status;
char buf[1024];
} cpx_t;
static INLINE void chk_cpx_err(cpx_t *cpx) {
if (cpx->status) {
if (CPXgeterrorstring(cpx->env, cpx->status, cpx->buf))
printf(cpx->buf);
else
printf("Unknown CPLEX error\n");
assert(0);
}
}
static cpx_t *new_cpx(lpp_t *lpp) {
cpx_t *cpx = xcalloc(1, sizeof(*cpx));
cpx->lpp = lpp;
cpx->env = CPXopenCPLEX(&cpx->status);
chk_cpx_err(cpx);
cpx->prob = CPXcreateprob(cpx->env, &cpx->status, lpp->name);
chk_cpx_err(cpx);
CPXchgobjsen(cpx->env, cpx->prob, (lpp->opt_type == minimize)?1:-1);
chk_cpx_err(cpx);
#ifdef LOGFILE
if (CPXsetlogfile(cpx->env, LOGFILE))
assert(0 && "Could not set logfile");
#endif
return cpx;
}
static void free_cpx(cpx_t *cpx) {
CPXfreeprob(cpx->env, &cpx->prob);
CPXcloseCPLEX(&cpx->env);
free(cpx);
}
static void cpx_construct(cpx_t *cpx) {
const matrix_elem_t *elem;
int i, o, sv_cnt, numcols, numrows, numentries, objsen, *matbeg, *matcnt, *matind, *indices;
double *obj, *rhs, *matval, *lb, *ub, *startv;
char *sense, *vartype, **colname;
lpp_t *lpp = cpx->lpp;
numcols = lpp->var_next-1;
numrows = lpp->cst_next-1;
numentries = matrix_get_entries(lpp->m);
objsen = lpp->opt_type == minimize ? 1 : -1;
obj = alloca(numcols * sizeof(*obj));
lb = alloca(numcols * sizeof(*lb));
ub = alloca(numcols * sizeof(*ub));
colname = alloca(numcols * sizeof(*colname));
vartype = alloca(numcols * sizeof(*vartype));
indices = alloca(numcols * sizeof(*indices));
startv = alloca(numcols * sizeof(*startv));
matbeg = alloca(numcols * sizeof(*matbeg));
matcnt = alloca(numcols * sizeof(*matcnt));
matind = alloca(numentries * sizeof(*matind));
matval = alloca(numentries * sizeof(*matval));
rhs = alloca(numrows * sizeof(*rhs));
sense = alloca(numrows * sizeof(*sense));
o = 0;
sv_cnt = 0;
for(i=0; i<numcols; ++i) {
name_t *curr_var = lpp->vars[1+i];
obj[i] = matrix_get(lpp->m, 0, 1+i);
lb[i] = 0.0;
ub[i] = CPX_INFBOUND;
colname[i] = curr_var->name;
vartype[i] = cpx_var_encoding[curr_var->type.var_type];
if(curr_var->value_kind == value_start) {
indices[sv_cnt] = i;
startv[sv_cnt++] = curr_var->value;
}
matbeg[i] = o;
matcnt[i] = 0;
matrix_foreach_in_col(lpp->m, 1+i, elem) {
if (elem->row == 0)
continue;
matind[o] = elem->row-1;
matval[o] = elem->val;
matcnt[i]++;
o++;
}
}
for(i=0; i<numrows; ++i) {
rhs[i] = matrix_get(lpp->m, 1+i, 0);
sense[i] = cpx_cst_encoding[lpp->csts[1+i]->type.cst_type];
}
cpx->status = CPXcopylpwnames(cpx->env, cpx->prob,
numcols, numrows, objsen,
obj, rhs, sense,
matbeg, matcnt, matind, matval,
lb, ub, NULL,
colname, NULL);
chk_cpx_err(cpx);
cpx->status = CPXcopyctype(cpx->env, cpx->prob, vartype);
chk_cpx_err(cpx);
cpx->status = CPXcopymipstart(cpx->env, cpx->prob, sv_cnt, indices, startv);
chk_cpx_err(cpx);
}
static void cpx_solve(cpx_t *cpx) {
int i, CPX_state, numcols;
double *values;