Avoid making solver variables for fixed input constraints.

When the coloring pass sees an instruction with a fixed input register
constraint that is already satisfied, make sure to tell the solver
about it anyway.

There are situations where the solver wants to convert a value to a
solver variable, and we can't allow that if the same value is also used
for a fixed register operand.

Fixes #221.
This commit is contained in:
Jakob Stoklund Olesen
2018-01-17 14:58:05 -08:00
parent 13af22b46b
commit 0a6500c99a
2 changed files with 38 additions and 8 deletions

View File

@@ -0,0 +1,29 @@
test regalloc
set is_64bit
isa intel haswell
; Test combinations of constraints.
;
; The Intel ushr instruction requires its second operand to be passed in %rcx and its output is
; tied to the first input operand.
;
; If we pass the same value to both operands, both constraints must be satisfied.
; Found by the Binaryen fuzzer in PR221.
;
; Conditions triggering the problem:
;
; - The same value used for a tied operand and a fixed operand.
; - The common value is already in %rcx.
; - The tied output value is live outside the EBB.
;
; Under these conditions, Solver::add_tied_input() would create a variable for the tied input
; without considering the fixed constraint.
function %pr221(i64 [%rdi], i64 [%rsi], i64 [%rdx], i64 [%rcx]) -> i64 [%rax] {
ebb0(v0: i64, v1: i64, v2: i64, v3: i64):
v4 = ushr v3, v3
jump ebb1
ebb1:
return v4
}

View File

@@ -499,14 +499,15 @@ impl<'a> Context<'a> {
match op.kind {
ConstraintKind::FixedReg(regunit) |
ConstraintKind::FixedTied(regunit) => {
if regunit != cur_reg {
self.solver.reassign_in(
value,
op.regclass,
cur_reg,
regunit,
);
}
// Add the fixed constraint even if `cur_reg == regunit`.
// It is possible that we will want to convert the value to a variable later,
// and this identity assignment prevents that from happening.
self.solver.reassign_in(
value,
op.regclass,
cur_reg,
regunit,
);
}
ConstraintKind::Reg |
ConstraintKind::Tied(_) => {