/* if a restriction is found, insert a perm before the irn */
if (req.type == arch_register_req_type_limited) {
insert_Perm_after(menv, cenv->cls, cenv->dom_front, sched_prev(irn));
+ /* TODO: Next line is overkill. Update_liveness would suffice. */
be_liveness(get_irn_irg(bl));
break;
}
static INLINE void qnode_set_new_color(const qnode_t *qn, ir_node *irn, int color) {
node_stat_t *found = qnode_find_or_insert_node(qn, irn);
found->new_color = color;
+ DBG((dbg, LEVEL_3, "\t col(%+F) := %d\n", irn, color));
}
/**
static INLINE void qnode_pin_local(const qnode_t *qn, ir_node *irn) {
node_stat_t *found = qnode_find_or_insert_node(qn, irn);
found->pinned_local = 1;
+ if (found->new_color == NO_COLOR)
+ found->new_color = get_irn_col(qn->ou->co, irn);
}
/**
* This should be true in SSA.
*/
static ir_node *qnode_color_irn(const qnode_t *qn, ir_node *irn, int col, const ir_node *trigger) {
- ir_node *res;
- struct obstack confl_ob;
- ir_node **confl, *cn;
- int i, irn_col;
const be_chordal_env_t *chordal_env = qn->ou->co->chordal_env;
- const arch_env_t *arch_env = get_arch_env(qn->ou->co);
const arch_register_class_t *cls = chordal_env->cls;
+ const arch_env_t *arch_env = chordal_env->main_env->arch_env;
+ int irn_col = qnode_get_new_color(qn, irn);
- DBG((dbg, LEVEL_3, "\t %+F \tcaused col(%+F) \t%2d --> %2d\n", trigger, irn, qnode_get_new_color(qn, irn), col));
- obstack_init(&confl_ob);
- irn_col = qnode_get_new_color(qn, irn);
+ DBG((dbg, LEVEL_3, "\t %+F \tcaused col(%+F) \t%2d --> %2d\n", trigger, irn, irn_col, col));
if (irn_col == col) {
- DBG((dbg, LEVEL_4, "\t Already same color.\n"));
- goto ret_save;
+ DBG((dbg, LEVEL_3, "\t %+F same color\n", irn));
+ return CHANGE_SAVE;
}
if (pset_find_ptr(pinned_global, irn) || qnode_is_pinned_local(qn, irn)) {
- res = irn;
- goto ret_confl;
+ DBG((dbg, LEVEL_3, "\t %+F conflicting\n", irn));
+ return irn;
+ }
+ if (!arch_reg_is_allocatable(arch_env, irn, -1, arch_register_for_index(cls, col))) {
+ DBG((dbg, LEVEL_3, "\t %+F impossible\n", irn));
+ return CHANGE_IMPOSSIBLE;
}
- if (!arch_reg_is_allocatable(arch_env,
- irn,
- -1,
- arch_register_for_index(cls, col)))
- goto ret_imposs;
- /* get all nodes which would conflict with this change */
+ /*
+ * Process all nodes which would conflict with this change
+ */
{
- struct obstack q;
- int in, out;
- ir_node *irn_bl;
-
- irn_bl = get_nodes_block(irn);
-
- /* first check for a conflicting node which is 'living in' the irns block */
- {
- ir_node *n;
- pset *live_ins = put_live_in(irn_bl, pset_new_ptr_default());
- for (n = pset_first(live_ins); n; n = pset_next(live_ins)) {
- DBG((dbg, LEVEL_4, "Checking %+F which is live-in at the block\n", n));
- if (arch_irn_has_reg_class(arch_env, n, -1, cls)
- && n != trigger && qnode_get_new_color(qn, n) == col
- && nodes_interfere(chordal_env, irn, n)) {
-
- DBG((dbg, LEVEL_4, "\t %+F\ttroubles\n", n));
- obstack_ptr_grow(&confl_ob, n);
- pset_break(live_ins);
- break;
- }
- }
- del_pset(live_ins);
- }
+ be_ifg_t *ifg = chordal_env->ifg;
+ void *iter = be_ifg_neighbours_iter_alloca(ifg);
+ ir_node *sub_res, *curr;
- /* setup the queue of blocks. */
- obstack_init(&q);
- obstack_ptr_grow(&q, irn_bl);
- in = 1;
- out = 0;
-
- /* process the queue. The code below checks for every block dominated
- * by the irns one, and in which the irn is live, if there are
- * conflicting nodes */
- while (out < in) {
- ir_node *curr_bl, *sub_bl;
- int i, max;
-
- curr_bl = ((ir_node **)obstack_base(&q))[out++];
-
- /* Add to the result all nodes in the block, which have
- * the target color and interfere with the irn */
- for (i = 0, max = get_irn_n_outs(curr_bl); i < max; ++i) {
- ir_node *n = get_irn_out(curr_bl, i);
- DBG((dbg, LEVEL_4, "Checking %+F defined in same block\n", n));
- if (arch_irn_has_reg_class(arch_env, n, -1, cls)
- && n != trigger && qnode_get_new_color(qn, n) == col
- && nodes_interfere(chordal_env, irn, n)) {
- DBG((dbg, LEVEL_4, "\t %+F\ttroubles\n", n));
- obstack_ptr_grow(&confl_ob, n);
+ /*
+ * Try to color all conflicting nodes 'curr'
+ * with the color of the irn itself.
+ */
+ be_ifg_foreach_neighbour(ifg, iter, irn, curr) {
+ DBG((dbg, LEVEL_3, "\t Confl %+F(%d)\n", curr, qnode_get_new_color(qn, curr)));
+ if (qnode_get_new_color(qn, curr) == col && curr != trigger) {
+ sub_res = qnode_color_irn(qn, curr, irn_col, irn);
+ if (sub_res != CHANGE_SAVE) {
+ be_ifg_neighbours_break(ifg, iter);
+ return sub_res;
}
}
-
- /* If irn lives out check i-dominated blocks where the irn lives in */
- /* Fill the queue */
- if (is_live_out(curr_bl, irn)) {
- dominates_for_each(curr_bl, sub_bl)
- if (is_live_in(sub_bl, irn)) {
- obstack_ptr_grow(&q, sub_bl);
- in++;
- }
- }
}
- obstack_free(&q, NULL);
- obstack_ptr_grow(&confl_ob, NULL);
- confl = (ir_node **) obstack_finish(&confl_ob);
}
- /* process all nodes which would conflict with this change */
- for (i = 0, cn = confl[0]; cn; cn = confl[++i]) {
- ir_node *sub_res;
-
- /* try to color the conflicting node cn with the color of the irn itself */
- sub_res = qnode_color_irn(qn, cn, irn_col, irn);
- if (sub_res != CHANGE_SAVE) {
- res = sub_res;
- goto ret_confl;
- }
- }
- /* if we arrive here all sub changes can be applied, so it's save to change this irn */
-
-ret_save:
- DBG((dbg, LEVEL_3, "\t %+F save\n", irn));
- obstack_free(&confl_ob, NULL);
+ /*
+ * If we arrive here, all sub changes have been applied.
+ * So it's save to change this irn
+ */
qnode_set_new_color(qn, irn, col);
return CHANGE_SAVE;
-
-ret_imposs:
- DBG((dbg, LEVEL_3, "\t %+F impossible\n", irn));
- obstack_free(&confl_ob, NULL);
- return CHANGE_IMPOSSIBLE;
-
-ret_confl:
- DBG((dbg, LEVEL_3, "\t %+F conflicting\n", irn));
- obstack_free(&confl_ob, NULL);
- return res;
}
/**
return 1;
}
-typedef int(*confl_f)(const ir_node *a, const ir_node *b, void *data);
-
-/**
- * @param result Gets filled with the computed maximum independent set.
- * @param count The size of input arrays / the number of nodes
- * @param nodes A set of nodes to copmute the max. ind. set for
- * @param weights Weights associated to the nodes in @p nodes
- * @param confl Callback function to decide if two values interfere
- * @param data Passed into all callbacks
- * @return The size of the computed set
- */
-//int max_ind_set(ir_node **result, int count, ir_node **nodes, int *weights, confl_f confl, void *data) {
-//
-//}
-
/**
* Determines a maximum weighted independent set with respect to
* the interference and conflict edges of all nodes in a qnode.
best = bitset_alloca(unsafe_count);
if (unsafe_count > MIS_HEUR_TRIGGER) {
- /* Heuristik: Greedy trial and error form index 0 to unsafe_count-1 */
+ /* Heuristic: Greedy trial and error form index 0 to unsafe_count-1 */
for (i=0; i<unsafe_count; ++i) {
bitset_set(best, i);
/* check if it is a stable set */
/* try */
if (qnode_try_color(curr))
break;
+
/* no success, so re-insert */
del_set(curr->changed_nodes);
curr->changed_nodes = new_set(set_cmp_node_stat_t, SLOTS_CHANGED_NODES);
/* apply the best found qnode */
if (curr->mis_size >= 2) {
node_stat_t *ns;
+ int root_col = qnode_get_new_color(curr, ou->nodes[0]);
DBG((dbg, LEVEL_1, "\t Best color: %d Costs: %d << %d << %d\n", curr->color, ou->min_nodes_costs, ou->all_nodes_costs - curr->mis_costs, ou->all_nodes_costs));
/* globally pin root and all args which have the same color */
pset_insert_ptr(pinned_global, ou->nodes[0]);
for (i=1; i<ou->node_count; ++i) {
ir_node *irn = ou->nodes[i];
int nc = qnode_get_new_color(curr, irn);
- if (nc != NO_COLOR && nc == qnode_get_new_color(curr, ou->nodes[0]))
+ if (nc != NO_COLOR && nc == root_col)
pset_insert_ptr(pinned_global, irn);
}
set_irn_col(ou->co, ns->irn, ns->new_color);
}
}
- /*
- * Enable for checking register allocation after each ou
- * be_ra_chordal_check(ou->co->chordal_env);
- */
}
/* free best qnode (curr) and queue */
void co_heur_opt(copy_opt_t *co) {
unit_t *curr;
dbg = firm_dbg_register("ir.be.copyoptheur");
- if (!strcmp(co->name, DEBUG_IRG))
- firm_dbg_set_mask(dbg, DEBUG_IRG_LVL_HEUR);
- else
- firm_dbg_set_mask(dbg, DEBUG_LVL_HEUR);
pinned_global = pset_new_ptr(SLOTS_PINNED_GLOBAL);
list_for_each_entry(unit_t, curr, &co->units, units)
problem_instance_t *pi;
dbg = firm_dbg_register("ir.be.copyoptilp");
- if (!strcmp(co->name, DEBUG_IRG))
- firm_dbg_set_mask(dbg, DEBUG_IRG_LVL_ILP);
- else
- firm_dbg_set_mask(dbg, DEBUG_LVL_ILP);
pi = new_pi(co);
if (!pi->all_simplicial) {
} else
/* Proj of a perm with corresponding arg */
- if (is_Copy(get_arch_env(co), irn)) {
+ if (is_Perm_Proj(get_arch_env(co), irn)) {
assert(!nodes_interfere(co->chordal_env, irn, get_Copy_src(irn)));
unit->nodes = xmalloc(2 * sizeof(*unit->nodes));
unit->costs = xmalloc(2 * sizeof(*unit->costs));
/* Src == Tgt of a 2-addr-code instruction */
if (is_2addr_code(get_arch_env(co), irn, &req)) {
int pos = req.data.pos;
- unit->nodes = xmalloc(2 * sizeof(*unit->nodes));
- unit->costs = xmalloc(2 * sizeof(*unit->costs));
- unit->node_count = 2;
- unit->nodes[0] = irn;
- unit->nodes[1] = get_irn_n(irn, pos);
- unit->costs[1] = co->get_costs(irn, unit->nodes[1], pos);
+ ir_node *other = get_irn_n(irn, pos);
+ if (!nodes_interfere(co->chordal_env, irn, other)) {
+ unit->nodes = xmalloc(2 * sizeof(*unit->nodes));
+ unit->costs = xmalloc(2 * sizeof(*unit->costs));
+ unit->node_count = 2;
+ unit->nodes[0] = irn;
+ unit->nodes[1] = other;
+ unit->costs[1] = co->get_costs(irn, other, pos);
+ }
} else
assert(0 && "This is not an optimizable node!");
/* Insert the new unit at a position according to its costs */
- {
+ if (unit->node_count > 1) {
int i;
struct list_head *tmp;
while (tmp->next != &co->units && list_entry_units(tmp->next)->sort_key > unit->sort_key)
tmp = tmp->next;
list_add(&unit->units, tmp);
+ } else {
+ free(unit);
}
}
copy_opt_t *co;
dbg = firm_dbg_register("ir.be.copyopt");
- firm_dbg_set_mask(dbg, DEBUG_LVL_CO);
co = xcalloc(1, sizeof(*co));
co->chordal_env = chordal_env;
len = strlen(s1) + strlen(s2) + strlen(s3) + 5;
co->name = xmalloc(len);
snprintf(co->name, len, "%s__%s__%s", s1, s2, s3);
- if (!strcmp(co->name, DEBUG_IRG))
- firm_dbg_set_mask(dbg, DEBUG_IRG_LVL_CO);
- else
- firm_dbg_set_mask(dbg, DEBUG_LVL_CO);
DBG((dbg, LEVEL_1, "\tCollecting optimization units\n"));
INIT_LIST_HEAD(&co->units);
xfree(co->name);
list_for_each_entry_safe(unit_t, curr, tmp, &co->units, units) {
xfree(curr->nodes);
+ xfree(curr->costs);
xfree(curr);
}
}
int is_optimizable_arg(const copy_opt_t *co, ir_node *irn) {
- int i, max;
arch_env_t *aenv = co->chordal_env->main_env->arch_env;
+ const ir_edge_t *edge;
- for(i=0, max=get_irn_n_outs(irn); i<max; ++i) {
- ir_node *n = get_irn_out(irn, i);
+ foreach_out_edge(irn, edge) {
+ ir_node *n = edge->src;
arch_register_req_t req;
+
arch_get_register_req(aenv, &req, n, -1);
if( ( (req.type == arch_register_req_type_should_be_same && get_irn_n(n, req.data.pos) == irn) ||
) && (irn == n || !nodes_interfere(co->chordal_env, irn, n)))
return 1;
}
+
return 0;
}
#include "bechordal_t.h"
#include "bearch.h"
-#define DEBUG_IRG "!!deflate.c__longest_match__datab"
-#define DEBUG_IRG_LVL_CO SET_LEVEL_1
-#define DEBUG_IRG_LVL_HEUR SET_LEVEL_1
-#define DEBUG_IRG_LVL_ILP SET_LEVEL_1
-#define DEBUG_LVL_CO SET_LEVEL_0
-#define DEBUG_LVL_HEUR SET_LEVEL_0
-#define DEBUG_LVL_ILP SET_LEVEL_0
-
#define MIS_HEUR_TRIGGER 8
-
typedef int(*cost_fct_t)(ir_node*, ir_node*, int);
/**
#define list_entry_units(lh) list_entry(lh, unit_t, units)
+#define get_Copy_src(irn) (get_irn_n(get_Proj_pred(irn), get_Proj_proj(irn)))
+#define is_Perm(arch_env, irn) (arch_irn_classify(arch_env, irn) == arch_irn_class_perm)
+#define is_Reg_Phi(irn) (is_Phi(irn) && mode_is_data(get_irn_mode(irn)))
+#define is_Perm_Proj(arch_env, irn) (is_Proj(irn) && is_Perm(arch_env, get_Proj_pred(irn)))
+#define is_2addr_code(arch_env, irn, req) (arch_get_register_req(arch_env, req, irn, -1)->type == arch_register_req_type_should_be_same)
+
/**
* Generate the problem. Collect all infos and optimizable nodes.
*/
void free_copy_opt(copy_opt_t *co);
-#define get_Copy_src(irn) (get_irn_n(get_Proj_pred(irn), get_Proj_proj(irn)))
-#define is_Perm(arch_env, irn) (arch_irn_classify(arch_env, irn) == arch_irn_class_perm)
-
-#define is_Reg_Phi(irn) (is_Phi(irn) && mode_is_data(get_irn_mode(irn)))
-#define is_Copy(arch_env, irn) (is_Proj(irn) && is_Perm(arch_env, get_Proj_pred(irn)))
-#define is_2addr_code(arch_env, irn, req) (arch_get_register_req(arch_env, req, irn, -1)->type == arch_register_req_type_should_be_same)
-
/**
* Checks if a node is optimizable, viz. has somthing to do with coalescing
* @param arch The architecture environment
* @param irn The irn to check
* @param req A register_requirement structure (used to check for 2-addr-code)
*/
-#define is_optimizable(arch, irn, req) (is_Reg_Phi(irn) || is_Copy(arch, irn) || is_2addr_code(arch, irn, req))
+#define is_optimizable(arch, irn, req) (is_Reg_Phi(irn) || is_Perm_Proj(arch, irn) || is_2addr_code(arch, irn, req))
/**
* Checks if the irn is a non-interfering argument of a node which 'is_optimizable'
* Licence: This file protected by GPL - GNU GENERAL PUBLIC LICENSE.
* Main file for the optimization reducing the copies needed for:
- * - phi coalescing
- * - register-constrained nodes
+ * - Phi coalescing
+ * - Register-constrained nodes
+ * - Two-address code instructions
*/
+
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include "phiclass.h"
#define DO_HEUR
-#undef DO_ILP_5_SEC
-#undef DO_ILP_30_SEC
+#undef DO_CLASSES
#undef DO_ILP
-#define DEBUG_LVL SET_LEVEL_1
static firm_dbg_module_t *dbg = NULL;
-void be_copy_opt_init(void) {
- dbg = firm_dbg_register("ir.be.copyoptmain");
- firm_dbg_set_mask(dbg, DEBUG_LVL);
-}
+
+/**
+ * Helpers for saving and restoring colors of nodes.
+ * Used to get dependable and comparable benchmark results.
+ */
+#if (defined(DO_HEUR) && defined(DO_BETTER)) || (defined(DO_HEUR) && defined(DO_ILP)) || (defined(DO_BETTER) && defined(DO_ILP))
typedef struct color_saver {
arch_env_t *arch_env;
be_chordal_env_t *chordal_env;
pmap *saved_colors;
- int flag; /* 0 save; 1 load */
+ int flag; /* 0 save, 1 load */
} color_save_t;
static void save_load(ir_node *irn, void *env) {
irg_walk_graph(color_saver->chordal_env->irg, save_load, NULL, color_saver);
}
+#endif /* Need save/load stuff */
+
+
+
+void be_copy_opt_init(void) {
+ dbg = firm_dbg_register("ir.be.copyoptmain");
+}
+
+
+
void be_copy_opt(be_chordal_env_t *chordal_env) {
copy_opt_t *co;
- int costs, costs_init=-1, costs_heur=-1, costs_ilp_5_sec=-1, costs_ilp_30_sec=-1, costs_ilp=-1;
- int lower_bound = -1;
- int was_optimal = 0;
+#ifdef DO_STAT
+ lc_timer_t *timer;
color_save_t saver;
- saver.arch_env = chordal_env->main_env->arch_env;
- saver.chordal_env = chordal_env;
- saver.saved_colors = pmap_create();
+ int costs, costs_inevit, costs_init, costs_heur, costs_classes, costs_ilp, lower_bound;
+#endif
- /* BETTER: You can remove this if you replace all
- * `grep get_irn_out *.c` by the irouts.h module.*/
- compute_irg_outs(chordal_env->irg);
co = new_copy_opt(chordal_env, get_costs_loop_depth);
DBG((dbg, LEVEL_1, "----> CO: %s\n", co->name));
phi_class_compute(chordal_env->irg);
+
#ifdef DO_STAT
- lower_bound = co_get_lower_bound(co);
- DBG((dbg, LEVEL_1, "Lower Bound: %3d\n", lower_bound));
- DBG((dbg, LEVEL_1, "Inevit Costs: %3d\n", co_get_inevit_copy_costs(co)));
-
- costs = co_get_copy_costs(co);
- costs_init = costs;
- copystat_add_max_costs(co_get_max_copy_costs(co));
- copystat_add_inevit_costs(co_get_inevit_copy_costs(co));
- copystat_add_init_costs(costs_init);
- DBG((dbg, LEVEL_1, "Init costs: %3d\n", costs_init));
+#if (defined(DO_HEUR) && defined(DO_BETTER)) || (defined(DO_HEUR) && defined(DO_ILP)) || (defined(DO_BETTER) && defined(DO_ILP))
+ saver.arch_env = chordal_env->main_env->arch_env;
+ saver.chordal_env = chordal_env;
+ saver.saved_colors = pmap_create();
+ save_colors(&saver);
+#endif
+
+ costs_inevit = co_get_inevit_copy_costs(co);
+ lower_bound = co_get_lower_bound(co);
+ costs_init = co_get_copy_costs(co);
+
+ DBG((dbg, LEVEL_1, "Inevit Costs: %3d\n", costs_inevit));
+ DBG((dbg, LEVEL_1, "Lower Bound: %3d\n", lower_bound));
+ DBG((dbg, LEVEL_1, "Init costs: %3d\n", costs_init));
+
+ copystat_add_inevit_costs(costs_inevit);
+ copystat_add_init_costs(costs_init);
+ copystat_add_max_costs(co_get_max_copy_costs(co));
#endif
-// save_colors(&saver);
#ifdef DO_HEUR
- {
- lc_timer_t *timer = lc_timer_register("heur", NULL);
- lc_timer_reset_and_start(timer);
- co_heur_opt(co);
- lc_timer_stop(timer);
- copystat_add_heur_time(lc_timer_elapsed_msec(timer));
- }
#ifdef DO_STAT
- costs = co_get_copy_costs(co);
- costs_heur = costs;
- copystat_add_heur_costs(costs_heur);
- DBG((dbg, LEVEL_1, "Heur costs: %3d\n", costs_heur));
+ timer = lc_timer_register("heur", NULL);
+ lc_timer_reset_and_start(timer);
#endif
- assert(lower_bound == -1 || costs_heur == -1 || lower_bound <= costs_heur);
+
+ co_heur_opt(co);
+
+#ifdef DO_STAT
+ lc_timer_stop(timer);
+ costs_heur = co_get_copy_costs(co);
+ DBG((dbg, LEVEL_1, "Heur costs: %3d\n", costs_heur));
+ copystat_add_heur_time(lc_timer_elapsed_msec(timer));
+ copystat_add_heur_costs(costs_heur);
+ assert(lower_bound <= costs_heur);
#endif
+#endif /* DO_HEUR */
-#ifdef DO_ILP_5_SEC
- load_colors(&saver);
- was_optimal = co_ilp_opt(co, 5.0);
+
+
+#ifdef DO_CLASSES
#ifdef DO_STAT
- costs = co_get_copy_costs(co);
- costs_ilp_5_sec = costs;
- copystat_add_ilp_5_sec_costs(costs_ilp_5_sec);
- DBG((dbg, LEVEL_1, "5_Sec costs: %3d\n", costs_ilp_5_sec));
+#ifdef DO_HEUR
+ load_colors(&saver);
#endif
+ timer = lc_timer_register("classes", NULL);
+ lc_timer_reset_and_start(timer);
#endif
-#ifdef DO_ILP_30_SEC
- if (!was_optimal) {
- load_colors(&saver);
- co_ilp_opt(co, 30.0);
- }
+ co_classes_opt(co);
+
#ifdef DO_STAT
- costs = co_get_copy_costs(co);
- costs_ilp_30_sec = costs;
- copystat_add_ilp_30_sec_costs(costs_ilp_30_sec);
- DBG((dbg, LEVEL_1, "30_Sec costs: %3d\n", costs_ilp_30_sec));
-#endif
+ lc_timer_stop(timer);
+ costs_classes = co_get_copy_costs(co);
+ DBG((dbg, LEVEL_1, "Classes costs: %3d\n", costs_classes));
+ copystat_add_classes_time(lc_timer_elapsed_msec(timer));
+ copystat_add_classes_costs(costs_heur);
+ assert(lower_bound <= costs_classes);
#endif
+#endif /* DO_CLASSES */
+
+
#ifdef DO_ILP
+#ifdef DO_STAT
+#if defined(DO_HEUR) || defined(DO_CLASSES)
load_colors(&saver);
+#endif
+#endif
+
co_ilp_opt(co, 60.0);
+
#ifdef DO_STAT
- costs = co_get_copy_costs(co);
- costs_ilp = costs;
- copystat_add_opt_costs(costs_ilp);
+ costs_ilp = co_get_copy_costs(co);
DBG((dbg, LEVEL_1, "Opt costs: %3d\n", costs_ilp));
+ copystat_add_opt_costs(costs_ilp);
+ assert(lower_bound <= costs_ilp);
#endif
- assert(lower_bound == -1 || costs_ilp == -1 || lower_bound <= costs_ilp);
-#endif
+#endif /* DO_ILP */
+
+#ifdef DO_STAT
+#if (defined(DO_HEUR) && defined(DO_BETTER)) || (defined(DO_HEUR) && defined(DO_ILP)) || (defined(DO_BETTER) && defined(DO_ILP))
pmap_destroy(saver.saved_colors);
+#endif
+#endif
free_copy_opt(co);
}
* Copyright: (c) Universitaet Karlsruhe
* Licence: This file protected by GPL - GNU GENERAL PUBLIC LICENSE.
- * Main header for the optimization reducing the copy costs needed for:
- * - phi coalescing
- * - register-constrained nodes
+ * Main file for the optimization reducing the copies needed for:
+ * - Phi coalescing
+ * - Register-constrained nodes
+ * - Two-address code instructions
*/
#ifndef _BECOPYOPTMAIN_H
void be_copy_opt_init(void);
void be_copy_opt(be_chordal_env_t *chordal_env);
-void be_copy_opt_verify(be_chordal_env_t *chordal_env);
#endif
if (is_Reg_Phi(node)) /* collect phis */
pset_insert_ptr(all_phi_nodes, node);
- if (is_Copy(arch_env, node))
+ if (is_Perm_Proj(arch_env, node))
pset_insert_ptr(all_copy_nodes, node);
+
+ /* TODO: Add 2-Addr-Code nodes */
}
static void copystat_collect_irg(ir_graph *irg, arch_env_t *arch_env) {
void be_ifg_check(const be_ifg_t *ifg)
{
- void *iter1 = be_ifg_neighbours_iter_alloca(ifg);
+ void *iter1 = be_ifg_nodes_iter_alloca(ifg);
void *iter2 = be_ifg_neighbours_iter_alloca(ifg);
ir_node *n, *m;
#include "irgwalk.h"
#include "be_t.h"
+#include "belive_t.h"
#include "bera.h"
#include "beifg_t.h"
#include "bechordal_t.h"
nodes_iter_t *it = iter;
obstack_init(&it->obst);
- it->n = 0;
- it->curr = 0;
+ it->n = 0;
+ it->curr = 0;
+ it->env = ifg->env;
irg_block_walk_graph(ifg->env->irg, nodes_walker, NULL, iter);
it->nodes = obstack_finish(&it->obst);
typedef struct _adj_iter_t {
const be_chordal_env_t *env;
const ir_node *irn;
- struct obstack obst;
- int degree;
- unsigned visited_nr;
- unsigned build_list : 1;
-
- int curr;
- ir_node **neighbours;
+ int reached_end;
+ pset *neighbours;
} adj_iter_t;
static void find_neighbour_walker(ir_node *block, void *data)
{
adj_iter_t *it = data;
- unsigned visited = it->visited_nr;
struct list_head *head = get_block_border_head(it->env, block);
border_t *b;
int has_started = 0;
+ if(!is_live_in(block, it->irn) && block != get_nodes_block(it->irn))
+ return;
+
foreach_border_head(head, b) {
ir_node *irn = b->irn;
- if(irn == it->irn)
- has_started = b->is_def;
-
- /*
- * If the def/use of the node is inside the live range
- * of the node in question, they interfere.
- * To avoid that a node is added twice, we record the
- * visit in the visited number provided by core firm.
- */
- else if(has_started && get_irn_visited(irn) < visited) {
- if(it->build_list)
- obstack_ptr_grow(&it->obst, irn);
-
- set_irn_visited(irn, visited);
- it->degree++;
+ if(irn == it->irn) {
+ if(b->is_def)
+ has_started = 1;
+ else
+ break; /* if we reached the end of the node's lifetime we can safely break */
+ }
+ else if(b->is_def) {
+ /* if any other node than the one in question starts living, add it to the set */
+ pset_insert_ptr(it->neighbours, irn);
+ }
+ else if(!has_started) {
+ /* we only delete, if the live range in question has not yet started */
+ pset_remove_ptr(it->neighbours, irn);
}
+
}
}
-static void find_neighbours(const ifg_std_t *ifg, adj_iter_t *it, const ir_node *irn, int build_list)
+static void find_neighbours(const ifg_std_t *ifg, adj_iter_t *it, const ir_node *irn)
{
- if(build_list)
- obstack_init(&it->obst);
-
- it->env = ifg->env;
- it->irn = irn;
- it->degree = 0;
- it->visited_nr = get_irg_visited(ifg->env->irg) + 1;
- it->build_list = build_list;
- it->neighbours = NULL;
- it->curr = 0;
+ it->env = ifg->env;
+ it->irn = irn;
+ it->neighbours = pset_new_ptr(16);
+ it->reached_end = 0;
- set_irg_visited(ifg->env->irg, it->visited_nr);
dom_tree_walk(get_nodes_block(irn), find_neighbour_walker, NULL, it);
-
- if(build_list)
- it->neighbours = obstack_finish(&it->obst);
}
static INLINE void neighbours_break(adj_iter_t *it, int force)
{
- if((it->curr >= it->degree || force) && it->neighbours) {
- obstack_free(&it->obst, NULL);
+ if((it->reached_end || force) && it->neighbours) {
+ del_pset(it->neighbours);
it->neighbours = NULL;
}
}
static ir_node *get_next_neighbour(adj_iter_t *it) {
- ir_node *res = NULL;
-
- if(it->curr < it->degree)
- res = it->neighbours[it->curr++];
+ ir_node *res = pset_next(it->neighbours);
+ it->reached_end = res == NULL;
neighbours_break(it, 0);
return res;
static ir_node *ifg_std_neighbours_begin(const void *self, void *iter, const ir_node *irn)
{
- find_neighbours(self, iter, irn, 1);
- return get_next_neighbour(iter);
+ adj_iter_t *it = iter;
+ find_neighbours(self, iter, irn);
+ return pset_first(it->neighbours);
}
static ir_node *ifg_std_neighbours_next(const void *self, void *iter)
static int ifg_std_degree(const void *self, const ir_node *irn)
{
adj_iter_t it;
- find_neighbours(self, &it, irn, 0);
- return it.degree;
+ int degree;
+ find_neighbours(self, &it, irn);
+ degree = pset_count(it.neighbours);
+ neighbours_break(&it, 1);
+ return degree;
}
static const be_ifg_impl_t ifg_std_impl = {
#endif
+void be_ifg_check(const be_ifg_t *ifg);
+
#endif /*_BEIFG_T_H_*/
static const be_ra_t *ra = &be_ra_chordal_allocator;
/* back end instruction set architecture to use */
-static const arch_isa_if_t *isa_if = &ia32_isa_if;
+static const arch_isa_if_t *isa_if = &firm_isa;
#ifdef WITH_LIBCORE