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:
@@ -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
|
||||||
|
}
|
||||||
|
|||||||
@@ -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, ®_info);
|
lr.affinity.merge(constraint, ®_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());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user