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

@@ -754,17 +754,14 @@ def emit_recipe_constraints(isa, fmt):
for r in isa.all_recipes:
fmt.comment(r.name)
tied_i2o, tied_o2i = r.ties()
fixed_ins, fixed_outs = r.fixed_ops()
with fmt.indented('RecipeConstraints {', '},'):
emit_operand_constraints(r, r.ins, 'ins', tied_i2o, fmt)
emit_operand_constraints(r, r.outs, 'outs', tied_o2i, fmt)
fmt.format(
'fixed_ins: {},',
str(any(isinstance(c, Register)
for c in r.ins)).lower())
fmt.format(
'fixed_outs: {},',
str(any(isinstance(c, Register)
for c in r.outs)).lower())
emit_operand_constraints(
r, r.ins, 'ins', tied_i2o, fixed_outs, fmt)
emit_operand_constraints(
r, r.outs, 'outs', tied_o2i, fixed_ins, fmt)
fmt.format('fixed_ins: {},', str(bool(fixed_ins)).lower())
fmt.format('fixed_outs: {},', str(bool(fixed_outs)).lower())
fmt.format('tied_ops: {},', str(bool(tied_i2o)).lower())
fmt.format(
'clobbers_flags: {},',
@@ -776,11 +773,16 @@ def emit_operand_constraints(
seq, # type: Sequence[OperandConstraint]
field, # type: str
tied, # type: Dict[int, int]
fixops, # type: Set[Register]
fmt # type: srcgen.Formatter
):
# type: (...) -> None
"""
Emit a struct field initializer for an array of operand constraints.
:param field: The name of the struct field to emit.
:param tied: Map of tied opnums to counterparts.
:param fix_ops: Set of fixed operands on the other side of the inst.
"""
if len(seq) == 0:
fmt.line('{}: &[],'.format(field))
@@ -796,8 +798,9 @@ def emit_operand_constraints(
fmt.format('regclass: &{}_DATA,', cons)
elif isinstance(cons, Register):
assert n not in tied, "Can't tie fixed register operand"
fmt.format(
'kind: ConstraintKind::FixedReg({}),', cons.unit)
# See if this fixed register is also on the other side.
t = 'FixedTied' if cons in fixops else 'FixedReg'
fmt.format('kind: ConstraintKind::{}({}),', t, cons.unit)
fmt.format('regclass: &{}_DATA,', cons.regclass)
elif isinstance(cons, int):
# This is a tied output constraint. It should never happen