Fuzzbugfix: actually do need eager liveness computation; must uphold invariant that all earlier-in-postorder blocks have full livein sets.
This commit is contained in:
@@ -177,7 +177,7 @@ impl<'a> std::iter::Iterator for AdaptiveMapIter<'a> {
|
|||||||
|
|
||||||
/// A conceptually infinite-length bitvector that allows bitwise operations and
|
/// A conceptually infinite-length bitvector that allows bitwise operations and
|
||||||
/// iteration over set bits efficiently.
|
/// iteration over set bits efficiently.
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone)]
|
||||||
pub struct BitVec {
|
pub struct BitVec {
|
||||||
elems: AdaptiveMap,
|
elems: AdaptiveMap,
|
||||||
}
|
}
|
||||||
@@ -275,6 +275,13 @@ impl Iterator for SetBitsIter {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl std::fmt::Debug for BitVec {
|
||||||
|
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
|
||||||
|
let vals = self.iter().collect::<Vec<_>>();
|
||||||
|
write!(f, "{:?}", vals)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod test {
|
mod test {
|
||||||
use super::BitVec;
|
use super::BitVec;
|
||||||
|
|||||||
@@ -130,7 +130,7 @@ impl Function for Func {
|
|||||||
&self.reftype_vregs[..]
|
&self.reftype_vregs[..]
|
||||||
}
|
}
|
||||||
|
|
||||||
fn is_move(&self, insn: Inst) -> Option<(VReg, VReg)> {
|
fn is_move(&self, _: Inst) -> Option<(VReg, VReg)> {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -267,7 +267,6 @@ struct Env<'a, F: Function> {
|
|||||||
env: &'a MachineEnv,
|
env: &'a MachineEnv,
|
||||||
cfginfo: CFGInfo,
|
cfginfo: CFGInfo,
|
||||||
liveins: Vec<BitVec>,
|
liveins: Vec<BitVec>,
|
||||||
livein_parents: Vec<Vec<Block>>,
|
|
||||||
/// Blockparam outputs: from-vreg, (end of) from-block, (start of)
|
/// Blockparam outputs: from-vreg, (end of) from-block, (start of)
|
||||||
/// to-block, to-vreg. The field order is significant: these are sorted so
|
/// to-block, to-vreg. The field order is significant: these are sorted so
|
||||||
/// that a scan over vregs, then blocks in each range, can scan in
|
/// that a scan over vregs, then blocks in each range, can scan in
|
||||||
@@ -664,7 +663,6 @@ impl<'a, F: Function> Env<'a, F> {
|
|||||||
cfginfo,
|
cfginfo,
|
||||||
|
|
||||||
liveins: vec![],
|
liveins: vec![],
|
||||||
livein_parents: vec![],
|
|
||||||
blockparam_outs: vec![],
|
blockparam_outs: vec![],
|
||||||
blockparam_ins: vec![],
|
blockparam_ins: vec![],
|
||||||
blockparam_allocs: vec![],
|
blockparam_allocs: vec![],
|
||||||
@@ -1016,23 +1014,13 @@ impl<'a, F: Function> Env<'a, F> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn is_live_in(&mut self, block: Block, vreg: VRegIndex) -> bool {
|
fn is_live_in(&mut self, block: Block, vreg: VRegIndex) -> bool {
|
||||||
if self.liveins[block.index()].get(vreg.index()) {
|
self.liveins[block.index()].get(vreg.index())
|
||||||
return true;
|
|
||||||
}
|
|
||||||
for &parent in &self.livein_parents[block.index()] {
|
|
||||||
if self.liveins[parent.index()].get(vreg.index()) {
|
|
||||||
self.liveins[block.index()].set(vreg.index(), true);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
false
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn compute_liveness(&mut self) {
|
fn compute_liveness(&mut self) {
|
||||||
// Create initial LiveIn bitsets.
|
// Create initial LiveIn bitsets.
|
||||||
for _ in 0..self.func.blocks() {
|
for _ in 0..self.func.blocks() {
|
||||||
self.liveins.push(BitVec::new());
|
self.liveins.push(BitVec::new());
|
||||||
self.livein_parents.push(vec![]);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut num_ranges = 0;
|
let mut num_ranges = 0;
|
||||||
@@ -1428,7 +1416,7 @@ impl<'a, F: Function> Env<'a, F> {
|
|||||||
);
|
);
|
||||||
log::debug!(" -> loop range {:?}", loop_range);
|
log::debug!(" -> loop range {:?}", loop_range);
|
||||||
for &loopblock in loop_blocks {
|
for &loopblock in loop_blocks {
|
||||||
self.livein_parents[loopblock.index()].push(block);
|
self.liveins[loopblock.index()].or(&live);
|
||||||
}
|
}
|
||||||
for vreg in live.iter() {
|
for vreg in live.iter() {
|
||||||
log::debug!(
|
log::debug!(
|
||||||
|
|||||||
16
src/lib.rs
16
src/lib.rs
@@ -779,11 +779,25 @@ pub enum InstPosition {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// A program point: a single point before or after a given instruction.
|
/// A program point: a single point before or after a given instruction.
|
||||||
#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||||||
pub struct ProgPoint {
|
pub struct ProgPoint {
|
||||||
bits: u32,
|
bits: u32,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl std::fmt::Debug for ProgPoint {
|
||||||
|
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
|
||||||
|
write!(
|
||||||
|
f,
|
||||||
|
"progpoint{}{}",
|
||||||
|
self.inst().index(),
|
||||||
|
match self.pos() {
|
||||||
|
InstPosition::Before => "-pre",
|
||||||
|
InstPosition::After => "-post",
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl ProgPoint {
|
impl ProgPoint {
|
||||||
pub fn new(inst: Inst, pos: InstPosition) -> Self {
|
pub fn new(inst: Inst, pos: InstPosition) -> Self {
|
||||||
let bits = ((inst.0 as u32) << 1) | (pos as u8 as u32);
|
let bits = ((inst.0 as u32) << 1) | (pos as u8 as u32);
|
||||||
|
|||||||
Reference in New Issue
Block a user