Apply register diversions during binemit tests.

When "binemit" tests encode instructions, keep track of the current set
of register diversions, and use the diverted locations to check operand
constraints.

This matches how constraints are applied during a real binemit phase.
This commit is contained in:
Jakob Stoklund Olesen
2017-10-04 16:33:50 -07:00
parent dda3efcbdd
commit 826d4062fb
3 changed files with 37 additions and 5 deletions

View File

@@ -10,6 +10,7 @@
use binemit::CodeOffset;
use isa::{RegClass, RegUnit};
use ir::{Function, ValueLoc, Inst};
use regalloc::RegDiversions;
/// Register constraint for a single value operand or instruction result.
pub struct OperandConstraint {
@@ -109,9 +110,9 @@ pub struct RecipeConstraints {
impl RecipeConstraints {
/// Check that these constraints are satisfied by the operands on `inst`.
pub fn satisfied(&self, inst: Inst, func: &Function) -> bool {
pub fn satisfied(&self, inst: Inst, divert: &RegDiversions, func: &Function) -> bool {
for (&arg, constraint) in func.dfg.inst_args(inst).iter().zip(self.ins) {
let loc = func.locations[arg];
let loc = divert.get(arg, &func.locations);
if let ConstraintKind::Tied(out_index) = constraint.kind {
let out_val = func.dfg.inst_results(inst)[out_index as usize];
@@ -127,7 +128,7 @@ impl RecipeConstraints {
}
for (&arg, constraint) in func.dfg.inst_results(inst).iter().zip(self.outs) {
let loc = func.locations[arg];
let loc = divert.get(arg, &func.locations);
if !constraint.satisfied(loc) {
return false;
}

View File

@@ -8,6 +8,7 @@
//! EBB.
use ir::{Value, ValueLoc, ValueLocations, StackSlot};
use ir::{InstructionData, Opcode};
use isa::{RegUnit, RegInfo};
use std::fmt;
@@ -118,6 +119,34 @@ impl RegDiversions {
self.divert(value, ValueLoc::Stack(from), ValueLoc::Reg(to));
}
/// Apply the effect of `inst`.
///
/// If `inst` is a `regmove`, `regfill`, or `regspill` instruction, update the diversions to
/// match.
pub fn apply(&mut self, inst: &InstructionData) {
match *inst {
InstructionData::RegMove {
opcode: Opcode::Regmove,
arg,
src,
dst,
} => self.regmove(arg, src, dst),
InstructionData::RegSpill {
opcode: Opcode::Regspill,
arg,
src,
dst,
} => self.regspill(arg, src, dst),
InstructionData::RegFill {
opcode: Opcode::Regfill,
arg,
src,
dst,
} => self.regfill(arg, src, dst),
_ => {}
}
}
/// Drop any recorded move for `value`.
///
/// Returns the `to` location of the removed diversion.