Properly handle prog-moves with fixed srcs or dests
This commit is contained in:
@@ -130,7 +130,7 @@ impl Function for Func {
|
|||||||
&self.reftype_vregs[..]
|
&self.reftype_vregs[..]
|
||||||
}
|
}
|
||||||
|
|
||||||
fn is_move(&self, _: Inst) -> Option<(VReg, VReg)> {
|
fn is_move(&self, _: Inst) -> Option<(Operand, Operand)> {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1165,8 +1165,8 @@ impl<'a, F: Function> Env<'a, F> {
|
|||||||
let mut live = self.liveouts[block.index()].clone();
|
let mut live = self.liveouts[block.index()].clone();
|
||||||
for inst in self.func.block_insns(block).rev().iter() {
|
for inst in self.func.block_insns(block).rev().iter() {
|
||||||
if let Some((src, dst)) = self.func.is_move(inst) {
|
if let Some((src, dst)) = self.func.is_move(inst) {
|
||||||
live.set(dst.vreg(), false);
|
live.set(dst.vreg().vreg(), false);
|
||||||
live.set(src.vreg(), true);
|
live.set(src.vreg().vreg(), true);
|
||||||
}
|
}
|
||||||
for pos in &[OperandPos::After, OperandPos::Before] {
|
for pos in &[OperandPos::After, OperandPos::Before] {
|
||||||
for op in self.func.inst_operands(inst) {
|
for op in self.func.inst_operands(inst) {
|
||||||
@@ -1304,19 +1304,23 @@ impl<'a, F: Function> Env<'a, F> {
|
|||||||
|
|
||||||
// If this is a move, handle specially.
|
// If this is a move, handle specially.
|
||||||
if let Some((src, dst)) = self.func.is_move(inst) {
|
if let Some((src, dst)) = self.func.is_move(inst) {
|
||||||
if src != dst {
|
if src.vreg() != dst.vreg() {
|
||||||
log::debug!(" -> move inst{}: src {} -> dst {}", inst.index(), src, dst);
|
log::debug!(" -> move inst{}: src {} -> dst {}", inst.index(), src, dst);
|
||||||
assert_eq!(src.class(), dst.class());
|
assert_eq!(src.class(), dst.class());
|
||||||
|
assert_eq!(src.kind(), OperandKind::Use);
|
||||||
|
assert_eq!(src.pos(), OperandPos::Before);
|
||||||
|
assert_eq!(dst.kind(), OperandKind::Def);
|
||||||
|
assert_eq!(dst.pos(), OperandPos::After);
|
||||||
|
|
||||||
// Handle the def w.r.t. liveranges: trim the
|
// Handle the def w.r.t. liveranges: trim the
|
||||||
// start of the range and mark it dead at this
|
// start of the range and mark it dead at this
|
||||||
// point in our backward scan.
|
// point in our backward scan.
|
||||||
let pos = ProgPoint::after(inst);
|
let pos = ProgPoint::after(inst);
|
||||||
let mut dst_lr = vreg_ranges[dst.vreg()];
|
let mut dst_lr = vreg_ranges[dst.vreg().vreg()];
|
||||||
// If there was no liverange (dead def), create a trivial one.
|
// If there was no liverange (dead def), create a trivial one.
|
||||||
if !live.get(dst.vreg()) {
|
if !live.get(dst.vreg().vreg()) {
|
||||||
dst_lr = self.add_liverange_to_vreg(
|
dst_lr = self.add_liverange_to_vreg(
|
||||||
VRegIndex::new(dst.vreg()),
|
VRegIndex::new(dst.vreg().vreg()),
|
||||||
CodeRange {
|
CodeRange {
|
||||||
from: pos,
|
from: pos,
|
||||||
to: pos.next(),
|
to: pos.next(),
|
||||||
@@ -1333,22 +1337,13 @@ impl<'a, F: Function> Env<'a, F> {
|
|||||||
log::debug!(" -> started at block start; trimming to {:?}", pos);
|
log::debug!(" -> started at block start; trimming to {:?}", pos);
|
||||||
self.ranges_hot[dst_lr.index()].range.from = pos;
|
self.ranges_hot[dst_lr.index()].range.from = pos;
|
||||||
}
|
}
|
||||||
live.set(dst.vreg(), false);
|
live.set(dst.vreg().vreg(), false);
|
||||||
vreg_ranges[dst.vreg()] = LiveRangeIndex::invalid();
|
vreg_ranges[dst.vreg().vreg()] = LiveRangeIndex::invalid();
|
||||||
self.vreg_regs[dst.vreg()] = dst;
|
self.vreg_regs[dst.vreg().vreg()] = dst.vreg();
|
||||||
|
|
||||||
let u = UseIndex::new(self.uses.len());
|
let u = UseIndex::new(self.uses.len());
|
||||||
self.uses.push(Use::new(
|
self.uses
|
||||||
Operand::new(
|
.push(Use::new(dst, pos, UseIndex::invalid(), SLOT_NONE as u8));
|
||||||
dst,
|
|
||||||
OperandPolicy::Any,
|
|
||||||
OperandKind::Def,
|
|
||||||
OperandPos::After,
|
|
||||||
),
|
|
||||||
pos,
|
|
||||||
UseIndex::invalid(),
|
|
||||||
SLOT_NONE as u8,
|
|
||||||
));
|
|
||||||
self.insert_use_into_liverange_and_update_stats(dst_lr, u);
|
self.insert_use_into_liverange_and_update_stats(dst_lr, u);
|
||||||
|
|
||||||
// Handle the use w.r.t. liveranges: make it live
|
// Handle the use w.r.t. liveranges: make it live
|
||||||
@@ -1360,37 +1355,32 @@ impl<'a, F: Function> Env<'a, F> {
|
|||||||
to: pos.next(),
|
to: pos.next(),
|
||||||
};
|
};
|
||||||
let src_lr = self.add_liverange_to_vreg(
|
let src_lr = self.add_liverange_to_vreg(
|
||||||
VRegIndex::new(src.vreg()),
|
VRegIndex::new(src.vreg().vreg()),
|
||||||
range,
|
range,
|
||||||
&mut num_ranges,
|
&mut num_ranges,
|
||||||
);
|
);
|
||||||
vreg_ranges[src.vreg()] = src_lr;
|
vreg_ranges[src.vreg().vreg()] = src_lr;
|
||||||
|
|
||||||
log::debug!(" -> src LR {:?}", src_lr);
|
log::debug!(" -> src LR {:?}", src_lr);
|
||||||
|
|
||||||
let u = UseIndex::new(self.uses.len());
|
let u = UseIndex::new(self.uses.len());
|
||||||
self.uses.push(Use::new(
|
self.uses
|
||||||
Operand::new(
|
.push(Use::new(src, pos, UseIndex::invalid(), SLOT_NONE as u8));
|
||||||
dst,
|
|
||||||
OperandPolicy::Any,
|
|
||||||
OperandKind::Use,
|
|
||||||
OperandPos::Before,
|
|
||||||
),
|
|
||||||
pos,
|
|
||||||
UseIndex::invalid(),
|
|
||||||
SLOT_NONE as u8,
|
|
||||||
));
|
|
||||||
self.insert_use_into_liverange_and_update_stats(src_lr, u);
|
self.insert_use_into_liverange_and_update_stats(src_lr, u);
|
||||||
|
|
||||||
// Add to live-set.
|
// Add to live-set.
|
||||||
let src_is_dead_after_move = !live.get(src.vreg());
|
let src_is_dead_after_move = !live.get(src.vreg().vreg());
|
||||||
live.set(src.vreg(), true);
|
live.set(src.vreg().vreg(), true);
|
||||||
|
|
||||||
// Add to program-moves lists.
|
// Add to program-moves lists.
|
||||||
self.prog_move_srcs
|
self.prog_move_srcs.push((
|
||||||
.push(((VRegIndex::new(src.vreg()), inst), Allocation::none()));
|
(VRegIndex::new(src.vreg().vreg()), inst),
|
||||||
self.prog_move_dsts
|
Allocation::none(),
|
||||||
.push(((VRegIndex::new(dst.vreg()), inst), Allocation::none()));
|
));
|
||||||
|
self.prog_move_dsts.push((
|
||||||
|
(VRegIndex::new(dst.vreg().vreg()), inst),
|
||||||
|
Allocation::none(),
|
||||||
|
));
|
||||||
if src_is_dead_after_move {
|
if src_is_dead_after_move {
|
||||||
self.prog_move_merges.push((src_lr, dst_lr));
|
self.prog_move_merges.push((src_lr, dst_lr));
|
||||||
}
|
}
|
||||||
@@ -3859,7 +3849,11 @@ impl<'a, F: Function> Env<'a, F> {
|
|||||||
} else {
|
} else {
|
||||||
(vreg, range.from.inst().next())
|
(vreg, range.from.inst().next())
|
||||||
};
|
};
|
||||||
let move_src_end = (vreg, range.to.inst());
|
let move_src_end = if range.to.pos() == InstPosition::Before {
|
||||||
|
(vreg, range.to.inst())
|
||||||
|
} else {
|
||||||
|
(vreg, range.to.inst().next())
|
||||||
|
};
|
||||||
log::debug!(
|
log::debug!(
|
||||||
"vreg {:?} range {:?}: looking for program-move sources from {:?} to {:?}",
|
"vreg {:?} range {:?}: looking for program-move sources from {:?} to {:?}",
|
||||||
vreg,
|
vreg,
|
||||||
|
|||||||
@@ -708,8 +708,8 @@ pub trait Function {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Determine whether an instruction is a move; if so, return the
|
/// Determine whether an instruction is a move; if so, return the
|
||||||
/// vregs for (src, dst).
|
/// Operands for (src, dst).
|
||||||
fn is_move(&self, insn: Inst) -> Option<(VReg, VReg)>;
|
fn is_move(&self, insn: Inst) -> Option<(Operand, Operand)>;
|
||||||
|
|
||||||
// --------------------------
|
// --------------------------
|
||||||
// Instruction register slots
|
// Instruction register slots
|
||||||
|
|||||||
Reference in New Issue
Block a user