Solver variables keep track of where they came from.
The register constraint solver has two kinds of variables: 1. Live values that were already in a register, and 2. Values defined by the instruction. Make a record of the original register holding the first kind of value.
This commit is contained in:
@@ -357,7 +357,7 @@ impl<'a> Context<'a> {
|
|||||||
.unwrap_or_else(|_| self.iterate_solution());
|
.unwrap_or_else(|_| self.iterate_solution());
|
||||||
|
|
||||||
// Apply the solution to the defs.
|
// Apply the solution to the defs.
|
||||||
for v in self.solver.vars().iter().filter(|&v| v.is_define) {
|
for v in self.solver.vars().iter().filter(|&v| v.is_define()) {
|
||||||
*locations.ensure(v.value) = ValueLoc::Reg(v.solution);
|
*locations.ensure(v.value) = ValueLoc::Reg(v.solution);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -129,6 +129,10 @@ pub struct Variable {
|
|||||||
/// The value whose register assignment we're looking for.
|
/// The value whose register assignment we're looking for.
|
||||||
pub value: Value,
|
pub value: Value,
|
||||||
|
|
||||||
|
/// Original register unit holding this live value before the instruction, or `None` for a
|
||||||
|
/// value that is defined by the instruction.
|
||||||
|
from: Option<RegUnit>,
|
||||||
|
|
||||||
/// Avoid interference on the input side.
|
/// Avoid interference on the input side.
|
||||||
is_input: bool,
|
is_input: bool,
|
||||||
|
|
||||||
@@ -138,9 +142,6 @@ pub struct Variable {
|
|||||||
/// Avoid interference with the global registers.
|
/// Avoid interference with the global registers.
|
||||||
is_global: bool,
|
is_global: bool,
|
||||||
|
|
||||||
/// The value is defined by the current instruction.
|
|
||||||
pub is_define: bool,
|
|
||||||
|
|
||||||
/// Number of registers available in the domain of this variable.
|
/// Number of registers available in the domain of this variable.
|
||||||
domain: u16,
|
domain: u16,
|
||||||
|
|
||||||
@@ -152,6 +153,37 @@ pub struct Variable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl Variable {
|
impl Variable {
|
||||||
|
fn new_live(value: Value, constraint: RegClass, from: RegUnit) -> Variable {
|
||||||
|
Variable {
|
||||||
|
value,
|
||||||
|
constraint,
|
||||||
|
from: Some(from),
|
||||||
|
is_input: true,
|
||||||
|
is_output: true,
|
||||||
|
is_global: false,
|
||||||
|
domain: 0,
|
||||||
|
solution: !0,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn new_def(value: Value, constraint: RegClass) -> Variable {
|
||||||
|
Variable {
|
||||||
|
value,
|
||||||
|
constraint,
|
||||||
|
from: None,
|
||||||
|
is_input: false,
|
||||||
|
is_output: true,
|
||||||
|
is_global: false,
|
||||||
|
domain: 0,
|
||||||
|
solution: !0,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Does this variable represent a value defined by the current instruction?
|
||||||
|
pub fn is_define(&self) -> bool {
|
||||||
|
self.from.is_none()
|
||||||
|
}
|
||||||
|
|
||||||
/// Get an iterator over possible register choices, given the available registers on the input
|
/// Get an iterator over possible register choices, given the available registers on the input
|
||||||
/// and output sides respectively.
|
/// and output sides respectively.
|
||||||
fn iter(&self, iregs: &AllocatableSet, oregs: &AllocatableSet) -> RegSetIter {
|
fn iter(&self, iregs: &AllocatableSet, oregs: &AllocatableSet) -> RegSetIter {
|
||||||
@@ -179,7 +211,7 @@ impl fmt::Display for Variable {
|
|||||||
if self.is_global {
|
if self.is_global {
|
||||||
write!(f, ", global")?;
|
write!(f, ", global")?;
|
||||||
}
|
}
|
||||||
if self.is_define {
|
if self.is_define() {
|
||||||
write!(f, ", def")?;
|
write!(f, ", def")?;
|
||||||
}
|
}
|
||||||
if self.domain > 0 {
|
if self.domain > 0 {
|
||||||
@@ -369,16 +401,7 @@ impl Solver {
|
|||||||
self.regs_out.free(constraint, from);
|
self.regs_out.free(constraint, from);
|
||||||
}
|
}
|
||||||
self.vars
|
self.vars
|
||||||
.push(Variable {
|
.push(Variable::new_live(value, constraint, from));
|
||||||
value,
|
|
||||||
constraint,
|
|
||||||
is_input: true,
|
|
||||||
is_output: true,
|
|
||||||
is_global: false,
|
|
||||||
is_define: false,
|
|
||||||
domain: 0,
|
|
||||||
solution: !0,
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Check for conflicts between fixed input assignments and existing live values.
|
/// Check for conflicts between fixed input assignments and existing live values.
|
||||||
@@ -474,17 +497,7 @@ impl Solver {
|
|||||||
/// This is similar to `add_var`, except the value doesn't have a prior register assignment.
|
/// This is similar to `add_var`, except the value doesn't have a prior register assignment.
|
||||||
pub fn add_def(&mut self, value: Value, constraint: RegClass) {
|
pub fn add_def(&mut self, value: Value, constraint: RegClass) {
|
||||||
debug_assert!(self.inputs_done);
|
debug_assert!(self.inputs_done);
|
||||||
self.vars
|
self.vars.push(Variable::new_def(value, constraint));
|
||||||
.push(Variable {
|
|
||||||
value,
|
|
||||||
constraint,
|
|
||||||
is_input: false,
|
|
||||||
is_output: true,
|
|
||||||
is_global: false,
|
|
||||||
is_define: true,
|
|
||||||
domain: 0,
|
|
||||||
solution: !0,
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user