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:
29
cranelift/filetests/regalloc/multi-constraints.cton
Normal file
29
cranelift/filetests/regalloc/multi-constraints.cton
Normal 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
|
||||
}
|
||||
@@ -499,7 +499,9 @@ impl<'a> Context<'a> {
|
||||
match op.kind {
|
||||
ConstraintKind::FixedReg(regunit) |
|
||||
ConstraintKind::FixedTied(regunit) => {
|
||||
if regunit != cur_reg {
|
||||
// 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,
|
||||
@@ -507,7 +509,6 @@ impl<'a> Context<'a> {
|
||||
regunit,
|
||||
);
|
||||
}
|
||||
}
|
||||
ConstraintKind::Reg |
|
||||
ConstraintKind::Tied(_) => {
|
||||
if !op.regclass.contains(cur_reg) {
|
||||
|
||||
Reference in New Issue
Block a user