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() {
|
while !workqueue.is_empty() {
|
||||||
let block = workqueue.pop_front().unwrap();
|
let block = workqueue.pop_front().unwrap();
|
||||||
workqueue_set.remove(&block);
|
workqueue_set.remove(&block);
|
||||||
|
let insns = self.func.block_insns(block);
|
||||||
|
|
||||||
log::trace!("computing liveins for block{}", block.index());
|
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();
|
let mut live = self.liveouts[block.index()].clone();
|
||||||
log::trace!(" -> initial liveout set: {:?}", live);
|
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) {
|
if let Some((src, dst)) = self.func.is_move(inst) {
|
||||||
live.set(dst.vreg().vreg(), false);
|
live.set(dst.vreg().vreg(), false);
|
||||||
live.set(src.vreg().vreg(), true);
|
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() {
|
for i in (0..self.func.num_blocks()).rev() {
|
||||||
let block = Block::new(i);
|
let block = Block::new(i);
|
||||||
|
let insns = self.func.block_insns(block);
|
||||||
|
|
||||||
self.stats.livein_blocks += 1;
|
self.stats.livein_blocks += 1;
|
||||||
|
|
||||||
// Init our local live-in set.
|
// Init our local live-in set.
|
||||||
let mut live = self.liveouts[block.index()].clone();
|
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.
|
// Initially, registers are assumed live for the whole block.
|
||||||
for vreg in live.iter() {
|
for vreg in live.iter() {
|
||||||
let range = CodeRange {
|
let range = CodeRange {
|
||||||
@@ -426,25 +457,6 @@ impl<'a, F: Function> Env<'a, F> {
|
|||||||
self.vregs[param.vreg()].blockparam = block;
|
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
|
// For each instruction, in reverse order, process
|
||||||
// operands and clobbers.
|
// operands and clobbers.
|
||||||
for inst in insns.rev().iter() {
|
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::Early) => ProgPoint::before(inst),
|
||||||
(OperandKind::Def, OperandPos::Late) => ProgPoint::after(inst),
|
(OperandKind::Def, OperandPos::Late) => ProgPoint::after(inst),
|
||||||
(OperandKind::Use, 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
|
// If there are any reused inputs in this
|
||||||
// instruction, and this is *not* the
|
// instruction, and this is *not* the
|
||||||
// reused input, force `pos` to
|
// reused input, force `pos` to
|
||||||
|
|||||||
Reference in New Issue
Block a user