* @param node the node
* @param reg the register
*/
-static void use_reg(ir_node *node, const arch_register_t *reg)
+static void use_reg(ir_node *node, const arch_register_t *reg, unsigned width)
{
unsigned r = arch_register_get_index(reg);
- assignments[r] = node;
+ for (unsigned r0 = r; r0 < r + width; ++r0)
+ assignments[r0] = node;
arch_set_irn_register(node, reg);
}
if (!arch_irn_consider_in_reg_alloc(cls, node))
return;
- const arch_register_t *reg = arch_get_irn_register(node);
- unsigned r = arch_register_get_index(reg);
+ const arch_register_t *reg = arch_get_irn_register(node);
+ const arch_register_req_t *req = arch_get_irn_register_req(node);
+ unsigned r = arch_register_get_index(reg);
/* assignment->value may be NULL if a value is used at 2 inputs
- so it gets freed twice. */
- assert(assignments[r] == node || assignments[r] == NULL);
- assignments[r] = NULL;
+ * so it gets freed twice. */
+ for (unsigned r0 = r; r0 < r + req->width; ++r0) {
+ assert(assignments[r0] == node || assignments[r0] == NULL);
+ assignments[r0] = NULL;
+ }
}
/**
if (i >= n_regs)
return false;
- const arch_register_t *reg = arch_register_for_index(cls, r);
- ir_node *copy = be_new_Copy(block, to_split);
+ const arch_register_t *reg = arch_register_for_index(cls, r);
+ ir_node *copy = be_new_Copy(block, to_split);
+ unsigned width = 1;
mark_as_copy_of(copy, to_split);
/* hacky, but correct here */
if (assignments[arch_register_get_index(from_reg)] == to_split)
free_reg_of_value(to_split);
- use_reg(copy, reg);
+ use_reg(copy, reg, width);
sched_add_before(before, copy);
DB((dbg, LEVEL_3,
{
assert(!is_Phi(node));
/* preassigned register? */
- const arch_register_t *final_reg = arch_get_irn_register(node);
+ 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;
if (final_reg != NULL) {
DB((dbg, LEVEL_2, "Preassignment %+F -> %s\n", node, final_reg->name));
- use_reg(node, final_reg);
+ use_reg(node, final_reg, width);
return;
}
- const arch_register_req_t *req = arch_get_irn_register_req(node);
/* ignore reqs must be preassigned */
assert (! (req->type & arch_register_req_type_ignore));
if (!rbitset_is_set(allowed_regs, final_reg_index))
continue;
/* alignment constraint? */
- if (req->width > 1 && (req->type & arch_register_req_type_aligned)
- && (final_reg_index % req->width) != 0)
- continue;
+ if (width > 1) {
+ if ((req->type & arch_register_req_type_aligned)
+ && (final_reg_index % width) != 0)
+ continue;
+ bool fine = true;
+ for (unsigned r0 = r+1; r0 < r+width; ++r0) {
+ if (assignments[r0] != NULL)
+ fine = false;
+ }
+ /* TODO: attempt optimistic split here */
+ if (!fine)
+ continue;
+ }
if (assignments[final_reg_index] == NULL)
break;
final_reg = arch_register_for_index(cls, final_reg_index);
DB((dbg, LEVEL_2, "Assign %+F -> %s\n", node, final_reg->name));
- use_reg(node, final_reg);
+ use_reg(node, final_reg, width);
}
/**
DB((dbg, LEVEL_2, "Copy %+F (from %+F, before %+F) -> %s\n",
copy, src, before, reg->name));
mark_as_copy_of(copy, src);
- use_reg(copy, reg);
+ unsigned width = 1; /* TODO */
+ use_reg(copy, reg, width);
if (live_nodes != NULL) {
ir_nodeset_insert(live_nodes, copy);
DB((dbg, LEVEL_2, "Perm %+F (perm %+F,%+F, before %+F)\n",
perm, in[0], in[1], before));
+ unsigned width = 1; /* TODO */
+
ir_node *proj0 = new_r_Proj(perm, get_irn_mode(in[0]), 0);
mark_as_copy_of(proj0, in[0]);
const arch_register_t *reg0 = arch_register_for_index(cls, old_r);
- use_reg(proj0, reg0);
+ use_reg(proj0, reg0, width);
ir_node *proj1 = new_r_Proj(perm, get_irn_mode(in[1]), 1);
mark_as_copy_of(proj1, in[1]);
const arch_register_t *reg1 = arch_register_for_index(cls, r2);
- use_reg(proj1, reg1);
+ use_reg(proj1, reg1, width);
/* 1 value is now in the correct register */
permutation[old_r] = old_r;
}
}
-#ifdef DEBUG_libfirm
+#ifndef NDEBUG
/* now we should only have fixpoints left */
for (unsigned r = 0; r < n_regs; ++r) {
assert(permutation[r] == r);
break;
if (!arch_irn_consider_in_reg_alloc(cls, node))
continue;
+ const arch_register_req_t *req
+ = arch_get_irn_register_req(node);
unsigned r = assignment[n++];
assert(rbitset_is_set(normal_regs, r));
const arch_register_t *reg = arch_register_for_index(cls, r);
DB((dbg, LEVEL_2, "Assign %+F -> %s\n", node, reg->name));
- use_reg(node, reg);
+ use_reg(node, reg, req->width);
/* adapt preferences for phi inputs */
if (propagate_phi_registers)
}
}
+static arch_register_req_t *allocate_reg_req(ir_graph *irg)
+{
+ struct obstack *obst = be_get_be_obst(irg);
+ arch_register_req_t *req = OALLOCZ(obst, arch_register_req_t);
+ return req;
+}
+
/**
* Walker: assign registers to all nodes of a block that
* need registers from the currently considered register class.
const arch_register_t *reg = arch_get_irn_register(node);
assert(reg != NULL); /* ignore values must be preassigned */
- use_reg(node, reg);
+ use_reg(node, reg, req->width);
continue;
}
if (need_phi) {
ir_mode *mode = get_irn_mode(node);
+ const arch_register_req_t *phi_req = cls->class_req;
+ if (req->width > 1) {
+ arch_register_req_t *new_req = allocate_reg_req(irg);
+ new_req->cls = cls;
+ new_req->type = req->type & arch_register_req_type_aligned;
+ new_req->width = req->width;
+ phi_req = new_req;
+ }
ir_node *phi = be_new_Phi(block, n_preds, phi_ins, mode,
- cls->class_req);
+ phi_req);
DB((dbg, LEVEL_3, "Create Phi %+F (for %+F) -", phi, node));
#ifdef DEBUG_libfirm
/* if the node already has a register assigned use it */
const arch_register_t *reg = arch_get_irn_register(node);
if (reg != NULL) {
- use_reg(node, reg);
+ use_reg(node, reg, req->width);
}
/* remember that this node is live at the beginning of the block */
ir_nodeset_insert(&live_nodes, node);
}
- unsigned *forbidden_regs; /**< collects registers which must
- not be used for optimistic splits */
+ unsigned *forbidden_regs; /**< collects registers which must
+ not be used for optimistic splits */
rbitset_alloca(forbidden_regs, n_regs);
/* handle phis... */
assign_phi_registers(block);
/* all live-ins must have a register */
-#ifdef DEBUG_libfirm
+#ifndef NDEBUG
foreach_ir_nodeset(&live_nodes, node, iter) {
const arch_register_t *reg = arch_get_irn_register(node);
assert(reg != NULL);