Fix liveranges for branch parameters
This commit is contained in:
@@ -315,6 +315,7 @@ impl<'a, F: Function> Env<'a, F> {
|
||||
while !workqueue.is_empty() {
|
||||
let block = workqueue.pop_front().unwrap();
|
||||
workqueue_set.remove(&block);
|
||||
let insns = self.func.block_insns(block);
|
||||
|
||||
log::trace!("computing liveins for block{}", block.index());
|
||||
|
||||
@@ -323,7 +324,16 @@ impl<'a, F: Function> Env<'a, F> {
|
||||
let mut live = self.liveouts[block.index()].clone();
|
||||
log::trace!(" -> initial liveout set: {:?}", live);
|
||||
|
||||
for inst in self.func.block_insns(block).rev().iter() {
|
||||
// Include outgoing blockparams in the initial live set.
|
||||
if self.func.is_branch(insns.last()) {
|
||||
for i in 0..self.func.block_succs(block).len() {
|
||||
for param in self.func.branch_blockparams(block, insns.last(), i) {
|
||||
live.set(param.vreg(), true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for inst in insns.rev().iter() {
|
||||
if let Some((src, dst)) = self.func.is_move(inst) {
|
||||
live.set(dst.vreg().vreg(), false);
|
||||
live.set(src.vreg().vreg(), true);
|
||||
@@ -399,12 +409,33 @@ impl<'a, F: Function> Env<'a, F> {
|
||||
|
||||
for i in (0..self.func.num_blocks()).rev() {
|
||||
let block = Block::new(i);
|
||||
let insns = self.func.block_insns(block);
|
||||
|
||||
self.stats.livein_blocks += 1;
|
||||
|
||||
// Init our local live-in set.
|
||||
let mut live = self.liveouts[block.index()].clone();
|
||||
|
||||
// If the last instruction is a branch (rather than
|
||||
// return), create blockparam_out entries.
|
||||
if self.func.is_branch(insns.last()) {
|
||||
for (i, &succ) in self.func.block_succs(block).iter().enumerate() {
|
||||
let blockparams_in = self.func.block_params(succ);
|
||||
let blockparams_out = self.func.branch_blockparams(block, insns.last(), i);
|
||||
for (&blockparam_in, &blockparam_out) in
|
||||
blockparams_in.iter().zip(blockparams_out)
|
||||
{
|
||||
let blockparam_out = VRegIndex::new(blockparam_out.vreg());
|
||||
let blockparam_in = VRegIndex::new(blockparam_in.vreg());
|
||||
self.blockparam_outs
|
||||
.push((blockparam_out, block, succ, blockparam_in));
|
||||
|
||||
// Include outgoing blockparams in the initial live set.
|
||||
live.set(blockparam_out.index(), true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Initially, registers are assumed live for the whole block.
|
||||
for vreg in live.iter() {
|
||||
let range = CodeRange {
|
||||
@@ -426,25 +457,6 @@ impl<'a, F: Function> Env<'a, F> {
|
||||
self.vregs[param.vreg()].blockparam = block;
|
||||
}
|
||||
|
||||
let insns = self.func.block_insns(block);
|
||||
|
||||
// If the last instruction is a branch (rather than
|
||||
// return), create blockparam_out entries.
|
||||
if self.func.is_branch(insns.last()) {
|
||||
for (i, &succ) in self.func.block_succs(block).iter().enumerate() {
|
||||
let blockparams_in = self.func.block_params(succ);
|
||||
let blockparams_out = self.func.branch_blockparams(block, insns.last(), i);
|
||||
for (&blockparam_in, &blockparam_out) in
|
||||
blockparams_in.iter().zip(blockparams_out)
|
||||
{
|
||||
let blockparam_out = VRegIndex::new(blockparam_out.vreg());
|
||||
let blockparam_in = VRegIndex::new(blockparam_in.vreg());
|
||||
self.blockparam_outs
|
||||
.push((blockparam_out, block, succ, blockparam_in));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// For each instruction, in reverse order, process
|
||||
// operands and clobbers.
|
||||
for inst in insns.rev().iter() {
|
||||
@@ -893,13 +905,6 @@ impl<'a, F: Function> Env<'a, F> {
|
||||
(OperandKind::Def, OperandPos::Early) => ProgPoint::before(inst),
|
||||
(OperandKind::Def, OperandPos::Late) => ProgPoint::after(inst),
|
||||
(OperandKind::Use, OperandPos::Late) => ProgPoint::after(inst),
|
||||
// If this is a branch, extend `pos` to
|
||||
// the end of the block. (Branch uses are
|
||||
// blockparams and need to be live at the
|
||||
// end of the block.)
|
||||
(OperandKind::Use, _) if self.func.is_branch(inst) => {
|
||||
self.cfginfo.block_exit[block.index()]
|
||||
}
|
||||
// If there are any reused inputs in this
|
||||
// instruction, and this is *not* the
|
||||
// reused input, force `pos` to
|
||||
|
||||
Reference in New Issue
Block a user