Guard trace! behind cfg!(debug_assertions)
Even if the trace log level is disabled, the presence of the trace! macro still has a significant impact on performance because it is present in the inner loops of the allocator. Removing the trace! calls at compile-time reduces instruction count by ~7%.
This commit is contained in:
@@ -191,7 +191,7 @@ impl CheckerValue {
|
|||||||
CheckerValue::Reg(r1, ref1)
|
CheckerValue::Reg(r1, ref1)
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
log::trace!("{:?} and {:?} meet to Conflicted", self, other);
|
trace!("{:?} and {:?} meet to Conflicted", self, other);
|
||||||
CheckerValue::Conflicted
|
CheckerValue::Conflicted
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -322,7 +322,7 @@ impl CheckerState {
|
|||||||
.get(alloc)
|
.get(alloc)
|
||||||
.cloned()
|
.cloned()
|
||||||
.unwrap_or(Default::default());
|
.unwrap_or(Default::default());
|
||||||
log::trace!(
|
trace!(
|
||||||
"checker: checkinst {:?}: op {:?}, alloc {:?}, checker value {:?}",
|
"checker: checkinst {:?}: op {:?}, alloc {:?}, checker value {:?}",
|
||||||
checkinst,
|
checkinst,
|
||||||
op,
|
op,
|
||||||
@@ -339,7 +339,7 @@ impl CheckerState {
|
|||||||
.get(&alloc)
|
.get(&alloc)
|
||||||
.cloned()
|
.cloned()
|
||||||
.unwrap_or(Default::default());
|
.unwrap_or(Default::default());
|
||||||
log::trace!(
|
trace!(
|
||||||
"checker: checkinst {:?}: safepoint slot {}, checker value {:?}",
|
"checker: checkinst {:?}: safepoint slot {}, checker value {:?}",
|
||||||
checkinst,
|
checkinst,
|
||||||
alloc,
|
alloc,
|
||||||
@@ -372,7 +372,7 @@ impl CheckerState {
|
|||||||
.get(&from)
|
.get(&from)
|
||||||
.cloned()
|
.cloned()
|
||||||
.unwrap_or(Default::default());
|
.unwrap_or(Default::default());
|
||||||
log::trace!(
|
trace!(
|
||||||
"checker: checkinst {:?} updating: move {:?} -> {:?} val {:?}",
|
"checker: checkinst {:?} updating: move {:?} -> {:?} val {:?}",
|
||||||
checkinst,
|
checkinst,
|
||||||
from,
|
from,
|
||||||
@@ -534,7 +534,7 @@ impl<'a, F: Function> Checker<'a, F> {
|
|||||||
/// Build the list of checker instructions based on the given func
|
/// Build the list of checker instructions based on the given func
|
||||||
/// and allocation results.
|
/// and allocation results.
|
||||||
pub fn prepare(&mut self, out: &Output) {
|
pub fn prepare(&mut self, out: &Output) {
|
||||||
log::trace!("checker: out = {:?}", out);
|
trace!("checker: out = {:?}", out);
|
||||||
// Preprocess safepoint stack-maps into per-inst vecs.
|
// Preprocess safepoint stack-maps into per-inst vecs.
|
||||||
let mut safepoint_slots: HashMap<Inst, Vec<Allocation>> = HashMap::new();
|
let mut safepoint_slots: HashMap<Inst, Vec<Allocation>> = HashMap::new();
|
||||||
for &(progpoint, slot) in &out.safepoint_slots {
|
for &(progpoint, slot) in &out.safepoint_slots {
|
||||||
@@ -591,13 +591,13 @@ impl<'a, F: Function> Checker<'a, F> {
|
|||||||
allocs,
|
allocs,
|
||||||
clobbers,
|
clobbers,
|
||||||
};
|
};
|
||||||
log::trace!("checker: adding inst {:?}", checkinst);
|
trace!("checker: adding inst {:?}", checkinst);
|
||||||
self.bb_insts.get_mut(&block).unwrap().push(checkinst);
|
self.bb_insts.get_mut(&block).unwrap().push(checkinst);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn handle_edit(&mut self, block: Block, edit: &Edit) {
|
fn handle_edit(&mut self, block: Block, edit: &Edit) {
|
||||||
log::trace!("checker: adding edit {:?}", edit);
|
trace!("checker: adding edit {:?}", edit);
|
||||||
match edit {
|
match edit {
|
||||||
&Edit::Move { from, to } => {
|
&Edit::Move { from, to } => {
|
||||||
self.bb_insts
|
self.bb_insts
|
||||||
@@ -628,10 +628,10 @@ impl<'a, F: Function> Checker<'a, F> {
|
|||||||
let block = queue.pop_front().unwrap();
|
let block = queue.pop_front().unwrap();
|
||||||
queue_set.remove(&block);
|
queue_set.remove(&block);
|
||||||
let mut state = self.bb_in.get(&block).cloned().unwrap();
|
let mut state = self.bb_in.get(&block).cloned().unwrap();
|
||||||
log::trace!("analyze: block {} has state {:?}", block.index(), state);
|
trace!("analyze: block {} has state {:?}", block.index(), state);
|
||||||
for inst in self.bb_insts.get(&block).unwrap() {
|
for inst in self.bb_insts.get(&block).unwrap() {
|
||||||
state.update(inst, self);
|
state.update(inst, self);
|
||||||
log::trace!("analyze: inst {:?} -> state {:?}", inst, state);
|
trace!("analyze: inst {:?} -> state {:?}", inst, state);
|
||||||
}
|
}
|
||||||
|
|
||||||
for &succ in self.f.block_succs(block) {
|
for &succ in self.f.block_succs(block) {
|
||||||
@@ -640,7 +640,7 @@ impl<'a, F: Function> Checker<'a, F> {
|
|||||||
new_state.meet_with(cur_succ_in);
|
new_state.meet_with(cur_succ_in);
|
||||||
let changed = &new_state != cur_succ_in;
|
let changed = &new_state != cur_succ_in;
|
||||||
if changed {
|
if changed {
|
||||||
log::trace!(
|
trace!(
|
||||||
"analyze: block {} state changed from {:?} to {:?}; pushing onto queue",
|
"analyze: block {} state changed from {:?} to {:?}; pushing onto queue",
|
||||||
succ.index(),
|
succ.index(),
|
||||||
cur_succ_in,
|
cur_succ_in,
|
||||||
@@ -665,12 +665,12 @@ impl<'a, F: Function> Checker<'a, F> {
|
|||||||
let mut state = input.clone();
|
let mut state = input.clone();
|
||||||
for inst in self.bb_insts.get(block).unwrap() {
|
for inst in self.bb_insts.get(block).unwrap() {
|
||||||
if let Err(e) = state.check(InstPosition::Before, inst) {
|
if let Err(e) = state.check(InstPosition::Before, inst) {
|
||||||
log::trace!("Checker error: {:?}", e);
|
trace!("Checker error: {:?}", e);
|
||||||
errors.push(e);
|
errors.push(e);
|
||||||
}
|
}
|
||||||
state.update(inst, self);
|
state.update(inst, self);
|
||||||
if let Err(e) = state.check(InstPosition::After, inst) {
|
if let Err(e) = state.check(InstPosition::After, inst) {
|
||||||
log::trace!("Checker error: {:?}", e);
|
trace!("Checker error: {:?}", e);
|
||||||
errors.push(e);
|
errors.push(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -689,20 +689,20 @@ impl<'a, F: Function> Checker<'a, F> {
|
|||||||
self.analyze();
|
self.analyze();
|
||||||
let result = self.find_errors();
|
let result = self.find_errors();
|
||||||
|
|
||||||
log::trace!("=== CHECKER RESULT ===");
|
trace!("=== CHECKER RESULT ===");
|
||||||
fn print_state(state: &CheckerState) {
|
fn print_state(state: &CheckerState) {
|
||||||
let mut s = vec![];
|
let mut s = vec![];
|
||||||
for (alloc, state) in &state.allocations {
|
for (alloc, state) in &state.allocations {
|
||||||
s.push(format!("{} := {}", alloc, state));
|
s.push(format!("{} := {}", alloc, state));
|
||||||
}
|
}
|
||||||
log::trace!(" {{ {} }}", s.join(", "))
|
trace!(" {{ {} }}", s.join(", "))
|
||||||
}
|
}
|
||||||
for vreg in self.f.reftype_vregs() {
|
for vreg in self.f.reftype_vregs() {
|
||||||
log::trace!(" REF: {}", vreg);
|
trace!(" REF: {}", vreg);
|
||||||
}
|
}
|
||||||
for bb in 0..self.f.num_blocks() {
|
for bb in 0..self.f.num_blocks() {
|
||||||
let bb = Block::new(bb);
|
let bb = Block::new(bb);
|
||||||
log::trace!("block{}:", bb.index());
|
trace!("block{}:", bb.index());
|
||||||
let insts = self.bb_insts.get(&bb).unwrap();
|
let insts = self.bb_insts.get(&bb).unwrap();
|
||||||
let mut state = self.bb_in.get(&bb).unwrap().clone();
|
let mut state = self.bb_in.get(&bb).unwrap().clone();
|
||||||
print_state(&state);
|
print_state(&state);
|
||||||
@@ -714,7 +714,7 @@ impl<'a, F: Function> Checker<'a, F> {
|
|||||||
ref allocs,
|
ref allocs,
|
||||||
ref clobbers,
|
ref clobbers,
|
||||||
} => {
|
} => {
|
||||||
log::trace!(
|
trace!(
|
||||||
" inst{}: {:?} ({:?}) clobbers:{:?}",
|
" inst{}: {:?} ({:?}) clobbers:{:?}",
|
||||||
inst.index(),
|
inst.index(),
|
||||||
operands,
|
operands,
|
||||||
@@ -723,17 +723,17 @@ impl<'a, F: Function> Checker<'a, F> {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
&CheckerInst::Move { from, into } => {
|
&CheckerInst::Move { from, into } => {
|
||||||
log::trace!(" {} -> {}", from, into);
|
trace!(" {} -> {}", from, into);
|
||||||
}
|
}
|
||||||
&CheckerInst::DefAlloc { alloc, vreg } => {
|
&CheckerInst::DefAlloc { alloc, vreg } => {
|
||||||
log::trace!(" defalloc: {}:{}", vreg, alloc);
|
trace!(" defalloc: {}:{}", vreg, alloc);
|
||||||
}
|
}
|
||||||
&CheckerInst::Safepoint { ref allocs, .. } => {
|
&CheckerInst::Safepoint { ref allocs, .. } => {
|
||||||
let mut slotargs = vec![];
|
let mut slotargs = vec![];
|
||||||
for &slot in allocs {
|
for &slot in allocs {
|
||||||
slotargs.push(format!("{}", slot));
|
slotargs.push(format!("{}", slot));
|
||||||
}
|
}
|
||||||
log::trace!(" safepoint: {}", slotargs.join(", "));
|
trace!(" safepoint: {}", slotargs.join(", "));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
state.update(inst, &self);
|
state.update(inst, &self);
|
||||||
|
|||||||
@@ -5,16 +5,16 @@ use crate::{Block, Function, ProgPoint};
|
|||||||
|
|
||||||
impl<'a, F: Function> Env<'a, F> {
|
impl<'a, F: Function> Env<'a, F> {
|
||||||
pub fn dump_state(&self) {
|
pub fn dump_state(&self) {
|
||||||
log::trace!("Bundles:");
|
trace!("Bundles:");
|
||||||
for (i, b) in self.bundles.iter().enumerate() {
|
for (i, b) in self.bundles.iter().enumerate() {
|
||||||
log::trace!(
|
trace!(
|
||||||
"bundle{}: spillset={:?} alloc={:?}",
|
"bundle{}: spillset={:?} alloc={:?}",
|
||||||
i,
|
i,
|
||||||
b.spillset,
|
b.spillset,
|
||||||
b.allocation
|
b.allocation
|
||||||
);
|
);
|
||||||
for entry in &b.ranges {
|
for entry in &b.ranges {
|
||||||
log::trace!(
|
trace!(
|
||||||
" * range {:?} -- {:?}: range{}",
|
" * range {:?} -- {:?}: range{}",
|
||||||
entry.range.from,
|
entry.range.from,
|
||||||
entry.range.to,
|
entry.range.to,
|
||||||
@@ -22,11 +22,11 @@ impl<'a, F: Function> Env<'a, F> {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
log::trace!("VRegs:");
|
trace!("VRegs:");
|
||||||
for (i, v) in self.vregs.iter().enumerate() {
|
for (i, v) in self.vregs.iter().enumerate() {
|
||||||
log::trace!("vreg{}:", i);
|
trace!("vreg{}:", i);
|
||||||
for entry in &v.ranges {
|
for entry in &v.ranges {
|
||||||
log::trace!(
|
trace!(
|
||||||
" * range {:?} -- {:?}: range{}",
|
" * range {:?} -- {:?}: range{}",
|
||||||
entry.range.from,
|
entry.range.from,
|
||||||
entry.range.to,
|
entry.range.to,
|
||||||
@@ -34,9 +34,9 @@ impl<'a, F: Function> Env<'a, F> {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
log::trace!("Ranges:");
|
trace!("Ranges:");
|
||||||
for (i, r) in self.ranges.iter().enumerate() {
|
for (i, r) in self.ranges.iter().enumerate() {
|
||||||
log::trace!(
|
trace!(
|
||||||
"range{}: range={:?} vreg={:?} bundle={:?} weight={:?}",
|
"range{}: range={:?} vreg={:?} bundle={:?} weight={:?}",
|
||||||
i,
|
i,
|
||||||
r.range,
|
r.range,
|
||||||
@@ -45,7 +45,7 @@ impl<'a, F: Function> Env<'a, F> {
|
|||||||
r.uses_spill_weight(),
|
r.uses_spill_weight(),
|
||||||
);
|
);
|
||||||
for u in &r.uses {
|
for u in &r.uses {
|
||||||
log::trace!(" * use at {:?} (slot {}): {:?}", u.pos, u.slot, u.operand);
|
trace!(" * use at {:?} (slot {}): {:?}", u.pos, u.slot, u.operand);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -179,7 +179,7 @@ impl<'a, F: Function> Env<'a, F> {
|
|||||||
///
|
///
|
||||||
/// Returns the liverange that contains the given range.
|
/// Returns the liverange that contains the given range.
|
||||||
pub fn add_liverange_to_vreg(&mut self, vreg: VRegIndex, range: CodeRange) -> LiveRangeIndex {
|
pub fn add_liverange_to_vreg(&mut self, vreg: VRegIndex, range: CodeRange) -> LiveRangeIndex {
|
||||||
log::trace!("add_liverange_to_vreg: vreg {:?} range {:?}", vreg, range);
|
trace!("add_liverange_to_vreg: vreg {:?} range {:?}", vreg, range);
|
||||||
|
|
||||||
// Invariant: as we are building liveness information, we
|
// Invariant: as we are building liveness information, we
|
||||||
// *always* process instructions bottom-to-top, and as a
|
// *always* process instructions bottom-to-top, and as a
|
||||||
@@ -246,7 +246,7 @@ impl<'a, F: Function> Env<'a, F> {
|
|||||||
);
|
);
|
||||||
u.weight = weight.to_bits();
|
u.weight = weight.to_bits();
|
||||||
|
|
||||||
log::trace!(
|
trace!(
|
||||||
"insert use {:?} into lr {:?} with weight {:?}",
|
"insert use {:?} into lr {:?} with weight {:?}",
|
||||||
u,
|
u,
|
||||||
into,
|
into,
|
||||||
@@ -262,7 +262,7 @@ impl<'a, F: Function> Env<'a, F> {
|
|||||||
// Update stats.
|
// Update stats.
|
||||||
let range_weight = self.ranges[into.index()].uses_spill_weight() + weight;
|
let range_weight = self.ranges[into.index()].uses_spill_weight() + weight;
|
||||||
self.ranges[into.index()].set_uses_spill_weight(range_weight);
|
self.ranges[into.index()].set_uses_spill_weight(range_weight);
|
||||||
log::trace!(
|
trace!(
|
||||||
" -> now range has weight {:?}",
|
" -> now range has weight {:?}",
|
||||||
self.ranges[into.index()].uses_spill_weight(),
|
self.ranges[into.index()].uses_spill_weight(),
|
||||||
);
|
);
|
||||||
@@ -282,7 +282,7 @@ impl<'a, F: Function> Env<'a, F> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn add_liverange_to_preg(&mut self, range: CodeRange, reg: PReg) {
|
pub fn add_liverange_to_preg(&mut self, range: CodeRange, reg: PReg) {
|
||||||
log::trace!("adding liverange to preg: {:?} to {}", range, reg);
|
trace!("adding liverange to preg: {:?} to {}", range, reg);
|
||||||
let preg_idx = PRegIndex::new(reg.index());
|
let preg_idx = PRegIndex::new(reg.index());
|
||||||
self.pregs[preg_idx.index()]
|
self.pregs[preg_idx.index()]
|
||||||
.allocations
|
.allocations
|
||||||
@@ -316,12 +316,12 @@ impl<'a, F: Function> Env<'a, F> {
|
|||||||
workqueue_set.remove(&block);
|
workqueue_set.remove(&block);
|
||||||
let insns = self.func.block_insns(block);
|
let insns = self.func.block_insns(block);
|
||||||
|
|
||||||
log::trace!("computing liveins for block{}", block.index());
|
trace!("computing liveins for block{}", block.index());
|
||||||
|
|
||||||
self.stats.livein_iterations += 1;
|
self.stats.livein_iterations += 1;
|
||||||
|
|
||||||
let mut live = self.liveouts[block.index()].clone();
|
let mut live = self.liveouts[block.index()].clone();
|
||||||
log::trace!(" -> initial liveout set: {:?}", live);
|
trace!(" -> initial liveout set: {:?}", live);
|
||||||
|
|
||||||
// Include outgoing blockparams in the initial live set.
|
// Include outgoing blockparams in the initial live set.
|
||||||
if self.func.is_branch(insns.last()) {
|
if self.func.is_branch(insns.last()) {
|
||||||
@@ -342,7 +342,7 @@ impl<'a, F: Function> Env<'a, F> {
|
|||||||
for op in self.func.inst_operands(inst) {
|
for op in self.func.inst_operands(inst) {
|
||||||
if op.pos() == *pos {
|
if op.pos() == *pos {
|
||||||
let was_live = live.get(op.vreg().vreg());
|
let was_live = live.get(op.vreg().vreg());
|
||||||
log::trace!("op {:?} was_live = {}", op, was_live);
|
trace!("op {:?} was_live = {}", op, was_live);
|
||||||
match op.kind() {
|
match op.kind() {
|
||||||
OperandKind::Use | OperandKind::Mod => {
|
OperandKind::Use | OperandKind::Mod => {
|
||||||
live.set(op.vreg().vreg(), true);
|
live.set(op.vreg().vreg(), true);
|
||||||
@@ -368,7 +368,7 @@ impl<'a, F: Function> Env<'a, F> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
log::trace!("computed liveins at block{}: {:?}", block.index(), live);
|
trace!("computed liveins at block{}: {:?}", block.index(), live);
|
||||||
self.liveins[block.index()] = live;
|
self.liveins[block.index()] = live;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -380,7 +380,7 @@ impl<'a, F: Function> Env<'a, F> {
|
|||||||
.next()
|
.next()
|
||||||
.is_some()
|
.is_some()
|
||||||
{
|
{
|
||||||
log::trace!(
|
trace!(
|
||||||
"non-empty liveins to entry block: {:?}",
|
"non-empty liveins to entry block: {:?}",
|
||||||
self.liveins[self.func.entry_block().index()]
|
self.liveins[self.func.entry_block().index()]
|
||||||
);
|
);
|
||||||
@@ -449,7 +449,7 @@ impl<'a, F: Function> Env<'a, F> {
|
|||||||
from: self.cfginfo.block_entry[block.index()],
|
from: self.cfginfo.block_entry[block.index()],
|
||||||
to: self.cfginfo.block_exit[block.index()].next(),
|
to: self.cfginfo.block_exit[block.index()].next(),
|
||||||
};
|
};
|
||||||
log::trace!(
|
trace!(
|
||||||
"vreg {:?} live at end of block --> create range {:?}",
|
"vreg {:?} live at end of block --> create range {:?}",
|
||||||
VRegIndex::new(vreg),
|
VRegIndex::new(vreg),
|
||||||
range
|
range
|
||||||
@@ -499,7 +499,7 @@ impl<'a, F: Function> Env<'a, F> {
|
|||||||
// We can completely skip the move if it is
|
// We can completely skip the move if it is
|
||||||
// trivial (vreg to same vreg).
|
// trivial (vreg to same vreg).
|
||||||
if src.vreg() != dst.vreg() {
|
if src.vreg() != dst.vreg() {
|
||||||
log::trace!(" -> move inst{}: src {} -> dst {}", inst.index(), src, dst);
|
trace!(" -> move inst{}: src {} -> dst {}", inst.index(), src, dst);
|
||||||
|
|
||||||
debug_assert_eq!(src.class(), dst.class());
|
debug_assert_eq!(src.class(), dst.class());
|
||||||
debug_assert_eq!(src.kind(), OperandKind::Use);
|
debug_assert_eq!(src.kind(), OperandKind::Use);
|
||||||
@@ -561,9 +561,7 @@ impl<'a, F: Function> Env<'a, F> {
|
|||||||
else if self.vregs[src.vreg().vreg()].is_pinned
|
else if self.vregs[src.vreg().vreg()].is_pinned
|
||||||
|| self.vregs[dst.vreg().vreg()].is_pinned
|
|| self.vregs[dst.vreg().vreg()].is_pinned
|
||||||
{
|
{
|
||||||
log::trace!(
|
trace!(" -> exactly one of src/dst is pinned; converting to ghost use");
|
||||||
" -> exactly one of src/dst is pinned; converting to ghost use"
|
|
||||||
);
|
|
||||||
let (preg, vreg, pinned_vreg, kind, pos, progpoint) =
|
let (preg, vreg, pinned_vreg, kind, pos, progpoint) =
|
||||||
if self.vregs[src.vreg().vreg()].is_pinned {
|
if self.vregs[src.vreg().vreg()].is_pinned {
|
||||||
// Source is pinned: this is a def on the dst with a pinned preg.
|
// Source is pinned: this is a def on the dst with a pinned preg.
|
||||||
@@ -589,7 +587,7 @@ impl<'a, F: Function> Env<'a, F> {
|
|||||||
let constraint = OperandConstraint::FixedReg(preg);
|
let constraint = OperandConstraint::FixedReg(preg);
|
||||||
let operand = Operand::new(vreg, constraint, kind, pos);
|
let operand = Operand::new(vreg, constraint, kind, pos);
|
||||||
|
|
||||||
log::trace!(
|
trace!(
|
||||||
concat!(
|
concat!(
|
||||||
" -> preg {:?} vreg {:?} kind {:?} ",
|
" -> preg {:?} vreg {:?} kind {:?} ",
|
||||||
"pos {:?} progpoint {:?} constraint {:?} operand {:?}"
|
"pos {:?} progpoint {:?} constraint {:?} operand {:?}"
|
||||||
@@ -616,9 +614,9 @@ impl<'a, F: Function> Env<'a, F> {
|
|||||||
VRegIndex::new(vreg.vreg()),
|
VRegIndex::new(vreg.vreg()),
|
||||||
CodeRange { from, to },
|
CodeRange { from, to },
|
||||||
);
|
);
|
||||||
log::trace!(" -> dead; created LR");
|
trace!(" -> dead; created LR");
|
||||||
}
|
}
|
||||||
log::trace!(" -> LR {:?}", lr);
|
trace!(" -> LR {:?}", lr);
|
||||||
|
|
||||||
self.insert_use_into_liverange(
|
self.insert_use_into_liverange(
|
||||||
lr,
|
lr,
|
||||||
@@ -652,7 +650,7 @@ impl<'a, F: Function> Env<'a, F> {
|
|||||||
// (this is the last use), start it
|
// (this is the last use), start it
|
||||||
// before.
|
// before.
|
||||||
if kind == OperandKind::Def {
|
if kind == OperandKind::Def {
|
||||||
log::trace!(" -> src on pinned vreg {:?}", pinned_vreg);
|
trace!(" -> src on pinned vreg {:?}", pinned_vreg);
|
||||||
// The *other* vreg is a def, so the pinned-vreg
|
// The *other* vreg is a def, so the pinned-vreg
|
||||||
// mention is a use. If already live,
|
// mention is a use. If already live,
|
||||||
// end the existing LR just *after*
|
// end the existing LR just *after*
|
||||||
@@ -666,7 +664,7 @@ impl<'a, F: Function> Env<'a, F> {
|
|||||||
if live.get(pinned_vreg.vreg()) {
|
if live.get(pinned_vreg.vreg()) {
|
||||||
let pinned_lr = vreg_ranges[pinned_vreg.vreg()];
|
let pinned_lr = vreg_ranges[pinned_vreg.vreg()];
|
||||||
let orig_start = self.ranges[pinned_lr.index()].range.from;
|
let orig_start = self.ranges[pinned_lr.index()].range.from;
|
||||||
log::trace!(
|
trace!(
|
||||||
" -> live with LR {:?}; truncating to start at {:?}",
|
" -> live with LR {:?}; truncating to start at {:?}",
|
||||||
pinned_lr,
|
pinned_lr,
|
||||||
progpoint.next()
|
progpoint.next()
|
||||||
@@ -680,7 +678,7 @@ impl<'a, F: Function> Env<'a, F> {
|
|||||||
},
|
},
|
||||||
);
|
);
|
||||||
vreg_ranges[pinned_vreg.vreg()] = new_lr;
|
vreg_ranges[pinned_vreg.vreg()] = new_lr;
|
||||||
log::trace!(" -> created LR {:?} with remaining range from {:?} to {:?}", new_lr, orig_start, progpoint);
|
trace!(" -> created LR {:?} with remaining range from {:?} to {:?}", new_lr, orig_start, progpoint);
|
||||||
|
|
||||||
// Add an edit right now to indicate that at
|
// Add an edit right now to indicate that at
|
||||||
// this program point, the given
|
// this program point, the given
|
||||||
@@ -714,10 +712,7 @@ impl<'a, F: Function> Env<'a, F> {
|
|||||||
);
|
);
|
||||||
vreg_ranges[pinned_vreg.vreg()] = new_lr;
|
vreg_ranges[pinned_vreg.vreg()] = new_lr;
|
||||||
live.set(pinned_vreg.vreg(), true);
|
live.set(pinned_vreg.vreg(), true);
|
||||||
log::trace!(
|
trace!(" -> was not live; created new LR {:?}", new_lr);
|
||||||
" -> was not live; created new LR {:?}",
|
|
||||||
new_lr
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add an edit right now to indicate that at
|
// Add an edit right now to indicate that at
|
||||||
@@ -734,7 +729,7 @@ impl<'a, F: Function> Env<'a, F> {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
log::trace!(" -> dst on pinned vreg {:?}", pinned_vreg);
|
trace!(" -> dst on pinned vreg {:?}", pinned_vreg);
|
||||||
// The *other* vreg is a use, so the pinned-vreg
|
// The *other* vreg is a use, so the pinned-vreg
|
||||||
// mention is a def. Truncate its LR
|
// mention is a def. Truncate its LR
|
||||||
// just *after* the `progpoint`
|
// just *after* the `progpoint`
|
||||||
@@ -742,7 +737,7 @@ impl<'a, F: Function> Env<'a, F> {
|
|||||||
if live.get(pinned_vreg.vreg()) {
|
if live.get(pinned_vreg.vreg()) {
|
||||||
let pinned_lr = vreg_ranges[pinned_vreg.vreg()];
|
let pinned_lr = vreg_ranges[pinned_vreg.vreg()];
|
||||||
self.ranges[pinned_lr.index()].range.from = progpoint.next();
|
self.ranges[pinned_lr.index()].range.from = progpoint.next();
|
||||||
log::trace!(
|
trace!(
|
||||||
" -> was live with LR {:?}; truncated start to {:?}",
|
" -> was live with LR {:?}; truncated start to {:?}",
|
||||||
pinned_lr,
|
pinned_lr,
|
||||||
progpoint.next()
|
progpoint.next()
|
||||||
@@ -842,14 +837,14 @@ impl<'a, F: Function> Env<'a, F> {
|
|||||||
VRegIndex::new(dst.vreg().vreg()),
|
VRegIndex::new(dst.vreg().vreg()),
|
||||||
CodeRange { from, to },
|
CodeRange { from, to },
|
||||||
);
|
);
|
||||||
log::trace!(" -> invalid LR for def; created {:?}", dst_lr);
|
trace!(" -> invalid LR for def; created {:?}", dst_lr);
|
||||||
}
|
}
|
||||||
log::trace!(" -> has existing LR {:?}", dst_lr);
|
trace!(" -> has existing LR {:?}", dst_lr);
|
||||||
// Trim the LR to start here.
|
// Trim the LR to start here.
|
||||||
if self.ranges[dst_lr.index()].range.from
|
if self.ranges[dst_lr.index()].range.from
|
||||||
== self.cfginfo.block_entry[block.index()]
|
== self.cfginfo.block_entry[block.index()]
|
||||||
{
|
{
|
||||||
log::trace!(" -> started at block start; trimming to {:?}", pos);
|
trace!(" -> started at block start; trimming to {:?}", pos);
|
||||||
self.ranges[dst_lr.index()].range.from = pos;
|
self.ranges[dst_lr.index()].range.from = pos;
|
||||||
}
|
}
|
||||||
self.ranges[dst_lr.index()].set_flag(LiveRangeFlag::StartsAtDef);
|
self.ranges[dst_lr.index()].set_flag(LiveRangeFlag::StartsAtDef);
|
||||||
@@ -876,7 +871,7 @@ impl<'a, F: Function> Env<'a, F> {
|
|||||||
vreg_ranges[src.vreg().vreg()]
|
vreg_ranges[src.vreg().vreg()]
|
||||||
};
|
};
|
||||||
|
|
||||||
log::trace!(" -> src LR {:?}", src_lr);
|
trace!(" -> src LR {:?}", src_lr);
|
||||||
|
|
||||||
// Add to live-set.
|
// Add to live-set.
|
||||||
let src_is_dead_after_move = !live.get(src.vreg().vreg());
|
let src_is_dead_after_move = !live.get(src.vreg().vreg());
|
||||||
@@ -929,7 +924,7 @@ impl<'a, F: Function> Env<'a, F> {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
log::trace!(
|
trace!(
|
||||||
"processing inst{} operand at {:?}: {:?}",
|
"processing inst{} operand at {:?}: {:?}",
|
||||||
inst.index(),
|
inst.index(),
|
||||||
pos,
|
pos,
|
||||||
@@ -938,14 +933,14 @@ impl<'a, F: Function> Env<'a, F> {
|
|||||||
|
|
||||||
match operand.kind() {
|
match operand.kind() {
|
||||||
OperandKind::Def | OperandKind::Mod => {
|
OperandKind::Def | OperandKind::Mod => {
|
||||||
log::trace!("Def of {} at {:?}", operand.vreg(), pos);
|
trace!("Def of {} at {:?}", operand.vreg(), pos);
|
||||||
|
|
||||||
// Fill in vreg's actual data.
|
// Fill in vreg's actual data.
|
||||||
self.vreg_regs[operand.vreg().vreg()] = operand.vreg();
|
self.vreg_regs[operand.vreg().vreg()] = operand.vreg();
|
||||||
|
|
||||||
// Get or create the LiveRange.
|
// Get or create the LiveRange.
|
||||||
let mut lr = vreg_ranges[operand.vreg().vreg()];
|
let mut lr = vreg_ranges[operand.vreg().vreg()];
|
||||||
log::trace!(" -> has existing LR {:?}", lr);
|
trace!(" -> 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() {
|
let from = match operand.kind() {
|
||||||
@@ -962,7 +957,7 @@ impl<'a, F: Function> Env<'a, F> {
|
|||||||
VRegIndex::new(operand.vreg().vreg()),
|
VRegIndex::new(operand.vreg().vreg()),
|
||||||
CodeRange { from, to },
|
CodeRange { from, to },
|
||||||
);
|
);
|
||||||
log::trace!(" -> invalid; created {:?}", lr);
|
trace!(" -> invalid; created {:?}", lr);
|
||||||
vreg_ranges[operand.vreg().vreg()] = lr;
|
vreg_ranges[operand.vreg().vreg()] = lr;
|
||||||
live.set(operand.vreg().vreg(), true);
|
live.set(operand.vreg().vreg(), true);
|
||||||
}
|
}
|
||||||
@@ -979,10 +974,7 @@ impl<'a, F: Function> Env<'a, F> {
|
|||||||
if self.ranges[lr.index()].range.from
|
if self.ranges[lr.index()].range.from
|
||||||
== self.cfginfo.block_entry[block.index()]
|
== self.cfginfo.block_entry[block.index()]
|
||||||
{
|
{
|
||||||
log::trace!(
|
trace!(" -> started at block start; trimming to {:?}", pos);
|
||||||
" -> started at block start; trimming to {:?}",
|
|
||||||
pos
|
|
||||||
);
|
|
||||||
self.ranges[lr.index()].range.from = pos;
|
self.ranges[lr.index()].range.from = pos;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1011,7 +1003,7 @@ impl<'a, F: Function> Env<'a, F> {
|
|||||||
}
|
}
|
||||||
debug_assert!(lr.is_valid());
|
debug_assert!(lr.is_valid());
|
||||||
|
|
||||||
log::trace!("Use of {:?} at {:?} -> {:?}", operand, pos, lr,);
|
trace!("Use of {:?} at {:?} -> {:?}", operand, pos, lr,);
|
||||||
|
|
||||||
self.insert_use_into_liverange(lr, Use::new(operand, pos, i as u8));
|
self.insert_use_into_liverange(lr, Use::new(operand, pos, i as u8));
|
||||||
|
|
||||||
@@ -1023,11 +1015,11 @@ impl<'a, F: Function> Env<'a, F> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if self.func.requires_refs_on_stack(inst) {
|
if self.func.requires_refs_on_stack(inst) {
|
||||||
log::trace!("inst{} is safepoint", inst.index());
|
trace!("inst{} is safepoint", inst.index());
|
||||||
self.safepoints.push(inst);
|
self.safepoints.push(inst);
|
||||||
for vreg in live.iter() {
|
for vreg in live.iter() {
|
||||||
if let Some(safepoints) = self.safepoints_per_vreg.get_mut(&vreg) {
|
if let Some(safepoints) = self.safepoints_per_vreg.get_mut(&vreg) {
|
||||||
log::trace!("vreg v{} live at safepoint inst{}", vreg, inst.index());
|
trace!("vreg v{} live at safepoint inst{}", vreg, inst.index());
|
||||||
safepoints.insert(inst);
|
safepoints.insert(inst);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1124,7 +1116,7 @@ impl<'a, F: Function> Env<'a, F> {
|
|||||||
OperandPos::Early,
|
OperandPos::Early,
|
||||||
);
|
);
|
||||||
|
|
||||||
log::trace!(
|
trace!(
|
||||||
"Safepoint-induced stack use of {:?} at {:?} -> {:?}",
|
"Safepoint-induced stack use of {:?} at {:?} -> {:?}",
|
||||||
operand,
|
operand,
|
||||||
pos,
|
pos,
|
||||||
@@ -1154,8 +1146,8 @@ impl<'a, F: Function> Env<'a, F> {
|
|||||||
self.prog_move_srcs.sort_unstable_by_key(|(pos, _)| *pos);
|
self.prog_move_srcs.sort_unstable_by_key(|(pos, _)| *pos);
|
||||||
self.prog_move_dsts.sort_unstable_by_key(|(pos, _)| *pos);
|
self.prog_move_dsts.sort_unstable_by_key(|(pos, _)| *pos);
|
||||||
|
|
||||||
log::trace!("prog_move_srcs = {:?}", self.prog_move_srcs);
|
trace!("prog_move_srcs = {:?}", self.prog_move_srcs);
|
||||||
log::trace!("prog_move_dsts = {:?}", self.prog_move_dsts);
|
trace!("prog_move_dsts = {:?}", self.prog_move_dsts);
|
||||||
|
|
||||||
self.stats.initial_liverange_count = self.ranges.len();
|
self.stats.initial_liverange_count = self.ranges.len();
|
||||||
self.stats.blockparam_ins_count = self.blockparam_ins.len();
|
self.stats.blockparam_ins_count = self.blockparam_ins.len();
|
||||||
@@ -1177,7 +1169,7 @@ impl<'a, F: Function> Env<'a, F> {
|
|||||||
for range_idx in 0..self.vregs[vreg].ranges.len() {
|
for range_idx in 0..self.vregs[vreg].ranges.len() {
|
||||||
let entry = self.vregs[vreg].ranges[range_idx];
|
let entry = self.vregs[vreg].ranges[range_idx];
|
||||||
let range = entry.index;
|
let range = entry.index;
|
||||||
log::trace!(
|
trace!(
|
||||||
"multi-fixed-reg cleanup: vreg {:?} range {:?}",
|
"multi-fixed-reg cleanup: vreg {:?} range {:?}",
|
||||||
VRegIndex::new(vreg),
|
VRegIndex::new(vreg),
|
||||||
range,
|
range,
|
||||||
@@ -1246,7 +1238,7 @@ impl<'a, F: Function> Env<'a, F> {
|
|||||||
if let OperandConstraint::FixedReg(preg) = u.operand.constraint() {
|
if let OperandConstraint::FixedReg(preg) = u.operand.constraint() {
|
||||||
let vreg_idx = VRegIndex::new(u.operand.vreg().vreg());
|
let vreg_idx = VRegIndex::new(u.operand.vreg().vreg());
|
||||||
let preg_idx = PRegIndex::new(preg.index());
|
let preg_idx = PRegIndex::new(preg.index());
|
||||||
log::trace!(
|
trace!(
|
||||||
"at pos {:?}, vreg {:?} has fixed constraint to preg {:?}",
|
"at pos {:?}, vreg {:?} has fixed constraint to preg {:?}",
|
||||||
u.pos,
|
u.pos,
|
||||||
vreg_idx,
|
vreg_idx,
|
||||||
@@ -1265,7 +1257,7 @@ impl<'a, F: Function> Env<'a, F> {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
log::trace!(" -> duplicate; switching to constraint Any");
|
trace!(" -> duplicate; switching to constraint Any");
|
||||||
self.multi_fixed_reg_fixups.push(MultiFixedRegFixup {
|
self.multi_fixed_reg_fixups.push(MultiFixedRegFixup {
|
||||||
pos: u.pos,
|
pos: u.pos,
|
||||||
from_slot: source_slot,
|
from_slot: source_slot,
|
||||||
@@ -1279,11 +1271,7 @@ impl<'a, F: Function> Env<'a, F> {
|
|||||||
u.operand.kind(),
|
u.operand.kind(),
|
||||||
u.operand.pos(),
|
u.operand.pos(),
|
||||||
);
|
);
|
||||||
log::trace!(
|
trace!(" -> extra clobber {} at inst{}", preg, u.pos.inst().index());
|
||||||
" -> extra clobber {} at inst{}",
|
|
||||||
preg,
|
|
||||||
u.pos.inst().index()
|
|
||||||
);
|
|
||||||
extra_clobbers.push((preg, u.pos.inst()));
|
extra_clobbers.push((preg, u.pos.inst()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ impl<'a, F: Function> Env<'a, F> {
|
|||||||
// Merge bundle into self -- trivial merge.
|
// Merge bundle into self -- trivial merge.
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
log::trace!(
|
trace!(
|
||||||
"merging from bundle{} to bundle{}",
|
"merging from bundle{} to bundle{}",
|
||||||
from.index(),
|
from.index(),
|
||||||
to.index()
|
to.index()
|
||||||
@@ -35,7 +35,7 @@ impl<'a, F: Function> Env<'a, F> {
|
|||||||
let from_rc = self.spillsets[self.bundles[from.index()].spillset.index()].class;
|
let from_rc = self.spillsets[self.bundles[from.index()].spillset.index()].class;
|
||||||
let to_rc = self.spillsets[self.bundles[to.index()].spillset.index()].class;
|
let to_rc = self.spillsets[self.bundles[to.index()].spillset.index()].class;
|
||||||
if from_rc != to_rc {
|
if from_rc != to_rc {
|
||||||
log::trace!(" -> mismatching reg classes");
|
trace!(" -> mismatching reg classes");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -43,7 +43,7 @@ impl<'a, F: Function> Env<'a, F> {
|
|||||||
if self.bundles[from.index()].allocation.is_some()
|
if self.bundles[from.index()].allocation.is_some()
|
||||||
|| self.bundles[to.index()].allocation.is_some()
|
|| self.bundles[to.index()].allocation.is_some()
|
||||||
{
|
{
|
||||||
log::trace!("one of the bundles is already assigned (pinned)");
|
trace!("one of the bundles is already assigned (pinned)");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -70,7 +70,7 @@ impl<'a, F: Function> Env<'a, F> {
|
|||||||
while idx_from < ranges_from.len() && idx_to < ranges_to.len() {
|
while idx_from < ranges_from.len() && idx_to < ranges_to.len() {
|
||||||
range_count += 1;
|
range_count += 1;
|
||||||
if range_count > 200 {
|
if range_count > 200 {
|
||||||
log::trace!(
|
trace!(
|
||||||
"reached merge complexity (range_count = {}); exiting",
|
"reached merge complexity (range_count = {}); exiting",
|
||||||
range_count
|
range_count
|
||||||
);
|
);
|
||||||
@@ -84,7 +84,7 @@ impl<'a, F: Function> Env<'a, F> {
|
|||||||
idx_from += 1;
|
idx_from += 1;
|
||||||
} else {
|
} else {
|
||||||
// Overlap -- cannot merge.
|
// Overlap -- cannot merge.
|
||||||
log::trace!(
|
trace!(
|
||||||
" -> overlap between {:?} and {:?}, exiting",
|
" -> overlap between {:?} and {:?}, exiting",
|
||||||
ranges_from[idx_from].index,
|
ranges_from[idx_from].index,
|
||||||
ranges_to[idx_to].index
|
ranges_to[idx_to].index
|
||||||
@@ -100,12 +100,12 @@ impl<'a, F: Function> Env<'a, F> {
|
|||||||
|| self.bundles[to.index()].cached_fixed()
|
|| self.bundles[to.index()].cached_fixed()
|
||||||
{
|
{
|
||||||
if self.merge_bundle_requirements(from, to).is_err() {
|
if self.merge_bundle_requirements(from, to).is_err() {
|
||||||
log::trace!(" -> conflicting requirements; aborting merge");
|
trace!(" -> conflicting requirements; aborting merge");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
log::trace!(" -> committing to merge");
|
trace!(" -> committing to merge");
|
||||||
|
|
||||||
// If we reach here, then the bundles do not overlap -- merge
|
// If we reach here, then the bundles do not overlap -- merge
|
||||||
// them! We do this with a merge-sort-like scan over both
|
// them! We do this with a merge-sort-like scan over both
|
||||||
@@ -113,13 +113,13 @@ impl<'a, F: Function> Env<'a, F> {
|
|||||||
// `to` when we're done.
|
// `to` when we're done.
|
||||||
if ranges_from.is_empty() {
|
if ranges_from.is_empty() {
|
||||||
// `from` bundle is empty -- trivial merge.
|
// `from` bundle is empty -- trivial merge.
|
||||||
log::trace!(" -> from bundle{} is empty; trivial merge", from.index());
|
trace!(" -> from bundle{} is empty; trivial merge", from.index());
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if ranges_to.is_empty() {
|
if ranges_to.is_empty() {
|
||||||
// `to` bundle is empty -- just move the list over from
|
// `to` bundle is empty -- just move the list over from
|
||||||
// `from` and set `bundle` up-link on all ranges.
|
// `from` and set `bundle` up-link on all ranges.
|
||||||
log::trace!(" -> to bundle{} is empty; trivial merge", to.index());
|
trace!(" -> to bundle{} is empty; trivial merge", to.index());
|
||||||
let list = std::mem::replace(&mut self.bundles[from.index()].ranges, smallvec![]);
|
let list = std::mem::replace(&mut self.bundles[from.index()].ranges, smallvec![]);
|
||||||
for entry in &list {
|
for entry in &list {
|
||||||
self.ranges[entry.index.index()].bundle = to;
|
self.ranges[entry.index.index()].bundle = to;
|
||||||
@@ -149,7 +149,7 @@ impl<'a, F: Function> Env<'a, F> {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
log::trace!(
|
trace!(
|
||||||
"merging: ranges_from = {:?} ranges_to = {:?}",
|
"merging: ranges_from = {:?} ranges_to = {:?}",
|
||||||
ranges_from,
|
ranges_from,
|
||||||
ranges_to
|
ranges_to
|
||||||
@@ -170,7 +170,7 @@ impl<'a, F: Function> Env<'a, F> {
|
|||||||
.sort_unstable_by_key(|entry| entry.range.from);
|
.sort_unstable_by_key(|entry| entry.range.from);
|
||||||
|
|
||||||
if self.annotations_enabled {
|
if self.annotations_enabled {
|
||||||
log::trace!("merging: merged = {:?}", self.bundles[to.index()].ranges);
|
trace!("merging: merged = {:?}", self.bundles[to.index()].ranges);
|
||||||
let mut last_range = None;
|
let mut last_range = None;
|
||||||
for i in 0..self.bundles[to.index()].ranges.len() {
|
for i in 0..self.bundles[to.index()].ranges.len() {
|
||||||
let entry = self.bundles[to.index()].ranges[i];
|
let entry = self.bundles[to.index()].ranges[i];
|
||||||
@@ -192,7 +192,7 @@ impl<'a, F: Function> Env<'a, F> {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
log::trace!(
|
trace!(
|
||||||
" -> merged result for bundle{}: range{}",
|
" -> merged result for bundle{}: range{}",
|
||||||
to.index(),
|
to.index(),
|
||||||
entry.index.index(),
|
entry.index.index(),
|
||||||
@@ -225,7 +225,7 @@ impl<'a, F: Function> Env<'a, F> {
|
|||||||
|
|
||||||
pub fn merge_vreg_bundles(&mut self) {
|
pub fn merge_vreg_bundles(&mut self) {
|
||||||
// Create a bundle for every vreg, initially.
|
// Create a bundle for every vreg, initially.
|
||||||
log::trace!("merge_vreg_bundles: creating vreg bundles");
|
trace!("merge_vreg_bundles: creating vreg bundles");
|
||||||
for vreg in 0..self.vregs.len() {
|
for vreg in 0..self.vregs.len() {
|
||||||
let vreg = VRegIndex::new(vreg);
|
let vreg = VRegIndex::new(vreg);
|
||||||
if self.vregs[vreg.index()].ranges.is_empty() {
|
if self.vregs[vreg.index()].ranges.is_empty() {
|
||||||
@@ -251,9 +251,9 @@ impl<'a, F: Function> Env<'a, F> {
|
|||||||
|
|
||||||
let bundle = self.create_bundle();
|
let bundle = self.create_bundle();
|
||||||
self.bundles[bundle.index()].ranges = self.vregs[vreg.index()].ranges.clone();
|
self.bundles[bundle.index()].ranges = self.vregs[vreg.index()].ranges.clone();
|
||||||
log::trace!("vreg v{} gets bundle{}", vreg.index(), bundle.index());
|
trace!("vreg v{} gets bundle{}", vreg.index(), bundle.index());
|
||||||
for entry in &self.bundles[bundle.index()].ranges {
|
for entry in &self.bundles[bundle.index()].ranges {
|
||||||
log::trace!(
|
trace!(
|
||||||
" -> with LR range{}: {:?}",
|
" -> with LR range{}: {:?}",
|
||||||
entry.index.index(),
|
entry.index.index(),
|
||||||
entry.range
|
entry.range
|
||||||
@@ -314,7 +314,7 @@ impl<'a, F: Function> Env<'a, F> {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
log::trace!(
|
trace!(
|
||||||
"trying to merge reused-input def: src {} to dst {}",
|
"trying to merge reused-input def: src {} to dst {}",
|
||||||
src_vreg,
|
src_vreg,
|
||||||
dst_vreg
|
dst_vreg
|
||||||
@@ -335,7 +335,7 @@ impl<'a, F: Function> Env<'a, F> {
|
|||||||
let BlockparamOut {
|
let BlockparamOut {
|
||||||
from_vreg, to_vreg, ..
|
from_vreg, to_vreg, ..
|
||||||
} = self.blockparam_outs[i];
|
} = self.blockparam_outs[i];
|
||||||
log::trace!(
|
trace!(
|
||||||
"trying to merge blockparam v{} with input v{}",
|
"trying to merge blockparam v{} with input v{}",
|
||||||
to_vreg.index(),
|
to_vreg.index(),
|
||||||
from_vreg.index()
|
from_vreg.index()
|
||||||
@@ -345,7 +345,7 @@ impl<'a, F: Function> Env<'a, F> {
|
|||||||
let from_bundle =
|
let from_bundle =
|
||||||
self.ranges[self.vregs[from_vreg.index()].ranges[0].index.index()].bundle;
|
self.ranges[self.vregs[from_vreg.index()].ranges[0].index.index()].bundle;
|
||||||
debug_assert!(from_bundle.is_valid());
|
debug_assert!(from_bundle.is_valid());
|
||||||
log::trace!(
|
trace!(
|
||||||
" -> from bundle{} to bundle{}",
|
" -> from bundle{} to bundle{}",
|
||||||
from_bundle.index(),
|
from_bundle.index(),
|
||||||
to_bundle.index()
|
to_bundle.index()
|
||||||
@@ -356,10 +356,10 @@ impl<'a, F: Function> Env<'a, F> {
|
|||||||
// Attempt to merge move srcs/dsts.
|
// Attempt to merge move srcs/dsts.
|
||||||
for i in 0..self.prog_move_merges.len() {
|
for i in 0..self.prog_move_merges.len() {
|
||||||
let (src, dst) = self.prog_move_merges[i];
|
let (src, dst) = self.prog_move_merges[i];
|
||||||
log::trace!("trying to merge move src LR {:?} to dst LR {:?}", src, dst);
|
trace!("trying to merge move src LR {:?} to dst LR {:?}", src, dst);
|
||||||
let src = self.resolve_merged_lr(src);
|
let src = self.resolve_merged_lr(src);
|
||||||
let dst = self.resolve_merged_lr(dst);
|
let dst = self.resolve_merged_lr(dst);
|
||||||
log::trace!(
|
trace!(
|
||||||
"resolved LR-construction merging chains: move-merge is now src LR {:?} to dst LR {:?}",
|
"resolved LR-construction merging chains: move-merge is now src LR {:?} to dst LR {:?}",
|
||||||
src,
|
src,
|
||||||
dst
|
dst
|
||||||
@@ -395,7 +395,7 @@ impl<'a, F: Function> Env<'a, F> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
log::trace!("done merging bundles");
|
trace!("done merging bundles");
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn resolve_merged_lr(&self, mut lr: LiveRangeIndex) -> LiveRangeIndex {
|
pub fn resolve_merged_lr(&self, mut lr: LiveRangeIndex) -> LiveRangeIndex {
|
||||||
@@ -419,14 +419,14 @@ impl<'a, F: Function> Env<'a, F> {
|
|||||||
|
|
||||||
pub fn queue_bundles(&mut self) {
|
pub fn queue_bundles(&mut self) {
|
||||||
for bundle in 0..self.bundles.len() {
|
for bundle in 0..self.bundles.len() {
|
||||||
log::trace!("enqueueing bundle{}", bundle);
|
trace!("enqueueing bundle{}", bundle);
|
||||||
if self.bundles[bundle].ranges.is_empty() {
|
if self.bundles[bundle].ranges.is_empty() {
|
||||||
log::trace!(" -> no ranges; skipping");
|
trace!(" -> no ranges; skipping");
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
let bundle = LiveBundleIndex::new(bundle);
|
let bundle = LiveBundleIndex::new(bundle);
|
||||||
let prio = self.compute_bundle_prio(bundle);
|
let prio = self.compute_bundle_prio(bundle);
|
||||||
log::trace!(" -> prio {}", prio);
|
trace!(" -> prio {}", prio);
|
||||||
self.bundles[bundle.index()].prio = prio;
|
self.bundles[bundle.index()].prio = prio;
|
||||||
self.recompute_bundle_properties(bundle);
|
self.recompute_bundle_properties(bundle);
|
||||||
self.allocation_queue
|
self.allocation_queue
|
||||||
|
|||||||
@@ -54,7 +54,7 @@ impl<'a, F: Function> Env<'a, F> {
|
|||||||
to_alloc: Allocation,
|
to_alloc: Allocation,
|
||||||
to_vreg: Option<VReg>,
|
to_vreg: Option<VReg>,
|
||||||
) {
|
) {
|
||||||
log::trace!(
|
trace!(
|
||||||
"insert_move: pos {:?} prio {:?} from_alloc {:?} to_alloc {:?}",
|
"insert_move: pos {:?} prio {:?} from_alloc {:?} to_alloc {:?}",
|
||||||
pos,
|
pos,
|
||||||
prio,
|
prio,
|
||||||
@@ -89,16 +89,16 @@ impl<'a, F: Function> Env<'a, F> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_alloc_for_range(&self, range: LiveRangeIndex) -> Allocation {
|
pub fn get_alloc_for_range(&self, range: LiveRangeIndex) -> Allocation {
|
||||||
log::trace!("get_alloc_for_range: {:?}", range);
|
trace!("get_alloc_for_range: {:?}", range);
|
||||||
let bundle = self.ranges[range.index()].bundle;
|
let bundle = self.ranges[range.index()].bundle;
|
||||||
log::trace!(" -> bundle: {:?}", bundle);
|
trace!(" -> bundle: {:?}", bundle);
|
||||||
let bundledata = &self.bundles[bundle.index()];
|
let bundledata = &self.bundles[bundle.index()];
|
||||||
log::trace!(" -> allocation {:?}", bundledata.allocation);
|
trace!(" -> allocation {:?}", bundledata.allocation);
|
||||||
if bundledata.allocation != Allocation::none() {
|
if bundledata.allocation != Allocation::none() {
|
||||||
bundledata.allocation
|
bundledata.allocation
|
||||||
} else {
|
} else {
|
||||||
log::trace!(" -> spillset {:?}", bundledata.spillset);
|
trace!(" -> spillset {:?}", bundledata.spillset);
|
||||||
log::trace!(
|
trace!(
|
||||||
" -> spill slot {:?}",
|
" -> spill slot {:?}",
|
||||||
self.spillsets[bundledata.spillset.index()].slot
|
self.spillsets[bundledata.spillset.index()].slot
|
||||||
);
|
);
|
||||||
@@ -107,9 +107,9 @@ impl<'a, F: Function> Env<'a, F> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn apply_allocations_and_insert_moves(&mut self) {
|
pub fn apply_allocations_and_insert_moves(&mut self) {
|
||||||
log::trace!("apply_allocations_and_insert_moves");
|
trace!("apply_allocations_and_insert_moves");
|
||||||
log::trace!("blockparam_ins: {:?}", self.blockparam_ins);
|
trace!("blockparam_ins: {:?}", self.blockparam_ins);
|
||||||
log::trace!("blockparam_outs: {:?}", self.blockparam_outs);
|
trace!("blockparam_outs: {:?}", self.blockparam_outs);
|
||||||
|
|
||||||
// Now that all splits are done, we can pay the cost once to
|
// Now that all splits are done, we can pay the cost once to
|
||||||
// sort VReg range lists and update with the final ranges.
|
// sort VReg range lists and update with the final ranges.
|
||||||
@@ -205,7 +205,7 @@ impl<'a, F: Function> Env<'a, F> {
|
|||||||
.map(|preg| Allocation::reg(preg))
|
.map(|preg| Allocation::reg(preg))
|
||||||
.unwrap_or_else(|| self.get_alloc_for_range(entry.index));
|
.unwrap_or_else(|| self.get_alloc_for_range(entry.index));
|
||||||
let range = entry.range;
|
let range = entry.range;
|
||||||
log::trace!(
|
trace!(
|
||||||
"apply_allocations: vreg {:?} LR {:?} with range {:?} has alloc {:?} (pinned {:?})",
|
"apply_allocations: vreg {:?} LR {:?} with range {:?} has alloc {:?} (pinned {:?})",
|
||||||
vreg,
|
vreg,
|
||||||
entry.index,
|
entry.index,
|
||||||
@@ -272,7 +272,7 @@ impl<'a, F: Function> Env<'a, F> {
|
|||||||
&& !self.is_start_of_block(range.from)
|
&& !self.is_start_of_block(range.from)
|
||||||
&& !first_is_def
|
&& !first_is_def
|
||||||
{
|
{
|
||||||
log::trace!(
|
trace!(
|
||||||
"prev LR {} abuts LR {} in same block; moving {} -> {} for v{}",
|
"prev LR {} abuts LR {} in same block; moving {} -> {} for v{}",
|
||||||
prev.index(),
|
prev.index(),
|
||||||
entry.index.index(),
|
entry.index.index(),
|
||||||
@@ -306,9 +306,9 @@ impl<'a, F: Function> Env<'a, F> {
|
|||||||
if range.to < self.cfginfo.block_exit[block.index()].next() {
|
if range.to < self.cfginfo.block_exit[block.index()].next() {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
log::trace!("examining block with end in range: block{}", block.index());
|
trace!("examining block with end in range: block{}", block.index());
|
||||||
for &succ in self.func.block_succs(block) {
|
for &succ in self.func.block_succs(block) {
|
||||||
log::trace!(
|
trace!(
|
||||||
" -> has succ block {} with entry {:?}",
|
" -> has succ block {} with entry {:?}",
|
||||||
succ.index(),
|
succ.index(),
|
||||||
self.cfginfo.block_entry[succ.index()]
|
self.cfginfo.block_entry[succ.index()]
|
||||||
@@ -316,9 +316,9 @@ impl<'a, F: Function> Env<'a, F> {
|
|||||||
if range.contains_point(self.cfginfo.block_entry[succ.index()]) {
|
if range.contains_point(self.cfginfo.block_entry[succ.index()]) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
log::trace!(" -> out of this range, requires half-move if live");
|
trace!(" -> out of this range, requires half-move if live");
|
||||||
if self.is_live_in(succ, vreg) {
|
if self.is_live_in(succ, vreg) {
|
||||||
log::trace!(" -> live at input to succ, adding halfmove");
|
trace!(" -> live at input to succ, adding halfmove");
|
||||||
half_moves.push(HalfMove {
|
half_moves.push(HalfMove {
|
||||||
key: half_move_key(block, succ, vreg, HalfMoveKind::Source),
|
key: half_move_key(block, succ, vreg, HalfMoveKind::Source),
|
||||||
alloc,
|
alloc,
|
||||||
@@ -329,7 +329,7 @@ impl<'a, F: Function> Env<'a, F> {
|
|||||||
// Scan forward in `blockparam_outs`, adding all
|
// Scan forward in `blockparam_outs`, adding all
|
||||||
// half-moves for outgoing values to blockparams
|
// half-moves for outgoing values to blockparams
|
||||||
// in succs.
|
// in succs.
|
||||||
log::trace!(
|
trace!(
|
||||||
"scanning blockparam_outs for v{} block{}: blockparam_out_idx = {}",
|
"scanning blockparam_outs for v{} block{}: blockparam_out_idx = {}",
|
||||||
vreg.index(),
|
vreg.index(),
|
||||||
block.index(),
|
block.index(),
|
||||||
@@ -346,7 +346,7 @@ impl<'a, F: Function> Env<'a, F> {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (from_vreg, from_block) == (vreg, block) {
|
if (from_vreg, from_block) == (vreg, block) {
|
||||||
log::trace!(
|
trace!(
|
||||||
" -> found: from v{} block{} to v{} block{}",
|
" -> found: from v{} block{} to v{} block{}",
|
||||||
from_vreg.index(),
|
from_vreg.index(),
|
||||||
from_block.index(),
|
from_block.index(),
|
||||||
@@ -398,7 +398,7 @@ impl<'a, F: Function> Env<'a, F> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Add half-moves for blockparam inputs.
|
// Add half-moves for blockparam inputs.
|
||||||
log::trace!(
|
trace!(
|
||||||
"scanning blockparam_ins at vreg {} block {}: blockparam_in_idx = {}",
|
"scanning blockparam_ins at vreg {} block {}: blockparam_in_idx = {}",
|
||||||
vreg.index(),
|
vreg.index(),
|
||||||
block.index(),
|
block.index(),
|
||||||
@@ -423,7 +423,7 @@ impl<'a, F: Function> Env<'a, F> {
|
|||||||
),
|
),
|
||||||
alloc,
|
alloc,
|
||||||
});
|
});
|
||||||
log::trace!(
|
trace!(
|
||||||
"match: blockparam_in: v{} in block{} from block{} into {}",
|
"match: blockparam_in: v{} in block{} from block{} into {}",
|
||||||
to_vreg.index(),
|
to_vreg.index(),
|
||||||
to_block.index(),
|
to_block.index(),
|
||||||
@@ -454,7 +454,7 @@ impl<'a, F: Function> Env<'a, F> {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
log::trace!(
|
trace!(
|
||||||
"scanning preds at vreg {} block {} for ends outside the range",
|
"scanning preds at vreg {} block {} for ends outside the range",
|
||||||
vreg.index(),
|
vreg.index(),
|
||||||
block.index()
|
block.index()
|
||||||
@@ -463,7 +463,7 @@ impl<'a, F: Function> Env<'a, F> {
|
|||||||
// Now find any preds whose ends are not in the
|
// Now find any preds whose ends are not in the
|
||||||
// same range, and insert appropriate moves.
|
// same range, and insert appropriate moves.
|
||||||
for &pred in self.func.block_preds(block) {
|
for &pred in self.func.block_preds(block) {
|
||||||
log::trace!(
|
trace!(
|
||||||
"pred block {} has exit {:?}",
|
"pred block {} has exit {:?}",
|
||||||
pred.index(),
|
pred.index(),
|
||||||
self.cfginfo.block_exit[pred.index()]
|
self.cfginfo.block_exit[pred.index()]
|
||||||
@@ -471,7 +471,7 @@ impl<'a, F: Function> Env<'a, F> {
|
|||||||
if range.contains_point(self.cfginfo.block_exit[pred.index()]) {
|
if range.contains_point(self.cfginfo.block_exit[pred.index()]) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
log::trace!(" -> requires half-move");
|
trace!(" -> requires half-move");
|
||||||
half_moves.push(HalfMove {
|
half_moves.push(HalfMove {
|
||||||
key: half_move_key(pred, block, vreg, HalfMoveKind::Dest),
|
key: half_move_key(pred, block, vreg, HalfMoveKind::Dest),
|
||||||
alloc,
|
alloc,
|
||||||
@@ -504,7 +504,7 @@ impl<'a, F: Function> Env<'a, F> {
|
|||||||
// Scan over def/uses and apply allocations.
|
// Scan over def/uses and apply allocations.
|
||||||
for use_idx in 0..self.ranges[entry.index.index()].uses.len() {
|
for use_idx in 0..self.ranges[entry.index.index()].uses.len() {
|
||||||
let usedata = self.ranges[entry.index.index()].uses[use_idx];
|
let usedata = self.ranges[entry.index.index()].uses[use_idx];
|
||||||
log::trace!("applying to use: {:?}", usedata);
|
trace!("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;
|
||||||
@@ -533,7 +533,7 @@ impl<'a, F: Function> Env<'a, F> {
|
|||||||
// covers only prev inst's After; so includes move
|
// covers only prev inst's After; so includes move
|
||||||
// srcs to (exclusive) inst.
|
// srcs to (exclusive) inst.
|
||||||
let move_src_end = (vreg, range.to.inst());
|
let move_src_end = (vreg, range.to.inst());
|
||||||
log::trace!(
|
trace!(
|
||||||
"vreg {:?} range {:?}: looking for program-move sources from {:?} to {:?}",
|
"vreg {:?} range {:?}: looking for program-move sources from {:?} to {:?}",
|
||||||
vreg,
|
vreg,
|
||||||
range,
|
range,
|
||||||
@@ -543,13 +543,13 @@ impl<'a, F: Function> Env<'a, F> {
|
|||||||
while prog_move_src_idx < self.prog_move_srcs.len()
|
while prog_move_src_idx < self.prog_move_srcs.len()
|
||||||
&& self.prog_move_srcs[prog_move_src_idx].0 < move_src_start
|
&& self.prog_move_srcs[prog_move_src_idx].0 < move_src_start
|
||||||
{
|
{
|
||||||
log::trace!(" -> skipping idx {}", prog_move_src_idx);
|
trace!(" -> skipping idx {}", prog_move_src_idx);
|
||||||
prog_move_src_idx += 1;
|
prog_move_src_idx += 1;
|
||||||
}
|
}
|
||||||
while prog_move_src_idx < self.prog_move_srcs.len()
|
while prog_move_src_idx < self.prog_move_srcs.len()
|
||||||
&& self.prog_move_srcs[prog_move_src_idx].0 < move_src_end
|
&& self.prog_move_srcs[prog_move_src_idx].0 < move_src_end
|
||||||
{
|
{
|
||||||
log::trace!(
|
trace!(
|
||||||
" -> setting idx {} ({:?}) to alloc {:?}",
|
" -> setting idx {} ({:?}) to alloc {:?}",
|
||||||
prog_move_src_idx,
|
prog_move_src_idx,
|
||||||
self.prog_move_srcs[prog_move_src_idx].0,
|
self.prog_move_srcs[prog_move_src_idx].0,
|
||||||
@@ -576,7 +576,7 @@ impl<'a, F: Function> Env<'a, F> {
|
|||||||
} else {
|
} else {
|
||||||
(vreg, range.to.inst().next())
|
(vreg, range.to.inst().next())
|
||||||
};
|
};
|
||||||
log::trace!(
|
trace!(
|
||||||
"vreg {:?} range {:?}: looking for program-move dests from {:?} to {:?}",
|
"vreg {:?} range {:?}: looking for program-move dests from {:?} to {:?}",
|
||||||
vreg,
|
vreg,
|
||||||
range,
|
range,
|
||||||
@@ -586,13 +586,13 @@ impl<'a, F: Function> Env<'a, F> {
|
|||||||
while prog_move_dst_idx < self.prog_move_dsts.len()
|
while prog_move_dst_idx < self.prog_move_dsts.len()
|
||||||
&& self.prog_move_dsts[prog_move_dst_idx].0 < move_dst_start
|
&& self.prog_move_dsts[prog_move_dst_idx].0 < move_dst_start
|
||||||
{
|
{
|
||||||
log::trace!(" -> skipping idx {}", prog_move_dst_idx);
|
trace!(" -> skipping idx {}", prog_move_dst_idx);
|
||||||
prog_move_dst_idx += 1;
|
prog_move_dst_idx += 1;
|
||||||
}
|
}
|
||||||
while prog_move_dst_idx < self.prog_move_dsts.len()
|
while prog_move_dst_idx < self.prog_move_dsts.len()
|
||||||
&& self.prog_move_dsts[prog_move_dst_idx].0 < move_dst_end
|
&& self.prog_move_dsts[prog_move_dst_idx].0 < move_dst_end
|
||||||
{
|
{
|
||||||
log::trace!(
|
trace!(
|
||||||
" -> setting idx {} ({:?}) to alloc {:?}",
|
" -> setting idx {} ({:?}) to alloc {:?}",
|
||||||
prog_move_dst_idx,
|
prog_move_dst_idx,
|
||||||
self.prog_move_dsts[prog_move_dst_idx].0,
|
self.prog_move_dsts[prog_move_dst_idx].0,
|
||||||
@@ -610,7 +610,7 @@ impl<'a, F: Function> Env<'a, F> {
|
|||||||
// from-vreg) tuple, find the from-alloc and all the
|
// from-vreg) tuple, find the from-alloc and all the
|
||||||
// to-allocs, and insert moves on the block edge.
|
// to-allocs, and insert moves on the block edge.
|
||||||
half_moves.sort_unstable_by_key(|h| h.key);
|
half_moves.sort_unstable_by_key(|h| h.key);
|
||||||
log::trace!("halfmoves: {:?}", half_moves);
|
trace!("halfmoves: {:?}", half_moves);
|
||||||
self.stats.halfmoves_count = half_moves.len();
|
self.stats.halfmoves_count = half_moves.len();
|
||||||
|
|
||||||
let mut i = 0;
|
let mut i = 0;
|
||||||
@@ -633,7 +633,7 @@ impl<'a, F: Function> Env<'a, F> {
|
|||||||
}
|
}
|
||||||
let last_dest = i;
|
let last_dest = i;
|
||||||
|
|
||||||
log::trace!(
|
trace!(
|
||||||
"halfmove match: src {:?} dests {:?}",
|
"halfmove match: src {:?} dests {:?}",
|
||||||
src,
|
src,
|
||||||
&half_moves[first_dest..last_dest]
|
&half_moves[first_dest..last_dest]
|
||||||
@@ -712,7 +712,7 @@ impl<'a, F: Function> Env<'a, F> {
|
|||||||
for fixup in std::mem::replace(&mut self.multi_fixed_reg_fixups, vec![]) {
|
for fixup in std::mem::replace(&mut self.multi_fixed_reg_fixups, vec![]) {
|
||||||
let from_alloc = self.get_alloc(fixup.pos.inst(), fixup.from_slot as usize);
|
let from_alloc = self.get_alloc(fixup.pos.inst(), fixup.from_slot as usize);
|
||||||
let to_alloc = Allocation::reg(PReg::from_index(fixup.to_preg.index()));
|
let to_alloc = Allocation::reg(PReg::from_index(fixup.to_preg.index()));
|
||||||
log::trace!(
|
trace!(
|
||||||
"multi-fixed-move constraint at {:?} from {} to {} for v{}",
|
"multi-fixed-move constraint at {:?} from {} to {} for v{}",
|
||||||
fixup.pos,
|
fixup.pos,
|
||||||
from_alloc,
|
from_alloc,
|
||||||
@@ -787,7 +787,7 @@ impl<'a, F: Function> Env<'a, F> {
|
|||||||
input_reused.push(input_idx);
|
input_reused.push(input_idx);
|
||||||
let input_alloc = self.get_alloc(inst, input_idx);
|
let input_alloc = self.get_alloc(inst, input_idx);
|
||||||
let output_alloc = self.get_alloc(inst, output_idx);
|
let output_alloc = self.get_alloc(inst, output_idx);
|
||||||
log::trace!(
|
trace!(
|
||||||
"reuse-input inst {:?}: output {} has alloc {:?}, input {} has alloc {:?}",
|
"reuse-input inst {:?}: output {} has alloc {:?}, input {} has alloc {:?}",
|
||||||
inst,
|
inst,
|
||||||
output_idx,
|
output_idx,
|
||||||
@@ -834,7 +834,7 @@ impl<'a, F: Function> Env<'a, F> {
|
|||||||
for (&((_, from_inst), from_alloc), &((to_vreg, to_inst), to_alloc)) in
|
for (&((_, from_inst), from_alloc), &((to_vreg, to_inst), to_alloc)) in
|
||||||
prog_move_srcs.iter().zip(prog_move_dsts.iter())
|
prog_move_srcs.iter().zip(prog_move_dsts.iter())
|
||||||
{
|
{
|
||||||
log::trace!(
|
trace!(
|
||||||
"program move at inst {:?}: alloc {:?} -> {:?} (v{})",
|
"program move at inst {:?}: alloc {:?} -> {:?} (v{})",
|
||||||
from_inst,
|
from_inst,
|
||||||
from_alloc,
|
from_alloc,
|
||||||
@@ -971,14 +971,14 @@ impl<'a, F: Function> Env<'a, F> {
|
|||||||
// that can be done one at a time.
|
// that can be done one at a time.
|
||||||
let scratch = self.env.scratch_by_class[regclass as u8 as usize];
|
let scratch = self.env.scratch_by_class[regclass as u8 as usize];
|
||||||
let mut parallel_moves = ParallelMoves::new(Allocation::reg(scratch));
|
let mut parallel_moves = ParallelMoves::new(Allocation::reg(scratch));
|
||||||
log::trace!(
|
trace!(
|
||||||
"parallel moves at pos {:?} prio {:?}",
|
"parallel moves at pos {:?} prio {:?}",
|
||||||
pos_prio.pos,
|
pos_prio.pos,
|
||||||
pos_prio.prio
|
pos_prio.prio
|
||||||
);
|
);
|
||||||
for m in moves {
|
for m in moves {
|
||||||
if (m.from_alloc != m.to_alloc) || m.to_vreg.is_some() {
|
if (m.from_alloc != m.to_alloc) || m.to_vreg.is_some() {
|
||||||
log::trace!(" {} -> {}", m.from_alloc, m.to_alloc,);
|
trace!(" {} -> {}", m.from_alloc, m.to_alloc,);
|
||||||
parallel_moves.add(m.from_alloc, m.to_alloc, m.to_vreg);
|
parallel_moves.add(m.from_alloc, m.to_alloc, m.to_vreg);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1009,7 +1009,7 @@ impl<'a, F: Function> Env<'a, F> {
|
|||||||
|
|
||||||
let mut scratch_used_yet = false;
|
let mut scratch_used_yet = false;
|
||||||
for (src, dst, to_vreg) in resolved {
|
for (src, dst, to_vreg) in resolved {
|
||||||
log::trace!(" resolved: {} -> {} ({:?})", src, dst, to_vreg);
|
trace!(" resolved: {} -> {} ({:?})", src, dst, to_vreg);
|
||||||
let action = redundant_moves.process_move(src, dst, to_vreg);
|
let action = redundant_moves.process_move(src, dst, to_vreg);
|
||||||
if !action.elide {
|
if !action.elide {
|
||||||
if dst == Allocation::reg(scratch) {
|
if dst == Allocation::reg(scratch) {
|
||||||
@@ -1060,11 +1060,11 @@ impl<'a, F: Function> Env<'a, F> {
|
|||||||
self.add_move_edit(pos_prio, src, dst, to_vreg);
|
self.add_move_edit(pos_prio, src, dst, to_vreg);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
log::trace!(" -> redundant move elided");
|
trace!(" -> redundant move elided");
|
||||||
}
|
}
|
||||||
#[cfg(feature = "checker")]
|
#[cfg(feature = "checker")]
|
||||||
if let Some((alloc, vreg)) = action.def_alloc {
|
if let Some((alloc, vreg)) = action.def_alloc {
|
||||||
log::trace!(
|
trace!(
|
||||||
" -> converted to DefAlloc: alloc {} vreg {}",
|
" -> converted to DefAlloc: alloc {} vreg {}",
|
||||||
alloc,
|
alloc,
|
||||||
vreg
|
vreg
|
||||||
@@ -1076,7 +1076,7 @@ impl<'a, F: Function> Env<'a, F> {
|
|||||||
|
|
||||||
#[cfg(feature = "checker")]
|
#[cfg(feature = "checker")]
|
||||||
for m in &self_moves {
|
for m in &self_moves {
|
||||||
log::trace!(
|
trace!(
|
||||||
"self move at pos {:?} prio {:?}: {} -> {} to_vreg {:?}",
|
"self move at pos {:?} prio {:?}: {} -> {} to_vreg {:?}",
|
||||||
pos_prio.pos,
|
pos_prio.pos,
|
||||||
pos_prio.prio,
|
pos_prio.prio,
|
||||||
@@ -1087,7 +1087,7 @@ impl<'a, F: Function> Env<'a, F> {
|
|||||||
let action = redundant_moves.process_move(m.from_alloc, m.to_alloc, m.to_vreg);
|
let action = redundant_moves.process_move(m.from_alloc, m.to_alloc, m.to_vreg);
|
||||||
debug_assert!(action.elide);
|
debug_assert!(action.elide);
|
||||||
if let Some((alloc, vreg)) = action.def_alloc {
|
if let Some((alloc, vreg)) = action.def_alloc {
|
||||||
log::trace!(" -> DefAlloc: alloc {} vreg {}", alloc, vreg);
|
trace!(" -> DefAlloc: alloc {} vreg {}", alloc, vreg);
|
||||||
self.edits.push((pos_prio, Edit::DefAlloc { alloc, vreg }));
|
self.edits.push((pos_prio, Edit::DefAlloc { alloc, vreg }));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -62,7 +62,7 @@ impl<'a, F: Function> Env<'a, F> {
|
|||||||
// `AllocRegResult::ConflictHighCost`.
|
// `AllocRegResult::ConflictHighCost`.
|
||||||
max_allowable_cost: Option<u32>,
|
max_allowable_cost: Option<u32>,
|
||||||
) -> AllocRegResult {
|
) -> AllocRegResult {
|
||||||
log::trace!("try_to_allocate_bundle_to_reg: {:?} -> {:?}", bundle, reg);
|
trace!("try_to_allocate_bundle_to_reg: {:?} -> {:?}", bundle, reg);
|
||||||
let mut conflicts = smallvec![];
|
let mut conflicts = smallvec![];
|
||||||
let mut conflict_set = FxHashSet::default();
|
let mut conflict_set = FxHashSet::default();
|
||||||
let mut max_conflict_weight = 0;
|
let mut max_conflict_weight = 0;
|
||||||
@@ -89,7 +89,7 @@ impl<'a, F: Function> Env<'a, F> {
|
|||||||
.btree
|
.btree
|
||||||
.range(from_key..)
|
.range(from_key..)
|
||||||
.peekable();
|
.peekable();
|
||||||
log::trace!(
|
trace!(
|
||||||
"alloc map for {:?} in range {:?}..: {:?}",
|
"alloc map for {:?} in range {:?}..: {:?}",
|
||||||
reg,
|
reg,
|
||||||
from_key,
|
from_key,
|
||||||
@@ -98,19 +98,19 @@ impl<'a, F: Function> Env<'a, F> {
|
|||||||
let mut first_conflict: Option<ProgPoint> = None;
|
let mut first_conflict: Option<ProgPoint> = None;
|
||||||
|
|
||||||
'ranges: for entry in bundle_ranges {
|
'ranges: for entry in bundle_ranges {
|
||||||
log::trace!(" -> range LR {:?}: {:?}", entry.index, entry.range);
|
trace!(" -> range LR {:?}: {:?}", entry.index, entry.range);
|
||||||
let key = LiveRangeKey::from_range(&entry.range);
|
let key = LiveRangeKey::from_range(&entry.range);
|
||||||
|
|
||||||
let mut skips = 0;
|
let mut skips = 0;
|
||||||
'alloc: loop {
|
'alloc: loop {
|
||||||
log::trace!(" -> PReg range {:?}", preg_range_iter.peek());
|
trace!(" -> PReg range {:?}", preg_range_iter.peek());
|
||||||
|
|
||||||
// Advance our BTree traversal until it is >= this bundle
|
// Advance our BTree traversal until it is >= this bundle
|
||||||
// range (i.e., skip PReg allocations in the BTree that
|
// range (i.e., skip PReg allocations in the BTree that
|
||||||
// are completely before this bundle range).
|
// are completely before this bundle range).
|
||||||
|
|
||||||
if preg_range_iter.peek().is_some() && *preg_range_iter.peek().unwrap().0 < key {
|
if preg_range_iter.peek().is_some() && *preg_range_iter.peek().unwrap().0 < key {
|
||||||
log::trace!(
|
trace!(
|
||||||
"Skipping PReg range {:?}",
|
"Skipping PReg range {:?}",
|
||||||
preg_range_iter.peek().unwrap().0
|
preg_range_iter.peek().unwrap().0
|
||||||
);
|
);
|
||||||
@@ -135,13 +135,13 @@ impl<'a, F: Function> Env<'a, F> {
|
|||||||
|
|
||||||
// If there are no more PReg allocations, we're done!
|
// If there are no more PReg allocations, we're done!
|
||||||
if preg_range_iter.peek().is_none() {
|
if preg_range_iter.peek().is_none() {
|
||||||
log::trace!(" -> no more PReg allocations; so no conflict possible!");
|
trace!(" -> no more PReg allocations; so no conflict possible!");
|
||||||
break 'ranges;
|
break 'ranges;
|
||||||
}
|
}
|
||||||
|
|
||||||
// If the current PReg range is beyond this range, there is no conflict; continue.
|
// If the current PReg range is beyond this range, there is no conflict; continue.
|
||||||
if *preg_range_iter.peek().unwrap().0 > key {
|
if *preg_range_iter.peek().unwrap().0 > key {
|
||||||
log::trace!(
|
trace!(
|
||||||
" -> next PReg allocation is at {:?}; moving to next VReg range",
|
" -> next PReg allocation is at {:?}; moving to next VReg range",
|
||||||
preg_range_iter.peek().unwrap().0
|
preg_range_iter.peek().unwrap().0
|
||||||
);
|
);
|
||||||
@@ -153,13 +153,13 @@ impl<'a, F: Function> Env<'a, F> {
|
|||||||
debug_assert_eq!(preg_key, key); // Assert that this range overlaps.
|
debug_assert_eq!(preg_key, key); // Assert that this range overlaps.
|
||||||
let preg_range = preg_range_iter.next().unwrap().1;
|
let preg_range = preg_range_iter.next().unwrap().1;
|
||||||
|
|
||||||
log::trace!(" -> btree contains range {:?} that overlaps", preg_range);
|
trace!(" -> btree contains range {:?} that overlaps", preg_range);
|
||||||
if preg_range.is_valid() {
|
if preg_range.is_valid() {
|
||||||
log::trace!(" -> from vreg {:?}", self.ranges[preg_range.index()].vreg);
|
trace!(" -> from vreg {:?}", self.ranges[preg_range.index()].vreg);
|
||||||
// range from an allocated bundle: find the bundle and add to
|
// range from an allocated bundle: find the bundle and add to
|
||||||
// conflicts list.
|
// conflicts list.
|
||||||
let conflict_bundle = self.ranges[preg_range.index()].bundle;
|
let conflict_bundle = self.ranges[preg_range.index()].bundle;
|
||||||
log::trace!(" -> conflict bundle {:?}", conflict_bundle);
|
trace!(" -> conflict bundle {:?}", conflict_bundle);
|
||||||
if !conflict_set.contains(&conflict_bundle) {
|
if !conflict_set.contains(&conflict_bundle) {
|
||||||
conflicts.push(conflict_bundle);
|
conflicts.push(conflict_bundle);
|
||||||
conflict_set.insert(conflict_bundle);
|
conflict_set.insert(conflict_bundle);
|
||||||
@@ -170,7 +170,7 @@ impl<'a, F: Function> Env<'a, F> {
|
|||||||
if max_allowable_cost.is_some()
|
if max_allowable_cost.is_some()
|
||||||
&& max_conflict_weight > max_allowable_cost.unwrap()
|
&& max_conflict_weight > max_allowable_cost.unwrap()
|
||||||
{
|
{
|
||||||
log::trace!(" -> reached high cost, retrying early");
|
trace!(" -> reached high cost, retrying early");
|
||||||
return AllocRegResult::ConflictHighCost;
|
return AllocRegResult::ConflictHighCost;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -182,7 +182,7 @@ impl<'a, F: Function> Env<'a, F> {
|
|||||||
)));
|
)));
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
log::trace!(" -> conflict with fixed reservation");
|
trace!(" -> conflict with fixed reservation");
|
||||||
// range from a direct use of the PReg (due to clobber).
|
// range from a direct use of the PReg (due to clobber).
|
||||||
return AllocRegResult::ConflictWithFixed(
|
return AllocRegResult::ConflictWithFixed(
|
||||||
max_conflict_weight,
|
max_conflict_weight,
|
||||||
@@ -198,7 +198,7 @@ impl<'a, F: Function> Env<'a, F> {
|
|||||||
|
|
||||||
// We can allocate! Add our ranges to the preg's BTree.
|
// We can allocate! Add our ranges to the preg's BTree.
|
||||||
let preg = PReg::from_index(reg.index());
|
let preg = PReg::from_index(reg.index());
|
||||||
log::trace!(" -> bundle {:?} assigned to preg {:?}", bundle, preg);
|
trace!(" -> bundle {:?} assigned to preg {:?}", bundle, preg);
|
||||||
self.bundles[bundle.index()].allocation = Allocation::reg(preg);
|
self.bundles[bundle.index()].allocation = Allocation::reg(preg);
|
||||||
for entry in &self.bundles[bundle.index()].ranges {
|
for entry in &self.bundles[bundle.index()].ranges {
|
||||||
self.pregs[reg.index()]
|
self.pregs[reg.index()]
|
||||||
@@ -211,7 +211,7 @@ impl<'a, F: Function> Env<'a, F> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn evict_bundle(&mut self, bundle: LiveBundleIndex) {
|
pub fn evict_bundle(&mut self, bundle: LiveBundleIndex) {
|
||||||
log::trace!(
|
trace!(
|
||||||
"evicting bundle {:?}: alloc {:?}",
|
"evicting bundle {:?}: alloc {:?}",
|
||||||
bundle,
|
bundle,
|
||||||
self.bundles[bundle.index()].allocation
|
self.bundles[bundle.index()].allocation
|
||||||
@@ -219,7 +219,7 @@ impl<'a, F: Function> Env<'a, F> {
|
|||||||
let preg = match self.bundles[bundle.index()].allocation.as_reg() {
|
let preg = match self.bundles[bundle.index()].allocation.as_reg() {
|
||||||
Some(preg) => preg,
|
Some(preg) => preg,
|
||||||
None => {
|
None => {
|
||||||
log::trace!(
|
trace!(
|
||||||
" -> has no allocation! {:?}",
|
" -> has no allocation! {:?}",
|
||||||
self.bundles[bundle.index()].allocation
|
self.bundles[bundle.index()].allocation
|
||||||
);
|
);
|
||||||
@@ -229,14 +229,14 @@ impl<'a, F: Function> Env<'a, F> {
|
|||||||
let preg_idx = PRegIndex::new(preg.index());
|
let preg_idx = PRegIndex::new(preg.index());
|
||||||
self.bundles[bundle.index()].allocation = Allocation::none();
|
self.bundles[bundle.index()].allocation = Allocation::none();
|
||||||
for entry in &self.bundles[bundle.index()].ranges {
|
for entry in &self.bundles[bundle.index()].ranges {
|
||||||
log::trace!(" -> removing LR {:?} from reg {:?}", entry.index, preg_idx);
|
trace!(" -> removing LR {:?} from reg {:?}", entry.index, preg_idx);
|
||||||
self.pregs[preg_idx.index()]
|
self.pregs[preg_idx.index()]
|
||||||
.allocations
|
.allocations
|
||||||
.btree
|
.btree
|
||||||
.remove(&LiveRangeKey::from_range(&entry.range));
|
.remove(&LiveRangeKey::from_range(&entry.range));
|
||||||
}
|
}
|
||||||
let prio = self.bundles[bundle.index()].prio;
|
let prio = self.bundles[bundle.index()].prio;
|
||||||
log::trace!(" -> prio {}; back into queue", prio);
|
trace!(" -> prio {}; back into queue", prio);
|
||||||
self.allocation_queue
|
self.allocation_queue
|
||||||
.insert(bundle, prio as usize, PReg::invalid());
|
.insert(bundle, prio as usize, PReg::invalid());
|
||||||
}
|
}
|
||||||
@@ -246,22 +246,22 @@ impl<'a, F: Function> Env<'a, F> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn maximum_spill_weight_in_bundle_set(&self, bundles: &LiveBundleVec) -> u32 {
|
pub fn maximum_spill_weight_in_bundle_set(&self, bundles: &LiveBundleVec) -> u32 {
|
||||||
log::trace!("maximum_spill_weight_in_bundle_set: {:?}", bundles);
|
trace!("maximum_spill_weight_in_bundle_set: {:?}", bundles);
|
||||||
let m = bundles
|
let m = bundles
|
||||||
.iter()
|
.iter()
|
||||||
.map(|&b| {
|
.map(|&b| {
|
||||||
let w = self.bundles[b.index()].cached_spill_weight();
|
let w = self.bundles[b.index()].cached_spill_weight();
|
||||||
log::trace!("bundle{}: {}", b.index(), w);
|
trace!("bundle{}: {}", b.index(), w);
|
||||||
w
|
w
|
||||||
})
|
})
|
||||||
.max()
|
.max()
|
||||||
.unwrap_or(0);
|
.unwrap_or(0);
|
||||||
log::trace!(" -> max: {}", m);
|
trace!(" -> max: {}", m);
|
||||||
m
|
m
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn recompute_bundle_properties(&mut self, bundle: LiveBundleIndex) {
|
pub fn recompute_bundle_properties(&mut self, bundle: LiveBundleIndex) {
|
||||||
log::trace!("recompute bundle properties: bundle {:?}", bundle);
|
trace!("recompute bundle properties: bundle {:?}", bundle);
|
||||||
|
|
||||||
let minimal;
|
let minimal;
|
||||||
let mut fixed = false;
|
let mut fixed = false;
|
||||||
@@ -273,18 +273,18 @@ impl<'a, F: Function> Env<'a, F> {
|
|||||||
self.bundles[bundle.index()].prio = self.compute_bundle_prio(bundle);
|
self.bundles[bundle.index()].prio = self.compute_bundle_prio(bundle);
|
||||||
|
|
||||||
if first_range_data.vreg.is_invalid() {
|
if first_range_data.vreg.is_invalid() {
|
||||||
log::trace!(" -> no vreg; minimal and fixed");
|
trace!(" -> no vreg; minimal and fixed");
|
||||||
minimal = true;
|
minimal = true;
|
||||||
fixed = true;
|
fixed = true;
|
||||||
} else {
|
} else {
|
||||||
for u in &first_range_data.uses {
|
for u in &first_range_data.uses {
|
||||||
log::trace!(" -> use: {:?}", u);
|
trace!(" -> use: {:?}", u);
|
||||||
if let OperandConstraint::FixedReg(_) = u.operand.constraint() {
|
if let OperandConstraint::FixedReg(_) = u.operand.constraint() {
|
||||||
log::trace!(" -> fixed use at {:?}: {:?}", u.pos, u.operand);
|
trace!(" -> fixed use at {:?}: {:?}", u.pos, u.operand);
|
||||||
fixed = true;
|
fixed = true;
|
||||||
}
|
}
|
||||||
if let OperandConstraint::Stack = u.operand.constraint() {
|
if let OperandConstraint::Stack = u.operand.constraint() {
|
||||||
log::trace!(" -> stack use at {:?}: {:?}", u.pos, u.operand);
|
trace!(" -> stack use at {:?}: {:?}", u.pos, u.operand);
|
||||||
stack = true;
|
stack = true;
|
||||||
}
|
}
|
||||||
if stack && fixed {
|
if stack && fixed {
|
||||||
@@ -295,7 +295,7 @@ impl<'a, F: Function> Env<'a, F> {
|
|||||||
// that it could cover just one ProgPoint,
|
// that it could cover just one ProgPoint,
|
||||||
// i.e. X.Before..X.After, or two ProgPoints,
|
// i.e. X.Before..X.After, or two ProgPoints,
|
||||||
// i.e. X.Before..X+1.Before.
|
// i.e. X.Before..X+1.Before.
|
||||||
log::trace!(" -> first range has range {:?}", first_range_data.range);
|
trace!(" -> first range has range {:?}", first_range_data.range);
|
||||||
let bundle_start = self.bundles[bundle.index()]
|
let bundle_start = self.bundles[bundle.index()]
|
||||||
.ranges
|
.ranges
|
||||||
.first()
|
.first()
|
||||||
@@ -304,22 +304,22 @@ impl<'a, F: Function> Env<'a, F> {
|
|||||||
.from;
|
.from;
|
||||||
let bundle_end = self.bundles[bundle.index()].ranges.last().unwrap().range.to;
|
let bundle_end = self.bundles[bundle.index()].ranges.last().unwrap().range.to;
|
||||||
minimal = bundle_start.inst() == bundle_end.prev().inst();
|
minimal = bundle_start.inst() == bundle_end.prev().inst();
|
||||||
log::trace!(" -> minimal: {}", minimal);
|
trace!(" -> minimal: {}", minimal);
|
||||||
}
|
}
|
||||||
|
|
||||||
let spill_weight = if minimal {
|
let spill_weight = if minimal {
|
||||||
if fixed {
|
if fixed {
|
||||||
log::trace!(" -> fixed and minimal");
|
trace!(" -> fixed and minimal");
|
||||||
MINIMAL_FIXED_BUNDLE_SPILL_WEIGHT
|
MINIMAL_FIXED_BUNDLE_SPILL_WEIGHT
|
||||||
} else {
|
} else {
|
||||||
log::trace!(" -> non-fixed and minimal");
|
trace!(" -> non-fixed and minimal");
|
||||||
MINIMAL_BUNDLE_SPILL_WEIGHT
|
MINIMAL_BUNDLE_SPILL_WEIGHT
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
let mut total = SpillWeight::zero();
|
let mut total = SpillWeight::zero();
|
||||||
for entry in &self.bundles[bundle.index()].ranges {
|
for entry in &self.bundles[bundle.index()].ranges {
|
||||||
let range_data = &self.ranges[entry.index.index()];
|
let range_data = &self.ranges[entry.index.index()];
|
||||||
log::trace!(
|
trace!(
|
||||||
" -> uses spill weight: +{:?}",
|
" -> uses spill weight: +{:?}",
|
||||||
range_data.uses_spill_weight()
|
range_data.uses_spill_weight()
|
||||||
);
|
);
|
||||||
@@ -328,7 +328,7 @@ impl<'a, F: Function> Env<'a, F> {
|
|||||||
|
|
||||||
if self.bundles[bundle.index()].prio > 0 {
|
if self.bundles[bundle.index()].prio > 0 {
|
||||||
let final_weight = (total.to_f32() as u32) / self.bundles[bundle.index()].prio;
|
let final_weight = (total.to_f32() as u32) / self.bundles[bundle.index()].prio;
|
||||||
log::trace!(
|
trace!(
|
||||||
" -> dividing by prio {}; final weight {}",
|
" -> dividing by prio {}; final weight {}",
|
||||||
self.bundles[bundle.index()].prio,
|
self.bundles[bundle.index()].prio,
|
||||||
final_weight
|
final_weight
|
||||||
@@ -356,7 +356,7 @@ impl<'a, F: Function> Env<'a, F> {
|
|||||||
let mut w = SpillWeight::zero();
|
let mut w = SpillWeight::zero();
|
||||||
for u in &rangedata.uses {
|
for u in &rangedata.uses {
|
||||||
w = w + SpillWeight::from_bits(u.weight);
|
w = w + SpillWeight::from_bits(u.weight);
|
||||||
log::trace!("range{}: use {:?}", range.index(), u);
|
trace!("range{}: use {:?}", range.index(), u);
|
||||||
}
|
}
|
||||||
rangedata.set_uses_spill_weight(w);
|
rangedata.set_uses_spill_weight(w);
|
||||||
if rangedata.uses.len() > 0 && rangedata.uses[0].operand.kind() == OperandKind::Def {
|
if rangedata.uses.len() > 0 && rangedata.uses[0].operand.kind() == OperandKind::Def {
|
||||||
@@ -397,7 +397,7 @@ impl<'a, F: Function> Env<'a, F> {
|
|||||||
reg_hint: PReg,
|
reg_hint: PReg,
|
||||||
) {
|
) {
|
||||||
self.stats.splits += 1;
|
self.stats.splits += 1;
|
||||||
log::trace!(
|
trace!(
|
||||||
"split bundle {:?} at {:?} and requeue with reg hint (for first part) {:?}",
|
"split bundle {:?} at {:?} and requeue with reg hint (for first part) {:?}",
|
||||||
bundle,
|
bundle,
|
||||||
split_at,
|
split_at,
|
||||||
@@ -435,7 +435,7 @@ impl<'a, F: Function> Env<'a, F> {
|
|||||||
break 'outer;
|
break 'outer;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
log::trace!(" -> first use loc is {:?}", first_use);
|
trace!(" -> first use loc is {:?}", first_use);
|
||||||
split_at = match first_use {
|
split_at = match first_use {
|
||||||
Some(pos) => {
|
Some(pos) => {
|
||||||
if pos.inst() == bundle_start.inst() {
|
if pos.inst() == bundle_start.inst() {
|
||||||
@@ -455,7 +455,7 @@ impl<'a, F: Function> Env<'a, F> {
|
|||||||
.next(),
|
.next(),
|
||||||
),
|
),
|
||||||
};
|
};
|
||||||
log::trace!(
|
trace!(
|
||||||
"split point is at bundle start; advancing to {:?}",
|
"split point is at bundle start; advancing to {:?}",
|
||||||
split_at
|
split_at
|
||||||
);
|
);
|
||||||
@@ -477,7 +477,7 @@ impl<'a, F: Function> Env<'a, F> {
|
|||||||
// which LR we need to split down the middle, then update the
|
// which LR we need to split down the middle, then update the
|
||||||
// current bundle, create a new one, and (re)-queue both.
|
// current bundle, create a new one, and (re)-queue both.
|
||||||
|
|
||||||
log::trace!(" -> LRs: {:?}", self.bundles[bundle.index()].ranges);
|
trace!(" -> LRs: {:?}", self.bundles[bundle.index()].ranges);
|
||||||
|
|
||||||
let mut last_lr_in_old_bundle_idx = 0; // last LR-list index in old bundle
|
let mut last_lr_in_old_bundle_idx = 0; // last LR-list index in old bundle
|
||||||
let mut first_lr_in_new_bundle_idx = 0; // first LR-list index in new bundle
|
let mut first_lr_in_new_bundle_idx = 0; // first LR-list index in new bundle
|
||||||
@@ -492,11 +492,11 @@ impl<'a, F: Function> Env<'a, F> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
log::trace!(
|
trace!(
|
||||||
" -> last LR in old bundle: LR {:?}",
|
" -> last LR in old bundle: LR {:?}",
|
||||||
self.bundles[bundle.index()].ranges[last_lr_in_old_bundle_idx]
|
self.bundles[bundle.index()].ranges[last_lr_in_old_bundle_idx]
|
||||||
);
|
);
|
||||||
log::trace!(
|
trace!(
|
||||||
" -> first LR in new bundle: LR {:?}",
|
" -> first LR in new bundle: LR {:?}",
|
||||||
self.bundles[bundle.index()].ranges[first_lr_in_new_bundle_idx]
|
self.bundles[bundle.index()].ranges[first_lr_in_new_bundle_idx]
|
||||||
);
|
);
|
||||||
@@ -523,7 +523,7 @@ impl<'a, F: Function> Env<'a, F> {
|
|||||||
to: new_lr_list[0].range.to,
|
to: new_lr_list[0].range.to,
|
||||||
});
|
});
|
||||||
self.ranges[new_lr.index()].vreg = self.ranges[orig_lr.index()].vreg;
|
self.ranges[new_lr.index()].vreg = self.ranges[orig_lr.index()].vreg;
|
||||||
log::trace!(" -> splitting LR {:?} into {:?}", orig_lr, new_lr);
|
trace!(" -> splitting LR {:?} into {:?}", orig_lr, new_lr);
|
||||||
let first_use = self.ranges[orig_lr.index()]
|
let first_use = self.ranges[orig_lr.index()]
|
||||||
.uses
|
.uses
|
||||||
.iter()
|
.iter()
|
||||||
@@ -560,7 +560,7 @@ impl<'a, F: Function> Env<'a, F> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let new_bundle = self.create_bundle();
|
let new_bundle = self.create_bundle();
|
||||||
log::trace!(" -> creating new bundle {:?}", new_bundle);
|
trace!(" -> creating new bundle {:?}", new_bundle);
|
||||||
self.bundles[new_bundle.index()].spillset = spillset;
|
self.bundles[new_bundle.index()].spillset = spillset;
|
||||||
for entry in &new_lr_list {
|
for entry in &new_lr_list {
|
||||||
self.ranges[entry.index.index()].bundle = new_bundle;
|
self.ranges[entry.index.index()].bundle = new_bundle;
|
||||||
@@ -582,7 +582,7 @@ impl<'a, F: Function> Env<'a, F> {
|
|||||||
let spill = self
|
let spill = self
|
||||||
.get_or_create_spill_bundle(bundle, /* create_if_absent = */ true)
|
.get_or_create_spill_bundle(bundle, /* create_if_absent = */ true)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
log::trace!(
|
trace!(
|
||||||
" -> bundle {:?} range {:?}: no uses; moving to spill bundle {:?}",
|
" -> bundle {:?} range {:?}: no uses; moving to spill bundle {:?}",
|
||||||
bundle,
|
bundle,
|
||||||
entry.index,
|
entry.index,
|
||||||
@@ -627,13 +627,13 @@ impl<'a, F: Function> Env<'a, F> {
|
|||||||
range,
|
range,
|
||||||
index: empty_lr,
|
index: empty_lr,
|
||||||
});
|
});
|
||||||
log::trace!(
|
trace!(
|
||||||
" -> bundle {:?} range {:?}: last use implies split point {:?}",
|
" -> bundle {:?} range {:?}: last use implies split point {:?}",
|
||||||
bundle,
|
bundle,
|
||||||
entry.index,
|
entry.index,
|
||||||
split
|
split
|
||||||
);
|
);
|
||||||
log::trace!(
|
trace!(
|
||||||
" -> moving trailing empty region to new spill bundle {:?} with new LR {:?}",
|
" -> moving trailing empty region to new spill bundle {:?} with new LR {:?}",
|
||||||
spill,
|
spill,
|
||||||
empty_lr
|
empty_lr
|
||||||
@@ -652,7 +652,7 @@ impl<'a, F: Function> Env<'a, F> {
|
|||||||
let spill = self
|
let spill = self
|
||||||
.get_or_create_spill_bundle(new_bundle, /* create_if_absent = */ true)
|
.get_or_create_spill_bundle(new_bundle, /* create_if_absent = */ true)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
log::trace!(
|
trace!(
|
||||||
" -> bundle {:?} range {:?}: no uses; moving to spill bundle {:?}",
|
" -> bundle {:?} range {:?}: no uses; moving to spill bundle {:?}",
|
||||||
new_bundle,
|
new_bundle,
|
||||||
entry.index,
|
entry.index,
|
||||||
@@ -697,13 +697,13 @@ impl<'a, F: Function> Env<'a, F> {
|
|||||||
range,
|
range,
|
||||||
index: empty_lr,
|
index: empty_lr,
|
||||||
});
|
});
|
||||||
log::trace!(
|
trace!(
|
||||||
" -> bundle {:?} range {:?}: first use implies split point {:?}",
|
" -> bundle {:?} range {:?}: first use implies split point {:?}",
|
||||||
bundle,
|
bundle,
|
||||||
entry.index,
|
entry.index,
|
||||||
first_use,
|
first_use,
|
||||||
);
|
);
|
||||||
log::trace!(
|
trace!(
|
||||||
" -> moving leading empty region to new spill bundle {:?} with new LR {:?}",
|
" -> moving leading empty region to new spill bundle {:?} with new LR {:?}",
|
||||||
spill,
|
spill,
|
||||||
empty_lr
|
empty_lr
|
||||||
@@ -741,7 +741,7 @@ impl<'a, F: Function> Env<'a, F> {
|
|||||||
if self.pregs[hint_reg.index()].is_stack {
|
if self.pregs[hint_reg.index()].is_stack {
|
||||||
hint_reg = PReg::invalid();
|
hint_reg = PReg::invalid();
|
||||||
}
|
}
|
||||||
log::trace!("process_bundle: bundle {:?} hint {:?}", bundle, hint_reg,);
|
trace!("process_bundle: bundle {:?} hint {:?}", bundle, hint_reg,);
|
||||||
|
|
||||||
let req = match self.compute_requirement(bundle) {
|
let req = match self.compute_requirement(bundle) {
|
||||||
Ok(req) => req,
|
Ok(req) => req,
|
||||||
@@ -786,7 +786,7 @@ impl<'a, F: Function> Env<'a, F> {
|
|||||||
let mut attempts = 0;
|
let mut attempts = 0;
|
||||||
loop {
|
loop {
|
||||||
attempts += 1;
|
attempts += 1;
|
||||||
log::trace!("attempt {}, req {:?}", attempts, req);
|
trace!("attempt {}, req {:?}", attempts, req);
|
||||||
debug_assert!(attempts < 100 * self.func.num_insts());
|
debug_assert!(attempts < 100 * self.func.num_insts());
|
||||||
|
|
||||||
let fixed_preg = match req {
|
let fixed_preg = match req {
|
||||||
@@ -836,7 +836,7 @@ impl<'a, F: Function> Env<'a, F> {
|
|||||||
) {
|
) {
|
||||||
self.stats.process_bundle_reg_probes_any += 1;
|
self.stats.process_bundle_reg_probes_any += 1;
|
||||||
let preg_idx = PRegIndex::new(preg.index());
|
let preg_idx = PRegIndex::new(preg.index());
|
||||||
log::trace!("trying preg {:?}", preg_idx);
|
trace!("trying preg {:?}", preg_idx);
|
||||||
|
|
||||||
let scan_limit_cost = match (
|
let scan_limit_cost = match (
|
||||||
lowest_cost_evict_conflict_cost,
|
lowest_cost_evict_conflict_cost,
|
||||||
@@ -848,13 +848,13 @@ impl<'a, F: Function> Env<'a, F> {
|
|||||||
match self.try_to_allocate_bundle_to_reg(bundle, preg_idx, scan_limit_cost) {
|
match self.try_to_allocate_bundle_to_reg(bundle, preg_idx, scan_limit_cost) {
|
||||||
AllocRegResult::Allocated(alloc) => {
|
AllocRegResult::Allocated(alloc) => {
|
||||||
self.stats.process_bundle_reg_success_any += 1;
|
self.stats.process_bundle_reg_success_any += 1;
|
||||||
log::trace!(" -> allocated to any {:?}", preg_idx);
|
trace!(" -> allocated to any {:?}", preg_idx);
|
||||||
self.spillsets[self.bundles[bundle.index()].spillset.index()].reg_hint =
|
self.spillsets[self.bundles[bundle.index()].spillset.index()].reg_hint =
|
||||||
alloc.as_reg().unwrap();
|
alloc.as_reg().unwrap();
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
AllocRegResult::Conflict(bundles, first_conflict_point) => {
|
AllocRegResult::Conflict(bundles, first_conflict_point) => {
|
||||||
log::trace!(
|
trace!(
|
||||||
" -> conflict with bundles {:?}, first conflict at {:?}",
|
" -> conflict with bundles {:?}, first conflict at {:?}",
|
||||||
bundles,
|
bundles,
|
||||||
first_conflict_point
|
first_conflict_point
|
||||||
@@ -887,7 +887,7 @@ impl<'a, F: Function> Env<'a, F> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
AllocRegResult::ConflictWithFixed(max_cost, point) => {
|
AllocRegResult::ConflictWithFixed(max_cost, point) => {
|
||||||
log::trace!(" -> conflict with fixed alloc; cost of other bundles up to point is {}, conflict at {:?}", max_cost, point);
|
trace!(" -> conflict with fixed alloc; cost of other bundles up to point is {}, conflict at {:?}", max_cost, point);
|
||||||
|
|
||||||
let loop_depth = self.cfginfo.approx_loop_depth
|
let loop_depth = self.cfginfo.approx_loop_depth
|
||||||
[self.cfginfo.insn_block[point.inst().index()].index()];
|
[self.cfginfo.insn_block[point.inst().index()].index()];
|
||||||
@@ -919,12 +919,12 @@ impl<'a, F: Function> Env<'a, F> {
|
|||||||
// any with current bundle assignments. Hence, we will need
|
// any with current bundle assignments. Hence, we will need
|
||||||
// to either split or attempt to evict some bundles.
|
// to either split or attempt to evict some bundles.
|
||||||
|
|
||||||
log::trace!(
|
trace!(
|
||||||
" -> lowest cost evict: set {:?}, cost {:?}",
|
" -> lowest cost evict: set {:?}, cost {:?}",
|
||||||
lowest_cost_evict_conflict_set,
|
lowest_cost_evict_conflict_set,
|
||||||
lowest_cost_evict_conflict_cost,
|
lowest_cost_evict_conflict_cost,
|
||||||
);
|
);
|
||||||
log::trace!(
|
trace!(
|
||||||
" -> lowest cost split: cost {:?}, point {:?}, reg {:?}",
|
" -> lowest cost split: cost {:?}, point {:?}, reg {:?}",
|
||||||
lowest_cost_split_conflict_cost,
|
lowest_cost_split_conflict_cost,
|
||||||
lowest_cost_split_conflict_point,
|
lowest_cost_split_conflict_point,
|
||||||
@@ -938,7 +938,7 @@ impl<'a, F: Function> Env<'a, F> {
|
|||||||
);
|
);
|
||||||
|
|
||||||
let our_spill_weight = self.bundle_spill_weight(bundle);
|
let our_spill_weight = self.bundle_spill_weight(bundle);
|
||||||
log::trace!(" -> our spill weight: {}", our_spill_weight);
|
trace!(" -> our spill weight: {}", our_spill_weight);
|
||||||
|
|
||||||
// We detect the "too-many-live-registers" case here and
|
// We detect the "too-many-live-registers" case here and
|
||||||
// return an error cleanly, rather than panicking, because
|
// return an error cleanly, rather than panicking, because
|
||||||
@@ -953,7 +953,7 @@ impl<'a, F: Function> Env<'a, F> {
|
|||||||
if let Requirement::Register = req {
|
if let Requirement::Register = req {
|
||||||
// Check if this is a too-many-live-registers situation.
|
// Check if this is a too-many-live-registers situation.
|
||||||
let range = self.bundles[bundle.index()].ranges[0].range;
|
let range = self.bundles[bundle.index()].ranges[0].range;
|
||||||
log::trace!("checking for too many live regs");
|
trace!("checking for too many live regs");
|
||||||
let mut min_bundles_assigned = 0;
|
let mut min_bundles_assigned = 0;
|
||||||
let mut fixed_assigned = 0;
|
let mut fixed_assigned = 0;
|
||||||
let mut total_regs = 0;
|
let mut total_regs = 0;
|
||||||
@@ -961,7 +961,7 @@ impl<'a, F: Function> Env<'a, F> {
|
|||||||
.iter()
|
.iter()
|
||||||
.chain(self.env.non_preferred_regs_by_class[class as u8 as usize].iter())
|
.chain(self.env.non_preferred_regs_by_class[class as u8 as usize].iter())
|
||||||
{
|
{
|
||||||
log::trace!(" -> PR {:?}", preg);
|
trace!(" -> PR {:?}", preg);
|
||||||
let start = LiveRangeKey::from_range(&CodeRange {
|
let start = LiveRangeKey::from_range(&CodeRange {
|
||||||
from: range.from.prev(),
|
from: range.from.prev(),
|
||||||
to: range.from.prev(),
|
to: range.from.prev(),
|
||||||
@@ -976,19 +976,19 @@ impl<'a, F: Function> Env<'a, F> {
|
|||||||
}
|
}
|
||||||
if lr.is_valid() {
|
if lr.is_valid() {
|
||||||
if self.minimal_bundle(self.ranges[lr.index()].bundle) {
|
if self.minimal_bundle(self.ranges[lr.index()].bundle) {
|
||||||
log::trace!(" -> min bundle {:?}", lr);
|
trace!(" -> min bundle {:?}", lr);
|
||||||
min_bundles_assigned += 1;
|
min_bundles_assigned += 1;
|
||||||
} else {
|
} else {
|
||||||
log::trace!(" -> non-min bundle {:?}", lr);
|
trace!(" -> non-min bundle {:?}", lr);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
log::trace!(" -> fixed bundle");
|
trace!(" -> fixed bundle");
|
||||||
fixed_assigned += 1;
|
fixed_assigned += 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
total_regs += 1;
|
total_regs += 1;
|
||||||
}
|
}
|
||||||
log::trace!(
|
trace!(
|
||||||
" -> total {}, fixed {}, min {}",
|
" -> total {}, fixed {}, min {}",
|
||||||
total_regs,
|
total_regs,
|
||||||
fixed_assigned,
|
fixed_assigned,
|
||||||
@@ -1020,7 +1020,7 @@ impl<'a, F: Function> Env<'a, F> {
|
|||||||
|| lowest_cost_evict_conflict_cost.is_none()
|
|| lowest_cost_evict_conflict_cost.is_none()
|
||||||
|| our_spill_weight <= lowest_cost_evict_conflict_cost.unwrap())
|
|| our_spill_weight <= lowest_cost_evict_conflict_cost.unwrap())
|
||||||
{
|
{
|
||||||
log::trace!(
|
trace!(
|
||||||
" -> deciding to split: our spill weight is {}",
|
" -> deciding to split: our spill weight is {}",
|
||||||
self.bundle_spill_weight(bundle)
|
self.bundle_spill_weight(bundle)
|
||||||
);
|
);
|
||||||
@@ -1053,7 +1053,7 @@ impl<'a, F: Function> Env<'a, F> {
|
|||||||
// Evict all bundles in `conflicting bundles` and try again.
|
// Evict all bundles in `conflicting bundles` and try again.
|
||||||
self.stats.evict_bundle_event += 1;
|
self.stats.evict_bundle_event += 1;
|
||||||
for &bundle in &lowest_cost_evict_conflict_set.unwrap() {
|
for &bundle in &lowest_cost_evict_conflict_set.unwrap() {
|
||||||
log::trace!(" -> evicting {:?}", bundle);
|
trace!(" -> evicting {:?}", bundle);
|
||||||
self.evict_bundle(bundle);
|
self.evict_bundle(bundle);
|
||||||
self.stats.evict_bundle_count += 1;
|
self.stats.evict_bundle_count += 1;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -41,13 +41,13 @@ impl RedundantMoveEliminator {
|
|||||||
.map(|&p| p)
|
.map(|&p| p)
|
||||||
.unwrap_or(RedundantMoveState::None);
|
.unwrap_or(RedundantMoveState::None);
|
||||||
|
|
||||||
log::trace!(
|
trace!(
|
||||||
" -> redundant move tracker: from {} to {} to_vreg {:?}",
|
" -> redundant move tracker: from {} to {} to_vreg {:?}",
|
||||||
from,
|
from,
|
||||||
to,
|
to,
|
||||||
to_vreg
|
to_vreg
|
||||||
);
|
);
|
||||||
log::trace!(
|
trace!(
|
||||||
" -> from_state {:?} to_state {:?}",
|
" -> from_state {:?} to_state {:?}",
|
||||||
from_state,
|
from_state,
|
||||||
to_state
|
to_state
|
||||||
@@ -69,29 +69,29 @@ impl RedundantMoveEliminator {
|
|||||||
RedundantMoveState::Orig(r) => Some(r),
|
RedundantMoveState::Orig(r) => Some(r),
|
||||||
_ => None,
|
_ => None,
|
||||||
};
|
};
|
||||||
log::trace!(" -> src_vreg {:?}", src_vreg);
|
trace!(" -> src_vreg {:?}", src_vreg);
|
||||||
let dst_vreg = to_vreg.or(src_vreg);
|
let dst_vreg = to_vreg.or(src_vreg);
|
||||||
log::trace!(" -> dst_vreg {:?}", dst_vreg);
|
trace!(" -> dst_vreg {:?}", dst_vreg);
|
||||||
let existing_dst_vreg = match to_state {
|
let existing_dst_vreg = match to_state {
|
||||||
RedundantMoveState::Copy(_, opt_r) => opt_r,
|
RedundantMoveState::Copy(_, opt_r) => opt_r,
|
||||||
RedundantMoveState::Orig(r) => Some(r),
|
RedundantMoveState::Orig(r) => Some(r),
|
||||||
_ => None,
|
_ => None,
|
||||||
};
|
};
|
||||||
log::trace!(" -> existing_dst_vreg {:?}", existing_dst_vreg);
|
trace!(" -> existing_dst_vreg {:?}", existing_dst_vreg);
|
||||||
|
|
||||||
let elide = match (from_state, to_state) {
|
let elide = match (from_state, to_state) {
|
||||||
(_, RedundantMoveState::Copy(orig_alloc, _)) if orig_alloc == from => true,
|
(_, RedundantMoveState::Copy(orig_alloc, _)) if orig_alloc == from => true,
|
||||||
(RedundantMoveState::Copy(new_alloc, _), _) if new_alloc == to => true,
|
(RedundantMoveState::Copy(new_alloc, _), _) if new_alloc == to => true,
|
||||||
_ => false,
|
_ => false,
|
||||||
};
|
};
|
||||||
log::trace!(" -> elide {}", elide);
|
trace!(" -> elide {}", elide);
|
||||||
|
|
||||||
let def_alloc = if dst_vreg != existing_dst_vreg && dst_vreg.is_some() {
|
let def_alloc = if dst_vreg != existing_dst_vreg && dst_vreg.is_some() {
|
||||||
Some((to, dst_vreg.unwrap()))
|
Some((to, dst_vreg.unwrap()))
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
};
|
};
|
||||||
log::trace!(" -> def_alloc {:?}", def_alloc);
|
trace!(" -> def_alloc {:?}", def_alloc);
|
||||||
|
|
||||||
// Invalidate all existing copies of `to` if `to` actually changed value.
|
// Invalidate all existing copies of `to` if `to` actually changed value.
|
||||||
if !elide {
|
if !elide {
|
||||||
@@ -102,7 +102,7 @@ impl RedundantMoveEliminator {
|
|||||||
if from.is_reg() || to.is_reg() {
|
if from.is_reg() || to.is_reg() {
|
||||||
self.allocs
|
self.allocs
|
||||||
.insert(to, RedundantMoveState::Copy(from, dst_vreg));
|
.insert(to, RedundantMoveState::Copy(from, dst_vreg));
|
||||||
log::trace!(
|
trace!(
|
||||||
" -> create mapping {} -> {:?}",
|
" -> create mapping {} -> {:?}",
|
||||||
to,
|
to,
|
||||||
RedundantMoveState::Copy(from, dst_vreg)
|
RedundantMoveState::Copy(from, dst_vreg)
|
||||||
@@ -121,16 +121,16 @@ impl RedundantMoveEliminator {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn clear(&mut self) {
|
pub fn clear(&mut self) {
|
||||||
log::trace!(" redundant move eliminator cleared");
|
trace!(" redundant move eliminator cleared");
|
||||||
self.allocs.clear();
|
self.allocs.clear();
|
||||||
self.reverse_allocs.clear();
|
self.reverse_allocs.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn clear_alloc(&mut self, alloc: Allocation) {
|
pub fn clear_alloc(&mut self, alloc: Allocation) {
|
||||||
log::trace!(" redundant move eliminator: clear {:?}", alloc);
|
trace!(" redundant move eliminator: clear {:?}", alloc);
|
||||||
if let Some(ref mut existing_copies) = self.reverse_allocs.get_mut(&alloc) {
|
if let Some(ref mut existing_copies) = self.reverse_allocs.get_mut(&alloc) {
|
||||||
for to_inval in existing_copies.iter() {
|
for to_inval in existing_copies.iter() {
|
||||||
log::trace!(" -> clear existing copy: {:?}", to_inval);
|
trace!(" -> clear existing copy: {:?}", to_inval);
|
||||||
if let Some(val) = self.allocs.get_mut(to_inval) {
|
if let Some(val) = self.allocs.get_mut(to_inval) {
|
||||||
match val {
|
match val {
|
||||||
RedundantMoveState::Copy(_, Some(vreg)) => {
|
RedundantMoveState::Copy(_, Some(vreg)) => {
|
||||||
|
|||||||
@@ -71,21 +71,21 @@ impl<'a, F: Function> Env<'a, F> {
|
|||||||
bundle: LiveBundleIndex,
|
bundle: LiveBundleIndex,
|
||||||
) -> Result<Requirement, RequirementConflictAt> {
|
) -> Result<Requirement, RequirementConflictAt> {
|
||||||
let mut req = Requirement::Any;
|
let mut req = Requirement::Any;
|
||||||
log::trace!("compute_requirement: {:?}", bundle);
|
trace!("compute_requirement: {:?}", bundle);
|
||||||
let ranges = &self.bundles[bundle.index()].ranges;
|
let ranges = &self.bundles[bundle.index()].ranges;
|
||||||
for entry in ranges {
|
for entry in ranges {
|
||||||
log::trace!(" -> LR {:?}", entry.index);
|
trace!(" -> LR {:?}", entry.index);
|
||||||
for u in &self.ranges[entry.index.index()].uses {
|
for u in &self.ranges[entry.index.index()].uses {
|
||||||
log::trace!(" -> use {:?}", u);
|
trace!(" -> use {:?}", u);
|
||||||
let r = self.requirement_from_operand(u.operand);
|
let r = self.requirement_from_operand(u.operand);
|
||||||
req = req.merge(r).map_err(|_| {
|
req = req.merge(r).map_err(|_| {
|
||||||
log::trace!(" -> conflict");
|
trace!(" -> conflict");
|
||||||
RequirementConflictAt(u.pos)
|
RequirementConflictAt(u.pos)
|
||||||
})?;
|
})?;
|
||||||
log::trace!(" -> req {:?}", req);
|
trace!(" -> req {:?}", req);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
log::trace!(" -> final: {:?}", req);
|
trace!(" -> final: {:?}", req);
|
||||||
Ok(req)
|
Ok(req)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ use crate::{Allocation, Function, SpillSlot};
|
|||||||
|
|
||||||
impl<'a, F: Function> Env<'a, F> {
|
impl<'a, F: Function> Env<'a, F> {
|
||||||
pub fn try_allocating_regs_for_spilled_bundles(&mut self) {
|
pub fn try_allocating_regs_for_spilled_bundles(&mut self) {
|
||||||
log::trace!("allocating regs for spilled bundles");
|
trace!("allocating regs for spilled bundles");
|
||||||
for i in 0..self.spilled_bundles.len() {
|
for i in 0..self.spilled_bundles.len() {
|
||||||
let bundle = self.spilled_bundles[i]; // don't borrow self
|
let bundle = self.spilled_bundles[i]; // don't borrow self
|
||||||
|
|
||||||
@@ -38,7 +38,7 @@ impl<'a, F: Function> Env<'a, F> {
|
|||||||
for preg in
|
for preg in
|
||||||
RegTraversalIter::new(self.env, class, hint, PReg::invalid(), bundle.index(), None)
|
RegTraversalIter::new(self.env, class, hint, PReg::invalid(), bundle.index(), None)
|
||||||
{
|
{
|
||||||
log::trace!("trying bundle {:?} to preg {:?}", bundle, preg);
|
trace!("trying bundle {:?} to preg {:?}", bundle, preg);
|
||||||
let preg_idx = PRegIndex::new(preg.index());
|
let preg_idx = PRegIndex::new(preg.index());
|
||||||
if let AllocRegResult::Allocated(_) =
|
if let AllocRegResult::Allocated(_) =
|
||||||
self.try_to_allocate_bundle_to_reg(bundle, preg_idx, None)
|
self.try_to_allocate_bundle_to_reg(bundle, preg_idx, None)
|
||||||
@@ -49,7 +49,7 @@ impl<'a, F: Function> Env<'a, F> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if !success {
|
if !success {
|
||||||
log::trace!(
|
trace!(
|
||||||
"spilling bundle {:?}: marking spillset {:?} as required",
|
"spilling bundle {:?}: marking spillset {:?} as required",
|
||||||
bundle,
|
bundle,
|
||||||
self.bundles[bundle.index()].spillset
|
self.bundles[bundle.index()].spillset
|
||||||
@@ -87,14 +87,14 @@ impl<'a, F: Function> Env<'a, F> {
|
|||||||
for i in 0..self.spillsets[spillset.index()].vregs.len() {
|
for i in 0..self.spillsets[spillset.index()].vregs.len() {
|
||||||
// don't borrow self
|
// don't borrow self
|
||||||
let vreg = self.spillsets[spillset.index()].vregs[i];
|
let vreg = self.spillsets[spillset.index()].vregs[i];
|
||||||
log::trace!(
|
trace!(
|
||||||
"spillslot {:?} alloc'ed to spillset {:?}: vreg {:?}",
|
"spillslot {:?} alloc'ed to spillset {:?}: vreg {:?}",
|
||||||
spillslot,
|
spillslot,
|
||||||
spillset,
|
spillset,
|
||||||
vreg,
|
vreg,
|
||||||
);
|
);
|
||||||
for entry in &self.vregs[vreg.index()].ranges {
|
for entry in &self.vregs[vreg.index()].ranges {
|
||||||
log::trace!(
|
trace!(
|
||||||
"spillslot {:?} getting range {:?} from LR {:?} from vreg {:?}",
|
"spillslot {:?} getting range {:?} from LR {:?} from vreg {:?}",
|
||||||
spillslot,
|
spillslot,
|
||||||
entry.range,
|
entry.range,
|
||||||
@@ -111,7 +111,7 @@ impl<'a, F: Function> Env<'a, F> {
|
|||||||
|
|
||||||
pub fn allocate_spillslots(&mut self) {
|
pub fn allocate_spillslots(&mut self) {
|
||||||
for spillset in 0..self.spillsets.len() {
|
for spillset in 0..self.spillsets.len() {
|
||||||
log::trace!("allocate spillslot: {}", spillset);
|
trace!("allocate spillslot: {}", spillset);
|
||||||
let spillset = SpillSetIndex::new(spillset);
|
let spillset = SpillSetIndex::new(spillset);
|
||||||
if !self.spillsets[spillset.index()].required {
|
if !self.spillsets[spillset.index()].required {
|
||||||
continue;
|
continue;
|
||||||
@@ -196,7 +196,7 @@ impl<'a, F: Function> Env<'a, F> {
|
|||||||
self.spillslots[i].alloc = self.allocate_spillslot(self.spillslots[i].class);
|
self.spillslots[i].alloc = self.allocate_spillslot(self.spillslots[i].class);
|
||||||
}
|
}
|
||||||
|
|
||||||
log::trace!("spillslot allocator done");
|
trace!("spillslot allocator done");
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn allocate_spillslot(&mut self, class: RegClass) -> Allocation {
|
pub fn allocate_spillslot(&mut self, class: RegClass) -> Allocation {
|
||||||
|
|||||||
@@ -30,10 +30,10 @@ impl<'a, F: Function> Env<'a, F> {
|
|||||||
// safepoints; and for each safepoint in the current range,
|
// safepoints; and for each safepoint in the current range,
|
||||||
// emit the allocation into the `safepoint_slots` list.
|
// emit the allocation into the `safepoint_slots` list.
|
||||||
|
|
||||||
log::trace!("safepoints_per_vreg = {:?}", self.safepoints_per_vreg);
|
trace!("safepoints_per_vreg = {:?}", self.safepoints_per_vreg);
|
||||||
|
|
||||||
for vreg in self.func.reftype_vregs() {
|
for vreg in self.func.reftype_vregs() {
|
||||||
log::trace!("generating safepoint info for vreg {}", vreg);
|
trace!("generating safepoint info for vreg {}", vreg);
|
||||||
let vreg = VRegIndex::new(vreg.vreg());
|
let vreg = VRegIndex::new(vreg.vreg());
|
||||||
let mut safepoints: Vec<ProgPoint> = self
|
let mut safepoints: Vec<ProgPoint> = self
|
||||||
.safepoints_per_vreg
|
.safepoints_per_vreg
|
||||||
@@ -43,19 +43,19 @@ impl<'a, F: Function> Env<'a, F> {
|
|||||||
.map(|&inst| ProgPoint::before(inst))
|
.map(|&inst| ProgPoint::before(inst))
|
||||||
.collect();
|
.collect();
|
||||||
safepoints.sort_unstable();
|
safepoints.sort_unstable();
|
||||||
log::trace!(" -> live over safepoints: {:?}", safepoints);
|
trace!(" -> live over safepoints: {:?}", safepoints);
|
||||||
|
|
||||||
let mut safepoint_idx = 0;
|
let mut safepoint_idx = 0;
|
||||||
for entry in &self.vregs[vreg.index()].ranges {
|
for entry in &self.vregs[vreg.index()].ranges {
|
||||||
let range = entry.range;
|
let range = entry.range;
|
||||||
let alloc = self.get_alloc_for_range(entry.index);
|
let alloc = self.get_alloc_for_range(entry.index);
|
||||||
log::trace!(" -> range {:?}: alloc {}", range, alloc);
|
trace!(" -> range {:?}: alloc {}", range, alloc);
|
||||||
while safepoint_idx < safepoints.len() && safepoints[safepoint_idx] < range.to {
|
while safepoint_idx < safepoints.len() && safepoints[safepoint_idx] < range.to {
|
||||||
if safepoints[safepoint_idx] < range.from {
|
if safepoints[safepoint_idx] < range.from {
|
||||||
safepoint_idx += 1;
|
safepoint_idx += 1;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
log::trace!(" -> covers safepoint {:?}", safepoints[safepoint_idx]);
|
trace!(" -> covers safepoint {:?}", safepoints[safepoint_idx]);
|
||||||
|
|
||||||
self.safepoint_slots
|
self.safepoint_slots
|
||||||
.push((safepoints[safepoint_idx], alloc));
|
.push((safepoints[safepoint_idx], alloc));
|
||||||
@@ -66,6 +66,6 @@ impl<'a, F: Function> Env<'a, F> {
|
|||||||
|
|
||||||
self.safepoint_slots
|
self.safepoint_slots
|
||||||
.sort_unstable_by_key(|(progpoint, slot)| u64_key(progpoint.to_index(), slot.bits()));
|
.sort_unstable_by_key(|(progpoint, slot)| u64_key(progpoint.to_index(), slot.bits()));
|
||||||
log::trace!("final safepoint slots info: {:?}", self.safepoint_slots);
|
trace!("final safepoint slots info: {:?}", self.safepoint_slots);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
10
src/lib.rs
10
src/lib.rs
@@ -12,6 +12,16 @@
|
|||||||
|
|
||||||
#![allow(dead_code)]
|
#![allow(dead_code)]
|
||||||
|
|
||||||
|
// Even when trace logging is disabled, the trace macro has a significant
|
||||||
|
// performance cost so we disable it in release builds.
|
||||||
|
macro_rules! trace {
|
||||||
|
($($tt:tt)*) => {
|
||||||
|
if cfg!(debug_assertions) {
|
||||||
|
::log::trace!($($tt)*);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
pub(crate) mod cfg;
|
pub(crate) mod cfg;
|
||||||
pub(crate) mod domtree;
|
pub(crate) mod domtree;
|
||||||
pub mod indexset;
|
pub mod indexset;
|
||||||
|
|||||||
Reference in New Issue
Block a user