Make sure return values are assigned an affinity.

When an EBB argument value is used only as a return value, it still
needs to be given a register affinity. Otherwise it would appear as a
ghost value with no affinity.

Do the same to call arguments.
This commit is contained in:
Jakob Stoklund Olesen
2017-06-28 19:30:36 -07:00
parent c4532b901e
commit cd1503eced
2 changed files with 35 additions and 5 deletions

View File

@@ -40,3 +40,26 @@ ebb0(v1: i32, v2: i32):
; nextln: return $v2, $v1 ; nextln: return $v2, $v1
return v2, v1 return v2, v1
} }
; Return an EBB argument.
function %retebb(i32, i32) -> i32 {
ebb0(v1: i32, v2: i32):
brnz v1, ebb1(v1)
jump ebb1(v2)
ebb1(v10: i32):
return v10
}
; Pass an EBB argument as a function argument.
function %callebb(i32, i32) -> i32 {
fn0 = function %foo(i32) -> i32
ebb0(v1: i32, v2: i32):
brnz v1, ebb1(v1)
jump ebb1(v2)
ebb1(v10: i32):
v11 = call fn0(v10)
return v11
}

View File

@@ -376,9 +376,9 @@ impl Liveness {
} }
// Iterator of constraints, one per value operand. // Iterator of constraints, one per value operand.
// TODO: Should we fail here if the instruction doesn't have a valid encoding? let encoding = func.encodings[inst];
let mut operand_constraints = enc_info let mut operand_constraints = enc_info
.operand_constraints(func.encodings[inst]) .operand_constraints(encoding)
.map(|c| c.ins) .map(|c| c.ins)
.unwrap_or(&[]) .unwrap_or(&[])
.iter(); .iter();
@@ -392,11 +392,18 @@ impl Liveness {
// Apply operand constraint, ignoring any variable arguments after the fixed // Apply operand constraint, ignoring any variable arguments after the fixed
// operands described by `operand_constraints`. Variable arguments are either // operands described by `operand_constraints`. Variable arguments are either
// EBB arguments or call/return ABI arguments. EBB arguments need to be // EBB arguments or call/return ABI arguments.
// resolved by the coloring algorithm, and ABI constraints require specific
// registers or stack slots which the affinities don't model anyway.
if let Some(constraint) = operand_constraints.next() { if let Some(constraint) = operand_constraints.next() {
lr.affinity.merge(constraint, &reg_info); lr.affinity.merge(constraint, &reg_info);
} else if lr.affinity.is_none() && encoding.is_legal() &&
!func.dfg[inst].opcode().is_branch() {
// This is a real encoded instruction using a value that doesn't yet have a
// concrete affinity. Most likely a call argument or a return value. Give
// the value a register affinity matching the ABI type.
//
// EBB arguments on a branch are not required to have an affinity.
let rc = isa.regclass_for_abi_type(func.dfg.value_type(arg));
lr.affinity = Affinity::Reg(rc.into());
} }
} }
} }