More efficient live-range creation re: uses

This commit is contained in:
Chris Fallin
2021-05-07 20:12:40 -07:00
parent a6e3128821
commit 4185eab441

View File

@@ -1350,20 +1350,56 @@ impl<'a, F: Function> Env<'a, F> {
} }
// Process defs and uses. // Process defs and uses.
for &cur_pos in &[InstPosition::After, InstPosition::Before] {
for i in 0..self.func.inst_operands(inst).len() { for i in 0..self.func.inst_operands(inst).len() {
// don't borrow `self` // don't borrow `self`
let operand = self.func.inst_operands(inst)[i]; let operand = self.func.inst_operands(inst)[i];
match operand.kind() {
OperandKind::Def | OperandKind::Mod => {
// Create the Def object.
let pos = match (operand.kind(), operand.pos()) { let pos = match (operand.kind(), operand.pos()) {
(OperandKind::Mod, _) => ProgPoint::before(inst), (OperandKind::Mod, _) => ProgPoint::before(inst),
(_, OperandPos::Before) => ProgPoint::before(inst), (OperandKind::Def, OperandPos::Before) => ProgPoint::before(inst),
(_, OperandPos::After) => ProgPoint::after(inst), (OperandKind::Def, OperandPos::After) => ProgPoint::after(inst),
(OperandKind::Use, OperandPos::After) => ProgPoint::after(inst),
// If this is a branch, extend `pos` to
// the end of the block. (Branch uses are
// blockparams and need to be live at the
// end of the block.)
(OperandKind::Use, _) if self.func.is_branch(inst) => {
self.cfginfo.block_exit[block.index()]
}
// If there are any reused inputs in this
// instruction, and this is *not* the
// reused input, force `pos` to
// `After`. (See note below for why; it's
// very subtle!)
(OperandKind::Use, OperandPos::Before)
if reused_input.is_some() && reused_input.unwrap() != i =>
{
ProgPoint::after(inst)
}
(OperandKind::Use, OperandPos::Before) => ProgPoint::before(inst),
}; };
if pos.pos() != cur_pos {
continue;
}
log::debug!(
"processing inst{} operand at {:?}: {:?}",
inst.index(),
pos,
operand
);
match operand.kind() {
OperandKind::Def | OperandKind::Mod => {
// Create the use object.
let u = UseIndex(self.uses.len() as u32); let u = UseIndex(self.uses.len() as u32);
self.uses self.uses.push(Use::new(
.push(Use::new(operand, pos, UseIndex::invalid(), i as u8)); operand,
pos,
UseIndex::invalid(),
i as u8,
));
log::debug!("Def of {} at {:?}", operand.vreg(), pos); log::debug!("Def of {} at {:?}", operand.vreg(), pos);
@@ -1374,10 +1410,15 @@ impl<'a, F: Function> Env<'a, F> {
log::debug!(" -> has existing LR {:?}", lr); log::debug!(" -> has existing LR {:?}", lr);
// 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(operand.vreg().vreg()) { if !live.get(operand.vreg().vreg()) {
let from = match operand.kind() {
OperandKind::Def => pos,
OperandKind::Mod => self.cfginfo.block_entry[block.index()],
_ => unreachable!(),
};
lr = self.add_liverange_to_vreg( lr = self.add_liverange_to_vreg(
VRegIndex::new(operand.vreg().vreg()), VRegIndex::new(operand.vreg().vreg()),
CodeRange { CodeRange {
from: pos, from,
to: pos.next(), to: pos.next(),
}, },
&mut num_ranges, &mut num_ranges,
@@ -1408,45 +1449,40 @@ impl<'a, F: Function> Env<'a, F> {
} }
} }
OperandKind::Use => { OperandKind::Use => {
// Establish where the use occurs. // Create the use object.
let mut pos = match operand.pos() {
OperandPos::Before => ProgPoint::before(inst),
OperandPos::After => ProgPoint::after(inst),
};
// If there are any reused inputs in this
// instruction, and this is *not* the
// reused input, force `pos` to
// `After`. (See note below for why; it's
// very subtle!)
if reused_input.is_some() && reused_input.unwrap() != i {
pos = ProgPoint::after(inst);
}
// If this is a branch, extend `pos` to
// the end of the block. (Branch uses are
// blockparams and need to be live at the
// end of the block.)
if self.func.is_branch(inst) {
pos = self.cfginfo.block_exit[block.index()];
}
// Create the actual use object.
let u = UseIndex(self.uses.len() as u32); let u = UseIndex(self.uses.len() as u32);
self.uses self.uses.push(Use::new(
.push(Use::new(operand, pos, UseIndex::invalid(), i as u8)); operand,
pos,
UseIndex::invalid(),
i as u8,
));
// Create/extend the LiveRange and add the use to the range. // Create/extend the LiveRange if it
// doesn't already exist, and add the use
// to the range.
let mut lr = vreg_ranges[operand.vreg().vreg()];
if !live.get(operand.vreg().vreg()) {
let range = CodeRange { let range = CodeRange {
from: self.cfginfo.block_entry[block.index()], from: self.cfginfo.block_entry[block.index()],
to: pos.next(), to: pos.next(),
}; };
let lr = self.add_liverange_to_vreg( lr = self.add_liverange_to_vreg(
VRegIndex::new(operand.vreg().vreg()), VRegIndex::new(operand.vreg().vreg()),
range, range,
&mut num_ranges, &mut num_ranges,
); );
vreg_ranges[operand.vreg().vreg()] = lr; vreg_ranges[operand.vreg().vreg()] = lr;
}
assert!(lr.is_valid());
log::debug!("Use of {:?} at {:?} -> {:?} -> {:?}", operand, pos, u, lr); log::debug!(
"Use of {:?} at {:?} -> {:?} -> {:?}",
operand,
pos,
u,
lr
);
self.insert_use_into_liverange_and_update_stats(lr, u); self.insert_use_into_liverange_and_update_stats(lr, u);
@@ -1455,6 +1491,7 @@ impl<'a, F: Function> Env<'a, F> {
} }
} }
} }
}
if self.func.is_safepoint(inst) { if self.func.is_safepoint(inst) {
self.safepoints.push(inst); self.safepoints.push(inst);
@@ -3741,6 +3778,7 @@ impl<'a, F: Function> Env<'a, F> {
let mut use_iter = self.ranges[iter.index()].first_use; let mut use_iter = self.ranges[iter.index()].first_use;
while use_iter.is_valid() { while use_iter.is_valid() {
let usedata = &self.uses[use_iter.index()]; let usedata = &self.uses[use_iter.index()];
log::debug!("applying to use: {:?}", usedata);
debug_assert!(range.contains_point(usedata.pos)); debug_assert!(range.contains_point(usedata.pos));
let inst = usedata.pos.inst(); let inst = usedata.pos.inst();
let slot = usedata.slot(); let slot = usedata.slot();