Allow for reused inputs when the reused vreg is also used as other (normal) uses. (#33)
The "reused input" operand constraint allows for an instruction to have
a def-operand whose allocation is constrained to reuse the same
allocation as one of the uses.
This is useful to express constraints needed for some instruction sets,
like x86, where at the ISA level, one register serves both as an input
and the output.
Unfortunately the way that we lower the constraints to liveranges does
not work if we have the same vreg used both for the reused input and
another input -- it results in impossible-to-solve constraints. For
example, the instruction
```
alu_op v42 use, v42 use, v43 def reuse(0)
```
would result in an impossible allocation.
This fixes liverange construction to properly handle all uses of the
vreg whose operand is reused, rather than just the one reused operand.
This commit is contained in:
@@ -477,11 +477,12 @@ impl<'a, F: Function> Env<'a, F> {
|
||||
|
||||
// Does the instruction have any input-reusing
|
||||
// outputs? This is important below to establish
|
||||
// proper interference wrt other inputs.
|
||||
// proper interference wrt other inputs. We note the
|
||||
// *vreg* that is reused, not the index.
|
||||
let mut reused_input = None;
|
||||
for op in self.func.inst_operands(inst) {
|
||||
if let OperandConstraint::Reuse(i) = op.constraint() {
|
||||
reused_input = Some(i);
|
||||
reused_input = Some(self.func.inst_operands(inst)[i].vreg());
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -900,11 +901,14 @@ impl<'a, F: Function> Env<'a, F> {
|
||||
(OperandKind::Use, OperandPos::Late) => ProgPoint::after(inst),
|
||||
// If there are any reused inputs in this
|
||||
// instruction, and this is *not* the
|
||||
// reused input, force `pos` to
|
||||
// `After`. (See note below for why; it's
|
||||
// very subtle!)
|
||||
// reused vreg, force `pos` to
|
||||
// `After`. This ensures that we correctly
|
||||
// account for the interference between
|
||||
// the other inputs and the
|
||||
// input-that-is-reused/output.
|
||||
(OperandKind::Use, OperandPos::Early)
|
||||
if reused_input.is_some() && reused_input.unwrap() != i =>
|
||||
if reused_input.is_some()
|
||||
&& reused_input.unwrap() != operand.vreg() =>
|
||||
{
|
||||
ProgPoint::after(inst)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user