/*
- * Copyright (C) 1995-2007 University of Karlsruhe. All right reserved.
+ * Copyright (C) 1995-2008 University of Karlsruhe. All right reserved.
*
* This file is part of libFirm.
*
* - Register-constrained nodes
* - Two-address code instructions
*/
-#ifdef HAVE_CONFIG_H
#include "config.h"
-#endif
#include "execfreq.h"
#include "xmalloc.h"
#include "belive_t.h"
#include "beinsn_t.h"
#include "besched_t.h"
-#include "bejavacoal.h"
#include "bestatevent.h"
#include "beirg_t.h"
#include "error.h"
-#include <libcore/lc_timing.h>
-#include <libcore/lc_opts.h>
-#include <libcore/lc_opts_enum.h>
+#include "lc_opts.h"
+#include "lc_opts_enum.h"
#define DUMP_BEFORE 1
#define DUMP_AFTER 2
FIRM_DBG_REGISTER(dbg, "ir.be.copyopt");
- co = xcalloc(1, sizeof(*co));
+ co = XMALLOCZ(copy_opt_t);
co->cenv = chordal_env;
- co->aenv = chordal_env->birg->main_env->arch_env;
co->irg = chordal_env->irg;
co->cls = chordal_env->cls;
co->get_costs = get_costs;
s2 = get_entity_name(get_irg_entity(co->irg));
s3 = chordal_env->cls->name;
len = strlen(s1) + strlen(s2) + strlen(s3) + 5;
- co->name = xmalloc(len);
+ co->name = XMALLOCN(char, len);
snprintf(co->name, len, "%s__%s__%s", s1, s2, s3);
return co;
free(co);
}
-int co_is_optimizable_root(const copy_opt_t *co, ir_node *irn) {
+/**
+ * Checks if a node is optimizable, viz. has something to do with coalescing
+ * @param irn The irn to check
+ */
+static int co_is_optimizable_root(ir_node *irn)
+{
const arch_register_req_t *req;
- const arch_register_t *reg;
+ const arch_register_t *reg;
- if (arch_irn_is(co->aenv, irn, ignore))
+ if (arch_irn_is_ignore(irn))
return 0;
- reg = arch_get_irn_register(co->aenv, irn);
+ reg = arch_get_irn_register(irn);
if (arch_register_type_is(reg, ignore))
return 0;
- req = arch_get_register_req(co->aenv, irn, -1);
- if (is_Reg_Phi(irn) || is_Perm_Proj(co->aenv, irn) || is_2addr_code(req))
+ if (is_Reg_Phi(irn) || is_Perm_Proj(irn))
+ return 1;
+
+ req = arch_get_register_req_out(irn);
+ if (is_2addr_code(req))
return 1;
return 0;
* safe: node has no interference, hence it is in every max stable set.
* unsafe: node has an interference
*/
- safe = alloca((ou->node_count-1) * sizeof(*safe));
- safe_costs = 0;
- safe_count = 0;
- unsafe = alloca((ou->node_count-1) * sizeof(*unsafe));
- unsafe_costs = alloca((ou->node_count-1) * sizeof(*unsafe_costs));
+ safe = ALLOCAN(ir_node*, ou->node_count - 1);
+ safe_costs = 0;
+ safe_count = 0;
+ unsafe = ALLOCAN(ir_node*, ou->node_count - 1);
+ unsafe_costs = ALLOCAN(int, ou->node_count - 1);
unsafe_count = 0;
for(i=1; i<ou->node_count; ++i) {
int is_safe = 1;
return safe_costs+best_weight;
}
-static void co_collect_units(ir_node *irn, void *env) {
- copy_opt_t *co = env;
+static void co_collect_units(ir_node *irn, void *env)
+{
+ const arch_register_req_t *req = arch_get_register_req_out(irn);
+ copy_opt_t *co = env;
unit_t *unit;
- if (!is_curr_reg_class(co, irn))
+ if (req->cls != co->cls)
return;
- if (!co_is_optimizable_root(co, irn))
+ if (!co_is_optimizable_root(irn))
return;
/* Init a new unit */
- unit = xcalloc(1, sizeof(*unit));
+ unit = XMALLOCZ(unit_t);
unit->co = co;
unit->node_count = 1;
INIT_LIST_HEAD(&unit->queue);
/* init */
arity = get_irn_arity(irn);
- unit->nodes = xmalloc((arity+1) * sizeof(*unit->nodes));
- unit->costs = xmalloc((arity+1) * sizeof(*unit->costs));
+ unit->nodes = XMALLOCN(ir_node*, arity + 1);
+ unit->costs = XMALLOCN(int, arity + 1);
unit->nodes[0] = irn;
/* fill */
int o, arg_pos;
ir_node *arg = get_irn_n(irn, i);
- assert(is_curr_reg_class(co, arg) && "Argument not in same register class.");
+ assert(arch_get_irn_reg_class_out(arg) == co->cls && "Argument not in same register class.");
if (arg == irn)
continue;
if (nodes_interfere(co->cenv, irn, arg)) {
/* Else insert the argument of the phi to the members of this ou */
DBG((dbg, LEVEL_1, "\t Member: %+F\n", arg));
- if (! arch_irn_is(co->aenv, arg, ignore)) {
- /* Check if arg has occurred at a prior position in the arg/list */
- arg_pos = 0;
- for (o=1; o<unit->node_count; ++o) {
- if (unit->nodes[o] == arg) {
- arg_pos = o;
- break;
- }
- }
+ if (arch_irn_is_ignore(arg))
+ continue;
- if (!arg_pos) { /* a new argument */
- /* insert node, set costs */
- unit->nodes[unit->node_count] = arg;
- unit->costs[unit->node_count] = co->get_costs(co, irn, arg, i);
- unit->node_count++;
- } else { /* arg has occurred before in same phi */
- /* increase costs for existing arg */
- unit->costs[arg_pos] += co->get_costs(co, irn, arg, i);
+ /* Check if arg has occurred at a prior position in the arg/list */
+ arg_pos = 0;
+ for (o=1; o<unit->node_count; ++o) {
+ if (unit->nodes[o] == arg) {
+ arg_pos = o;
+ break;
}
}
+
+ if (!arg_pos) { /* a new argument */
+ /* insert node, set costs */
+ unit->nodes[unit->node_count] = arg;
+ unit->costs[unit->node_count] = co->get_costs(co, irn, arg, i);
+ unit->node_count++;
+ } else { /* arg has occurred before in same phi */
+ /* increase costs for existing arg */
+ unit->costs[arg_pos] += co->get_costs(co, irn, arg, i);
+ }
}
- unit->nodes = xrealloc(unit->nodes, unit->node_count * sizeof(*unit->nodes));
- unit->costs = xrealloc(unit->costs, unit->node_count * sizeof(*unit->costs));
- } else if (is_Perm_Proj(co->aenv, irn)) {
+ unit->nodes = XREALLOC(unit->nodes, ir_node*, unit->node_count);
+ unit->costs = XREALLOC(unit->costs, int, unit->node_count);
+ } else if (is_Perm_Proj(irn)) {
/* Proj of a perm with corresponding arg */
assert(!nodes_interfere(co->cenv, irn, get_Perm_src(irn)));
- unit->nodes = xmalloc(2 * sizeof(*unit->nodes));
- unit->costs = xmalloc(2 * sizeof(*unit->costs));
+ unit->nodes = XMALLOCN(ir_node*, 2);
+ unit->costs = XMALLOCN(int, 2);
unit->node_count = 2;
unit->nodes[0] = irn;
unit->nodes[1] = get_Perm_src(irn);
unit->costs[1] = co->get_costs(co, irn, unit->nodes[1], -1);
} else {
- const arch_register_req_t *req =
- arch_get_register_req(co->aenv, irn, -1);
-
/* Src == Tgt of a 2-addr-code instruction */
if (is_2addr_code(req)) {
const unsigned other = req->other_same;
for (i = 0; (1U << i) <= other; ++i) {
if (other & (1U << i)) {
ir_node *o = get_irn_n(skip_Proj(irn), i);
- if (!arch_irn_is(co->aenv, o, ignore) &&
- !nodes_interfere(co->cenv, irn, o)) {
- ++count;
- }
+ if (arch_irn_is_ignore(o))
+ continue;
+ if (nodes_interfere(co->cenv, irn, o))
+ continue;
+ ++count;
}
}
if (count != 0) {
int k = 0;
++count;
- unit->nodes = xmalloc(count * sizeof(*unit->nodes));
- unit->costs = xmalloc(count * sizeof(*unit->costs));
+ unit->nodes = XMALLOCN(ir_node*, count);
+ unit->costs = XMALLOCN(int, count);
unit->node_count = count;
unit->nodes[k++] = irn;
for (i = 0; 1U << i <= other; ++i) {
if (other & (1U << i)) {
ir_node *o = get_irn_n(skip_Proj(irn), i);
- if (!arch_irn_is(co->aenv, o, ignore) &&
+ if (!arch_irn_is_ignore(o) &&
!nodes_interfere(co->cenv, irn, o)) {
unit->nodes[k] = o;
unit->costs[k] = co->get_costs(co, irn, o, -1);
const unit_t *u2 = *((const unit_t **) k2);
int i, o, u1_has_constr, u2_has_constr;
arch_register_req_t req;
- const arch_env_t *aenv = u1->co->aenv;
/* Units with constraints come first */
u1_has_constr = 0;
for (i=0; i<u1->node_count; ++i) {
- arch_get_register_req(aenv, &req, u1->nodes[i], -1);
+ arch_get_register_req_out(&req, u1->nodes[i]);
if (arch_register_req_is(&req, limited)) {
u1_has_constr = 1;
break;
u2_has_constr = 0;
for (i=0; i<u2->node_count; ++i) {
- arch_get_register_req(aenv, &req, u2->nodes[i], -1);
+ arch_get_register_req_out(&req, u2->nodes[i]);
if (arch_register_req_is(&req, limited)) {
u2_has_constr = 1;
break;
/* get the number of ous, remove them form the list and fill the array */
list_for_each_entry(unit_t, ou, &co->units, units)
count++;
- ous = alloca(count * sizeof(*ous));
+ ous = ALLOCAN(unit_t, count);
costs = co_get_max_copy_costs(co);
ASSERT_OU_AVAIL(co);
list_for_each_entry(unit_t, curr, &co->units, units) {
- int root_col = get_irn_col(co, curr->nodes[0]);
+ int root_col = get_irn_col(curr->nodes[0]);
DBG((dbg, LEVEL_1, " %3d costs for root %+F color %d\n", curr->inevitable_costs, curr->nodes[0], root_col));
res += curr->inevitable_costs;
for (i=1; i<curr->node_count; ++i) {
- int arg_col = get_irn_col(co, curr->nodes[i]);
+ int arg_col = get_irn_col(curr->nodes[i]);
if (root_col != arg_col) {
DBG((dbg, LEVEL_1, " %3d for arg %+F color %d\n", curr->costs[i], curr->nodes[i], arg_col));
res += curr->costs[i];
stat->aff_edges += 1;
stat->max_costs += neigh->costs;
- if(get_irn_col(co, an->irn) != get_irn_col(co, neigh->irn)) {
+ if (get_irn_col(an->irn) != get_irn_col(neigh->irn)) {
stat->costs += neigh->costs;
stat->unsatisfied_edges += 1;
}
nbr->costs += costs;
}
-static INLINE void add_edges(copy_opt_t *co, ir_node *n1, ir_node *n2, int costs) {
+static inline void add_edges(copy_opt_t *co, ir_node *n1, ir_node *n2, int costs) {
if (! be_ifg_connected(co->cenv->ifg, n1, n2)) {
add_edge(co, n1, n2, costs);
add_edge(co, n2, n1, costs);
}
static void build_graph_walker(ir_node *irn, void *env) {
- copy_opt_t *co = env;
+ const arch_register_req_t *req = arch_get_register_req_out(irn);
+ copy_opt_t *co = env;
int pos, max;
const arch_register_t *reg;
- if (!is_curr_reg_class(co, irn) || arch_irn_is(co->aenv, irn, ignore))
+ if (req->cls != co->cls || arch_irn_is_ignore(irn))
return;
- reg = arch_get_irn_register(co->aenv, irn);
+ reg = arch_get_irn_register(irn);
if (arch_register_type_is(reg, ignore))
return;
ir_node *arg = get_irn_n(irn, pos);
add_edges(co, irn, arg, co->get_costs(co, irn, arg, pos));
}
- }
- else if (is_Perm_Proj(co->aenv, irn)) { /* Perms */
+ } else if (is_Perm_Proj(irn)) { /* Perms */
ir_node *arg = get_Perm_src(irn);
add_edges(co, irn, arg, co->get_costs(co, irn, arg, 0));
- }
- else { /* 2-address code */
- const arch_register_req_t *req = arch_get_register_req(co->aenv, irn, -1);
+ } else { /* 2-address code */
if (is_2addr_code(req)) {
const unsigned other = req->other_same;
int i;
for (i = 0; 1U << i <= other; ++i) {
if (other & (1U << i)) {
ir_node *other = get_irn_n(skip_Proj(irn), i);
- if (! arch_irn_is(co->aenv, other, ignore))
+ if (!arch_irn_is_ignore(other))
add_edges(co, irn, other, co->get_costs(co, irn, other, 0));
}
}
{
ir_node *nodes[] = { a, b };
bitset_t *constr[] = { NULL, NULL };
- const arch_register_req_t *req;
int j;
constr[0] = bitset_alloca(co->cls->n_regs);
constr[1] = bitset_alloca(co->cls->n_regs);
for (j = 0; j < 2; ++j) {
- req = arch_get_register_req(co->aenv, nodes[j], BE_OUT_POS(0));
+ const arch_register_req_t *req = arch_get_register_req_out(nodes[j]);
if(arch_register_req_is(req, limited))
rbitset_copy_to_bitset(req->limited, constr[j]);
else
void co_dump_appel_graph(const copy_opt_t *co, FILE *f)
{
- be_ifg_t *ifg = co->cenv->ifg;
- int *color_map = alloca(co->cls->n_regs * sizeof(color_map[0]));
- int *node_map = xmalloc((get_irg_last_idx(co->irg) + 1) * sizeof(node_map[0]));
+ be_ifg_t *ifg = co->cenv->ifg;
+ int *color_map = ALLOCAN(int, co->cls->n_regs);
+ int *node_map = XMALLOCN(int, get_irg_last_idx(co->irg) + 1);
ir_node *irn;
void *it, *nit;
n = n_regs;
be_ifg_foreach_node(ifg, it, irn) {
- if(!arch_irn_is(co->aenv, irn, ignore))
- node_map[get_irn_idx(irn)] = n++;
+ if (arch_irn_is_ignore(irn))
+ continue;
+ node_map[get_irn_idx(irn)] = n++;
}
fprintf(f, "%d %d\n", n, n_regs);
be_ifg_foreach_node(ifg, it, irn) {
- if(!arch_irn_is(co->aenv, irn, ignore)) {
- int idx = node_map[get_irn_idx(irn)];
- affinity_node_t *a = get_affinity_info(co, irn);
-
- const arch_register_req_t *req;
- ir_node *adj;
+ if (!arch_irn_is_ignore(irn)) {
+ int idx = node_map[get_irn_idx(irn)];
+ affinity_node_t *a = get_affinity_info(co, irn);
+ const arch_register_req_t *req = arch_get_register_req_out(irn);
+ ir_node *adj;
- req = arch_get_register_req(co->aenv, irn, BE_OUT_POS(0));
if(arch_register_req_is(req, limited)) {
for(i = 0; i < co->cls->n_regs; ++i) {
if(!rbitset_is_set(req->limited, i) && color_map[i] >= 0)
}
be_ifg_foreach_neighbour(ifg, nit, irn, adj) {
- if(!arch_irn_is(co->aenv, adj, ignore) && !co_dump_appel_disjoint_constraints(co, irn, adj)) {
+ if (!arch_irn_is_ignore(adj) &&
+ !co_dump_appel_disjoint_constraints(co, irn, adj)) {
int adj_idx = node_map[get_irn_idx(adj)];
if(idx < adj_idx)
fprintf(f, "%d %d -1\n", idx, adj_idx);
neighb_t *n;
co_gs_foreach_neighb(a, n) {
- if(!arch_irn_is(co->aenv, n->irn, ignore)) {
+ if (!arch_irn_is_ignore(n->irn)) {
int n_idx = node_map[get_irn_idx(n->irn)];
if(idx < n_idx)
fprintf(f, "%d %d %d\n", idx, n_idx, (int) n->costs);
static int ifg_is_dump_node(void *self, ir_node *irn)
{
- co_ifg_dump_t *cod = self;
- return !arch_irn_is(cod->co->aenv, irn, ignore);
+ (void)self;
+ return !arch_irn_is_ignore(irn);
}
static void ifg_dump_node_attr(FILE *f, void *self, ir_node *irn)
{
- co_ifg_dump_t *env = self;
- const arch_register_t *reg = arch_get_irn_register(env->co->aenv, irn);
- const arch_register_req_t *req;
- int limited;
-
- req = arch_get_register_req(env->co->aenv, irn, BE_OUT_POS(0));
- limited = arch_register_req_is(req, limited);
+ co_ifg_dump_t *env = self;
+ const arch_register_t *reg = arch_get_irn_register(irn);
+ const arch_register_req_t *req = arch_get_register_req_out(irn);
+ int limited = arch_register_req_is(req, limited);
if(env->flags & CO_IFG_DUMP_LABELS) {
ir_fprintf(f, "label=\"%+F", irn);
affinity_node_t *a;
co_gs_foreach_aff_node(env->co, a) {
- const arch_register_t *ar = arch_get_irn_register(env->co->aenv, a->irn);
+ const arch_register_t *ar = arch_get_irn_register(a->irn);
unsigned aidx = get_irn_idx(a->irn);
neighb_t *n;
co_gs_foreach_neighb(a, n) {
- const arch_register_t *nr = arch_get_irn_register(env->co->aenv, n->irn);
+ const arch_register_t *nr = arch_get_irn_register(n->irn);
unsigned nidx = get_irn_idx(n->irn);
if(aidx < nidx) {
char *tu_name;
n = strlen(env->birg->main_env->cup_name);
- tu_name = xmalloc((n + 1) * sizeof(*tu_name));
+ tu_name = XMALLOCN(char, n + 1);
strcpy(tu_name, env->birg->main_env->cup_name);
for (i = 0; i < n; ++i)
if (tu_name[i] == '.')
void co_driver(be_chordal_env_t *cenv)
{
- lc_timer_t *timer = lc_timer_register("firm.be.copyopt", "runtime");
+ ir_timer_t *timer = ir_timer_register("firm.be.copyopt", "runtime");
co_complete_stats_t before, after;
copy_opt_t *co;
co_algo_t *algo_func;
algo_func = algos[algo].algo;
/* perform actual copy minimization */
- lc_timer_reset_and_start(timer);
+ ir_timer_reset_and_start(timer);
was_optimal = algo_func(co);
- lc_timer_stop(timer);
+ ir_timer_stop(timer);
- be_stat_ev("co_time", lc_timer_elapsed_msec(timer));
+ be_stat_ev("co_time", ir_timer_elapsed_msec(timer));
be_stat_ev_ull("co_optimal", was_optimal);
if (dump_flags & DUMP_AFTER) {