Add a FixedTied constraint kind for operand constraints.

Fixes #175.

The Intel division instructions have fixed input operands that are
clobbered by fixed output operands, so the value passed as an input will
be clobbered just like a tied operand.

The FixedTied operand constraint is used to indicate a fixed input
operand that has a corresponding output operand with the same fixed
register.

Teach the spiller to teach a FixedTied operand the same as a Tied
operand constraint and make sure that the input value is killed by the
instruction.
This commit is contained in:
Jakob Stoklund Olesen
2017-10-25 11:14:11 -07:00
parent 2932a9314d
commit e8ecf1f809
7 changed files with 72 additions and 18 deletions

View File

@@ -478,7 +478,8 @@ impl<'a> Context<'a> {
// already in a register.
let cur_reg = self.divert.reg(value, &self.cur.func.locations);
match op.kind {
ConstraintKind::FixedReg(regunit) => {
ConstraintKind::FixedReg(regunit) |
ConstraintKind::FixedTied(regunit) => {
if regunit != cur_reg {
self.solver.reassign_in(
value,
@@ -532,7 +533,9 @@ impl<'a> Context<'a> {
}
}
}
_ => {}
ConstraintKind::FixedReg(_) |
ConstraintKind::FixedTied(_) |
ConstraintKind::Stack => {}
}
}
}
@@ -674,8 +677,15 @@ impl<'a> Context<'a> {
throughs: &[LiveValue],
) {
for (op, lv) in constraints.iter().zip(defs) {
if let ConstraintKind::FixedReg(reg) = op.kind {
self.add_fixed_output(lv.value, op.regclass, reg, throughs);
match op.kind {
ConstraintKind::FixedReg(reg) |
ConstraintKind::FixedTied(reg) => {
self.add_fixed_output(lv.value, op.regclass, reg, throughs);
}
ConstraintKind::Reg |
ConstraintKind::Tied(_) |
ConstraintKind::Stack => {}
}
}
}
@@ -741,6 +751,7 @@ impl<'a> Context<'a> {
for (op, lv) in constraints.iter().zip(defs) {
match op.kind {
ConstraintKind::FixedReg(_) |
ConstraintKind::FixedTied(_) |
ConstraintKind::Stack => continue,
ConstraintKind::Reg => {
self.solver.add_def(lv.value, op.regclass, !lv.is_local);

View File

@@ -301,6 +301,10 @@ impl<'a> Context<'a> {
// A tied operand must kill the used value.
reguse.tied = !lr.killed_at(inst, ebb, &self.cur.func.layout);
}
ConstraintKind::FixedTied(_) => {
reguse.fixed = true;
reguse.tied = !lr.killed_at(inst, ebb, &self.cur.func.layout);
}
ConstraintKind::Reg => {}
}
if lr.affinity.is_stack() {