X-Git-Url: http://nsz.repo.hu/git/?a=blobdiff_plain;f=ir%2Fbe%2Fbecopyilp2.c;h=db68195be7db19a9bf65746d11b3ec38d0db291d;hb=fcb579b8959da1d7563b1a7b9f008a423ffdf75a;hp=f1703fb7d555a024832140b89913209f3834d314;hpb=87d3e7eba011a02e25e216fc299dd41f82d6e30d;p=libfirm diff --git a/ir/be/becopyilp2.c b/ir/be/becopyilp2.c index f1703fb7d..db68195be 100644 --- a/ir/be/becopyilp2.c +++ b/ir/be/becopyilp2.c @@ -1,9 +1,28 @@ -/** - * Author: Daniel Grund - * Date: 28.02.2006 - * Copyright: (c) Universitaet Karlsruhe - * Licence: This file protected by GPL - GNU GENERAL PUBLIC LICENSE. +/* + * Copyright (C) 1995-2008 University of Karlsruhe. All right reserved. + * + * 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. + */ + +/** + * @file + * @brief ILP based copy minimization. + * @author Daniel Grund + * @date 28.02.2006 + * @version $Id$ * * ILP formalization using G=(V, E, Q): * - 2 class of variables: coloring vars x_ic and equal color vars y_ij @@ -25,14 +44,16 @@ * * x_nc, y_ij \in N, w_ij \in R^+ */ - #ifdef HAVE_CONFIG_H #include "config.h" #endif /* HAVE_CONFIG_H */ +#include "firm_config.h" + #ifdef WITH_ILP -#include +#include "bitset.h" +#include "raw_bitset.h" #include "pdeq.h" #include "irtools.h" @@ -44,15 +65,17 @@ #define DEBUG_LVL 1 typedef struct _local_env_t { - firm_dbg_module_t *dbg; double time_limit; int first_x_var, last_x_var; + int n_colors; + bitset_t *normal_colors; pmap *nr_2_irn; + DEBUG_ONLY(firm_dbg_module_t *dbg;) } local_env_t; static void build_coloring_cstr(ilp_env_t *ienv) { - be_ifg_t *ifg = ienv->co->cenv->ifg; - void *iter = be_ifg_nodes_iter_alloca(ifg); + be_ifg_t *ifg = ienv->co->cenv->ifg; + void *iter = be_ifg_nodes_iter_alloca(ifg); bitset_t *colors; ir_node *irn; char buf[16]; @@ -61,28 +84,32 @@ static void build_coloring_cstr(ilp_env_t *ienv) { be_ifg_foreach_node(ifg, iter, irn) if (!sr_is_removed(ienv->sr, irn)) { - int col, cst_idx; - arch_register_req_t req; - int curr_node_color = get_irn_col(ienv->co, irn); - int node_nr = (int)get_irn_node_nr(irn); + bitset_pos_t col; + int cst_idx; + const arch_register_req_t *req; + int curr_node_color = get_irn_col(irn); + int node_nr = (int)get_irn_idx(irn); local_env_t *lenv = ienv->env; pmap_insert(lenv->nr_2_irn, INT_TO_PTR(node_nr), irn); - arch_get_register_req(ienv->co->aenv, &req, irn, -1); + req = arch_get_register_req(irn, -1); + + bitset_clear_all(colors); /* get assignable colors */ - if (arch_register_req_is(&req, limited)) - req.limited(req.limited_env, colors); - else - arch_put_non_ignore_regs(ienv->co->aenv, req.cls, colors); + if (arch_register_req_is(req, limited)) { + rbitset_copy_to_bitset(req->limited, colors); + } else { + bitset_copy(colors, lenv->normal_colors); + } /* add the coloring constraint */ cst_idx = lpp_add_cst(ienv->lp, NULL, lpp_equal, 1.0); bitset_foreach(colors, col) { int var_idx = lpp_add_var(ienv->lp, name_cdd(buf, 'x', node_nr, col), lpp_binary, 0.0); - lpp_set_start_value(ienv->lp, var_idx, (col == curr_node_color) ? 1.0 : 0.0); + lpp_set_start_value(ienv->lp, var_idx, (col == (unsigned) curr_node_color) ? 1.0 : 0.0); lpp_set_factor_fast(ienv->lp, cst_idx, var_idx, 1); lenv->last_x_var = var_idx; @@ -103,9 +130,10 @@ static void build_coloring_cstr(ilp_env_t *ienv) { } static void build_interference_cstr(ilp_env_t *ienv) { - lpp_t *lpp = ienv->lp; - be_ifg_t *ifg = ienv->co->cenv->ifg; - int n_colors = arch_register_class_n_regs(ienv->co->cls); + lpp_t *lpp = ienv->lp; + local_env_t *lenv = ienv->env; + be_ifg_t *ifg = ienv->co->cenv->ifg; + int n_colors = lenv->n_colors; int i, col; void *iter = be_ifg_cliques_iter_alloca(ifg); @@ -134,7 +162,7 @@ static void build_interference_cstr(ilp_env_t *ienv) { ir_node *irn = clique[i]; if (!sr_is_removed(ienv->sr, irn)) { - int var_idx = lpp_get_var_idx(lpp, name_cdd(buf, 'x', (int)get_irn_node_nr(irn), col)); + int var_idx = lpp_get_var_idx(lpp, name_cdd(buf, 'x', (int)get_irn_idx(irn), col)); lpp_set_factor_fast(lpp, cst_idx, var_idx, 1); } } @@ -142,9 +170,16 @@ static void build_interference_cstr(ilp_env_t *ienv) { } } + +/** + * TODO: Remove the dependency of the opt-units data structure + * by walking over all affinity edges. Graph structure + * does not provide this walker, yet. + */ static void build_affinity_cstr(ilp_env_t *ienv) { + local_env_t *lenv = ienv->env; + int n_colors = lenv->n_colors; unit_t *curr; - int n_colors = arch_register_class_n_regs(ienv->co->cls); /* for all optimization units */ list_for_each_entry(unit_t, curr, &ienv->co->units, units) { @@ -154,13 +189,13 @@ static void build_affinity_cstr(ilp_env_t *ienv) { int root_col, arg_col; root = curr->nodes[0]; - root_nr = (int) get_irn_node_nr(root); - root_col = get_irn_col(ienv->co, root); + root_nr = (int) get_irn_idx(root); + root_col = get_irn_col(root); for (i = 1; i < curr->node_count; ++i) { arg = curr->nodes[i]; - arg_nr = (int) get_irn_node_nr(arg); - arg_col = get_irn_col(ienv->co, arg); + arg_nr = (int) get_irn_idx(arg); + arg_col = get_irn_col(arg); /* add a new affinity variable */ y_idx = lpp_add_var(ienv->lp, name_cdd_sorted(buf, 'y', root_nr, arg_nr), lpp_binary, curr->costs[i]); @@ -190,11 +225,12 @@ typedef struct _edge_t { static int compare_edge_t(const void *k1, const void *k2, size_t size) { const edge_t *e1 = k1; const edge_t *e2 = k2; + (void) size; return ! (e1->n1 == e2->n1 && e1->n2 == e2->n2); } -#define HASH_EDGE(e) (HASH_PTR((e)->n1) ^ HASH_PTR((e)->n2)) +#define HASH_EDGE(e) (hash_irn((e)->n1) ^ hash_irn((e)->n2)) static INLINE edge_t *add_edge(set *edges, ir_node *n1, ir_node *n2, int *counter) { edge_t new_edge; @@ -249,25 +285,30 @@ static INLINE void remove_edge(set *edges, ir_node *n1, ir_node *n2, int *counte * At most 1 node of the clique can be colored equally with the external node. */ static void build_clique_star_cstr(ilp_env_t *ienv) { - affinity_t *aff; + affinity_node_t *aff; /* for each node with affinity edges */ co_gs_foreach_aff_node(ienv->co, aff) { struct obstack ob; neighb_t *nbr; - ir_node *center = aff->irn; + const ir_node *center = aff->irn; ir_node **nodes; set *edges; int i, o, n_nodes, n_edges; + if (arch_irn_is(aff->irn, ignore)) + continue; + obstack_init(&ob); edges = new_set(compare_edge_t, 8); /* get all affinity neighbours */ n_nodes = 0; co_gs_foreach_neighb(aff, nbr) { - obstack_ptr_grow(&ob, nbr->irn); - ++n_nodes; + if (!arch_irn_is(nbr->irn, ignore)) { + obstack_ptr_grow(&ob, nbr->irn); + ++n_nodes; + } } nodes = obstack_finish(&ob); @@ -288,6 +329,9 @@ static void build_clique_star_cstr(ilp_env_t *ienv) { for (e=set_first(edges); !e->n1; e=set_next(edges)) /*nothing*/ ; + /* we could be stepped out of the loop before the set iterated to the end */ + set_break(edges); + pset_insert_ptr(clique, e->n1); pset_insert_ptr(clique, e->n2); remove_edge(edges, e->n1, e->n2, &n_edges); @@ -336,10 +380,10 @@ static void build_clique_star_cstr(ilp_env_t *ienv) { char buf[16]; cst_idx = lpp_add_cst(ienv->lp, NULL, lpp_greater, pset_count(clique)-1); - center_nr = get_irn_node_nr(center); + center_nr = get_irn_idx(center); pset_foreach(clique, member) { - member_nr = get_irn_node_nr(member); + member_nr = get_irn_idx(member); var_idx = lpp_get_var_idx(ienv->lp, name_cdd_sorted(buf, 'y', center_nr, member_nr)); lpp_set_factor_fast(ienv->lp, cst_idx, var_idx, 1.0); } @@ -354,17 +398,20 @@ static void build_clique_star_cstr(ilp_env_t *ienv) { } -static void extend_path(ilp_env_t *ienv, pdeq *path, ir_node *irn) { +static void extend_path(ilp_env_t *ienv, pdeq *path, const ir_node *irn) { be_ifg_t *ifg = ienv->co->cenv->ifg; int i, len; ir_node **curr_path; - affinity_t *aff; + affinity_node_t *aff; neighb_t *nbr; /* do not walk backwards or in circles */ if (pdeq_contains(path, irn)) return; + if (arch_irn_is(irn, ignore)) + return; + /* insert the new irn */ pdeq_putr(path, irn); @@ -373,7 +420,7 @@ static void extend_path(ilp_env_t *ienv, pdeq *path, ir_node *irn) { /* check for forbidden interferences */ len = pdeq_len(path); curr_path = alloca(len * sizeof(*curr_path)); - pdeq_copyl(path, curr_path); + pdeq_copyl(path, (const void **)curr_path); for (i=1; ilp, NULL, lpp_greater, 1.0); for (i=1; ilp, name_cdd_sorted(buf, 'y', nr_1, nr_2)); lpp_set_factor_fast(ienv->lp, cst_idx, var_idx, 1.0); } @@ -423,7 +470,7 @@ end: * Then at least one of these affinity edges must break. */ static void build_path_cstr(ilp_env_t *ienv) { - affinity_t *aff_info; + affinity_node_t *aff_info; /* for each node with affinity edges */ co_gs_foreach_aff_node(ienv->co, aff_info) { @@ -453,16 +500,14 @@ static void ilp2_build(ilp_env_t *ienv) { static void ilp2_apply(ilp_env_t *ienv) { local_env_t *lenv = ienv->env; - double *sol; - lpp_sol_state_t state; - int i, count; + int i; /* first check if there was sth. to optimize */ if (lenv->first_x_var >= 0) { + 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); - count = lenv->last_x_var - lenv->first_x_var + 1; - sol = xmalloc(count * sizeof(sol[0])); - state = lpp_get_solution(ienv->lp, sol, lenv->first_x_var, lenv->last_x_var); if (state != lpp_optimal) { printf("WARNING %s: Solution state is not 'optimal': %d\n", ienv->co->name, state); assert(state >= lpp_feasible && "The solution should at least be feasible!"); @@ -484,6 +529,8 @@ static void ilp2_apply(ilp_env_t *ienv) { assert(0 && "This should be a x-var"); } } + + xfree(sol); } #ifdef COPYOPT_STAT @@ -495,17 +542,24 @@ static void ilp2_apply(ilp_env_t *ienv) { #endif } -int co_solve_ilp2(copy_opt_t *co, double time_limit) { +int co_solve_ilp2(copy_opt_t *co) { lpp_sol_state_t sol_state; ilp_env_t *ienv; local_env_t my; - my.time_limit = time_limit; + ASSERT_OU_AVAIL(co); //See build_clique_st + ASSERT_GS_AVAIL(co); + + my.time_limit = 0; my.first_x_var = -1; my.last_x_var = -1; my.nr_2_irn = pmap_create(); - my.dbg = firm_dbg_register("ir.be.coilp2"); - firm_dbg_set_mask(my.dbg, DEBUG_LVL); + FIRM_DBG_REGISTER(my.dbg, "firm.be.coilp2"); + + my.normal_colors = bitset_alloca(arch_register_class_n_regs(co->cls)); + bitset_clear_all(my.normal_colors); + arch_put_non_ignore_regs(co->cls, my.normal_colors); + my.n_colors = bitset_popcnt(my.normal_colors); ienv = new_ilp_env(co, ilp2_build, ilp2_apply, &my); @@ -519,7 +573,7 @@ int co_solve_ilp2(copy_opt_t *co, double time_limit) { #else /* WITH_ILP */ -static void only_that_you_can_compile_without_WITH_ILP_defined(void) { +static INLINE void only_that_you_can_compile_without_WITH_ILP_defined(void) { } #endif /* WITH_ILP */