/*
- * Copyright (C) 1995-2011 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.
+ * Copyright (C) 2012 University of Karlsruhe.
*/
/**
* @param weight the weight
* @param node the current node
*/
-static void check_defs(const ir_nodeset_t *live_nodes, float weight,
- ir_node *node)
+static void check_defs(ir_nodeset_t const *const live_nodes, float const weight, ir_node *const node, arch_register_req_t const *const req)
{
- const arch_register_req_t *req = arch_get_irn_register_req(node);
if (arch_register_req_is(req, limited)) {
const unsigned *limited = req->limited;
float penalty = weight * DEF_FACTOR;
if (is_Phi(node))
break;
- be_foreach_definition(node, cls, value,
- check_defs(&live_nodes, weight, value);
+ be_foreach_definition(node, cls, value, req,
+ check_defs(&live_nodes, weight, value, req);
);
/* mark last uses */
be_liveness_transfer(cls, node, &live_nodes);
/* update weights based on usage constraints */
- for (int i = 0; i < arity; ++i) {
- ir_node *op = get_irn_n(node, i);
- if (!arch_irn_consider_in_reg_alloc(cls, op))
- continue;
-
- const arch_register_req_t *req
- = arch_get_irn_register_req_in(node, i);
+ be_foreach_use(node, cls, req, op, op_req,
if (!arch_register_req_is(req, limited))
continue;
- const unsigned *limited = req->limited;
- give_penalties_for_limits(&live_nodes, weight * USE_FACTOR,
- limited, op);
- }
+ give_penalties_for_limits(&live_nodes, weight * USE_FACTOR, req->limited, op);
+ );
}
ir_nodeset_destroy(&live_nodes);
}
-static void congruence_def(ir_nodeset_t *live_nodes, const ir_node *node)
+static void congruence_def(ir_nodeset_t *const live_nodes, ir_node const *const node, arch_register_req_t const *const req)
{
- const arch_register_req_t *req = arch_get_irn_register_req(node);
-
/* should be same constraint? */
if (arch_register_req_is(req, should_be_same)) {
const ir_node *insn = skip_Proj_const(node);
be_liveness_end_of_block(lv, cls, block, &live_nodes);
/* check should be same constraints */
- ir_node *last_phi = NULL;
sched_foreach_reverse(block, node) {
- if (is_Phi(node)) {
- last_phi = node;
+ if (is_Phi(node))
break;
- }
- be_foreach_definition(node, cls, value,
- congruence_def(&live_nodes, value);
+ be_foreach_definition(node, cls, value, req,
+ congruence_def(&live_nodes, value, req);
);
be_liveness_transfer(cls, node, &live_nodes);
}
- if (!last_phi) {
- ir_nodeset_destroy(&live_nodes);
- return;
- }
/* check phi congruence classes */
- sched_foreach_reverse_from(last_phi, phi) {
- assert(is_Phi(phi));
+ sched_foreach(block, phi) {
+ if (!is_Phi(phi))
+ break;
if (!arch_irn_consider_in_reg_alloc(cls, phi))
continue;
/**
* Determine and assign a register for node @p node
*/
-static void assign_reg(const ir_node *block, ir_node *node,
- unsigned *forbidden_regs)
+static void assign_reg(ir_node const *const block, ir_node *const node, arch_register_req_t const *const req, unsigned *const forbidden_regs)
{
assert(!is_Phi(node));
/* preassigned register? */
- const arch_register_t *final_reg = arch_get_irn_register(node);
- const arch_register_req_t *req = arch_get_irn_register_req(node);
- unsigned width = req->width;
+ arch_register_t const *final_reg = arch_get_irn_register(node);
+ unsigned const width = req->width;
if (final_reg != NULL) {
DB((dbg, LEVEL_2, "Preassignment %+F -> %s\n", node, final_reg->name));
use_reg(node, final_reg, width);
lpp_set_log(lpp, stdout);
/** mark some edges as forbidden */
- int arity = get_irn_arity(node);
- for (int i = 0; i < arity; ++i) {
- ir_node *op = get_irn_n(node, i);
- if (!arch_irn_consider_in_reg_alloc(cls, op))
- continue;
-
- const arch_register_req_t *req = arch_get_irn_register_req_in(node, i);
+ be_foreach_use(node, cls, req, op, op_req,
if (!arch_register_req_is(req, limited))
continue;
rbitset_set(forbidden_edges, current_reg*n_regs + r);
}
- }
+ );
/* add all combinations, except for not allowed ones */
for (unsigned l = 0; l < n_regs; ++l) {
* values are involved */
bool double_width = false;
bool good = true;
- int arity = get_irn_arity(node);
- for (int i = 0; i < arity; ++i) {
- ir_node *op = get_irn_n(node, i);
- if (!arch_irn_consider_in_reg_alloc(cls, op))
- continue;
-
+ be_foreach_use(node, cls, req, op, op_req,
/* are there any limitations for the i'th operand? */
- const arch_register_req_t *req = arch_get_irn_register_req_in(node, i);
if (req->width > 1)
double_width = true;
const arch_register_t *reg = arch_get_irn_register(op);
good = false;
continue;
}
- }
+ );
/* is any of the live-throughs using a constrained output register? */
unsigned *live_through_regs = NULL;
- be_foreach_definition(node, cls, value,
+ be_foreach_definition(node, cls, value, req,
(void)value;
- if (req_->width > 1)
+ if (req->width > 1)
double_width = true;
- if (!arch_register_req_is(req_, limited))
+ if (!arch_register_req_is(req, limited))
continue;
if (live_through_regs == NULL) {
live_through_regs = rbitset_alloca(n_regs);
determine_live_through_regs(live_through_regs, node);
}
- rbitset_or(forbidden_regs, req_->limited, n_regs);
- if (rbitsets_have_common(req_->limited, live_through_regs, n_regs))
+ rbitset_or(forbidden_regs, req->limited, n_regs);
+ if (rbitsets_have_common(req->limited, live_through_regs, n_regs))
good = false;
);
}
}
- for (int i = 0; i < arity; ++i) {
- ir_node *op = get_irn_n(node, i);
- if (!arch_irn_consider_in_reg_alloc(cls, op))
- continue;
-
- const arch_register_req_t *req = arch_get_irn_register_req_in(node, i);
+ be_foreach_use(node, cls, req, op, op_req,
if (!arch_register_req_is(req, limited))
continue;
continue;
hungarian_remove(bp, r, current_reg);
}
- }
+ );
//hungarian_print_cost_matrix(bp, 1);
hungarian_prepare_cost_matrix(bp, HUNGARIAN_MODE_MAXIMIZE_UTIL);
int res = hungarian_solve(bp, assignment, NULL, 0);
assert(res == 0);
-#if 0
- fprintf(stderr, "Swap result:");
- for (i = 0; i < (int) n_regs; ++i) {
- fprintf(stderr, " %d", assignment[i]);
- }
- fprintf(stderr, "\n");
-#endif
-
hungarian_free(bp);
permute_values(live_nodes, node, assignment);
if (req->cls != cls)
continue;
- if (arch_register_req_is(req, limited)) {
+ if (arch_register_req_is(req, ignore)) {
allocation_info_t *info = get_allocation_info(node);
info->current_value = node;
rewire_inputs(node);
/* we may not use registers used for inputs for optimistic splits */
- int arity = get_irn_arity(node);
- for (int i = 0; i < arity; ++i) {
- ir_node *op = get_irn_n(node, i);
- if (!arch_irn_consider_in_reg_alloc(cls, op))
- continue;
-
+ be_foreach_use(node, cls, in_req, op, op_req,
const arch_register_t *reg = arch_get_irn_register(op);
rbitset_set(forbidden_regs, reg->index);
- }
+ );
/* free registers of values last used at this instruction */
free_last_uses(&live_nodes, node);
/* assign output registers */
- be_foreach_definition_(node, cls, value,
- assign_reg(block, value, forbidden_regs);
+ be_foreach_definition_(node, cls, value, req,
+ assign_reg(block, value, req, forbidden_regs);
);
}