Hook up the handling of tied register constraints.

Tests are forthcoming, we need to implement Intel ABI lowering first.
This commit is contained in:
Jakob Stoklund Olesen
2017-06-30 08:41:54 -07:00
parent 18dc420352
commit aa3bf4467e
2 changed files with 17 additions and 6 deletions

View File

@@ -399,7 +399,7 @@ impl LiveRange {
} }
} }
/// Check if this live range reaches a use at `inst` in `ebb`. /// Check if this live range reaches a use at `user` in `ebb`.
pub fn reaches_use<PO>(&self, user: Inst, ebb: Ebb, order: &PO) -> bool pub fn reaches_use<PO>(&self, user: Inst, ebb: Ebb, order: &PO) -> bool
where PO: ProgramOrder where PO: ProgramOrder
{ {
@@ -415,6 +415,13 @@ impl LiveRange {
None => false, None => false,
} }
} }
/// Check if this live range is killed at `user` in `ebb`.
pub fn killed_at<PO>(&self, user: Inst, ebb: Ebb, order: &PO) -> bool
where PO: ProgramOrder
{
self.def_local_end() == user.into() || self.livein_local_end(ebb, order) == Some(user)
}
} }
/// Allow a `LiveRange` to be stored in a `SparseMap` indexed by values. /// Allow a `LiveRange` to be stored in a `SparseMap` indexed by values.

View File

@@ -155,7 +155,7 @@ impl<'a> Context<'a> {
pos.goto_top(ebb); pos.goto_top(ebb);
while let Some(inst) = pos.next_inst() { while let Some(inst) = pos.next_inst() {
if let Some(constraints) = self.encinfo.operand_constraints(self.encodings[inst]) { if let Some(constraints) = self.encinfo.operand_constraints(self.encodings[inst]) {
self.visit_inst(inst, constraints, &mut pos, dfg, tracker); self.visit_inst(inst, ebb, constraints, &mut pos, dfg, tracker);
} else { } else {
let (_throughs, kills) = tracker.process_ghost(inst); let (_throughs, kills) = tracker.process_ghost(inst);
self.free_regs(kills); self.free_regs(kills);
@@ -240,6 +240,7 @@ impl<'a> Context<'a> {
fn visit_inst(&mut self, fn visit_inst(&mut self,
inst: Inst, inst: Inst,
ebb: Ebb,
constraints: &RecipeConstraints, constraints: &RecipeConstraints,
pos: &mut Cursor, pos: &mut Cursor,
dfg: &mut DataFlowGraph, dfg: &mut DataFlowGraph,
@@ -248,7 +249,7 @@ impl<'a> Context<'a> {
// We may need to resolve register constraints if there are any noteworthy uses. // We may need to resolve register constraints if there are any noteworthy uses.
assert!(self.reg_uses.is_empty()); assert!(self.reg_uses.is_empty());
self.collect_reg_uses(inst, constraints, dfg); self.collect_reg_uses(inst, ebb, constraints, dfg, pos.layout);
// Calls usually have fixed register uses. // Calls usually have fixed register uses.
let call_sig = dfg.call_signature(inst); let call_sig = dfg.call_signature(inst);
@@ -315,20 +316,23 @@ impl<'a> Context<'a> {
// operands are always compatible. // operands are always compatible.
fn collect_reg_uses(&mut self, fn collect_reg_uses(&mut self,
inst: Inst, inst: Inst,
ebb: Ebb,
constraints: &RecipeConstraints, constraints: &RecipeConstraints,
dfg: &DataFlowGraph) { dfg: &DataFlowGraph,
layout: &Layout) {
let args = dfg.inst_args(inst); let args = dfg.inst_args(inst);
for (idx, (op, &arg)) in constraints.ins.iter().zip(args).enumerate() { for (idx, (op, &arg)) in constraints.ins.iter().zip(args).enumerate() {
let mut reguse = RegUse::new(arg, idx, op.regclass.into()); let mut reguse = RegUse::new(arg, idx, op.regclass.into());
let lr = &self.liveness[arg];
match op.kind { match op.kind {
ConstraintKind::Stack => continue, ConstraintKind::Stack => continue,
ConstraintKind::FixedReg(_) => reguse.fixed = true, ConstraintKind::FixedReg(_) => reguse.fixed = true,
ConstraintKind::Tied(_) => { ConstraintKind::Tied(_) => {
// TODO: If `arg` isn't killed here, we need a copy // A tied operand must kill the used value.
reguse.tied = !lr.killed_at(inst, ebb, layout);
} }
ConstraintKind::Reg => {} ConstraintKind::Reg => {}
} }
let lr = &self.liveness[arg];
if lr.affinity.is_stack() { if lr.affinity.is_stack() {
reguse.spilled = true; reguse.spilled = true;
} }