Convert AllSets::on_entry_sets to a Vec<IdxSetBuf<E>>.

This makes it more like `AllSets::{gen,kill}_set`, removes the need for
a bunch of bitset range computations, and removes the need for `Bits`.

It's marginally less efficient, because we have to allocate one bitset
per basic block instead of one large shared bitset, but the difference
is negligible in practice.
This commit is contained in:
Nicholas Nethercote 2018-08-17 10:41:14 +10:00
parent 3ac79c7184
commit 04b50e22bb

View file

@ -10,7 +10,7 @@
use syntax::ast::{self, MetaItem};
use rustc_data_structures::bitslice::{bitwise, BitwiseOperator, Word};
use rustc_data_structures::bitslice::{bitwise, BitwiseOperator};
use rustc_data_structures::indexed_set::{HybridIdxSetBuf, IdxSet, IdxSetBuf};
use rustc_data_structures::indexed_vec::Idx;
use rustc_data_structures::work_queue::WorkQueue;
@ -23,7 +23,6 @@ use rustc::session::Session;
use std::borrow::Borrow;
use std::fmt;
use std::io;
use std::mem;
use std::path::PathBuf;
use std::usize;
@ -287,18 +286,6 @@ impl<'a, 'tcx: 'a, BD> DataflowBuilder<'a, 'tcx, BD> where BD: BitDenotation
}
}
/// Maps each block to a set of bits
#[derive(Clone, Debug)]
pub(crate) struct Bits<E:Idx> {
bits: IdxSetBuf<E>,
}
impl<E:Idx> Bits<E> {
fn new(bits: IdxSetBuf<E>) -> Self {
Bits { bits: bits }
}
}
/// DataflowResultsConsumer abstracts over walking the MIR with some
/// already constructed dataflow results.
///
@ -464,12 +451,8 @@ pub struct AllSets<E: Idx> {
/// Analysis bitwidth for each block.
bits_per_block: usize,
/// Number of words associated with each block entry
/// equal to bits_per_block / (mem::size_of::<Word> * 8), rounded up.
words_per_block: usize,
/// For each block, bits valid on entry to the block.
on_entry_sets: Bits<E>,
on_entry_sets: Vec<IdxSetBuf<E>>,
/// For each block, bits generated by executing the statements in
/// the block. (For comparison, the Terminator for each block is
@ -559,19 +542,15 @@ impl<'a, E:Idx> BlockSets<'a, E> {
impl<E:Idx> AllSets<E> {
pub fn bits_per_block(&self) -> usize { self.bits_per_block }
pub fn for_block(&mut self, block_idx: usize) -> BlockSets<E> {
let offset = self.words_per_block * block_idx;
let range = E::new(offset)..E::new(offset + self.words_per_block);
BlockSets {
on_entry: self.on_entry_sets.bits.range_mut(&range),
on_entry: &mut self.on_entry_sets[block_idx],
gen_set: &mut self.gen_sets[block_idx],
kill_set: &mut self.kill_sets[block_idx],
}
}
pub fn on_entry_set_for(&self, block_idx: usize) -> &IdxSet<E> {
let offset = self.words_per_block * block_idx;
let range = E::new(offset)..E::new(offset + self.words_per_block);
self.on_entry_sets.bits.range(&range)
pub fn on_entry_set_for(&self, block_idx: usize) -> &IdxSetBuf<E> {
&self.on_entry_sets[block_idx]
}
pub fn gen_set_for(&self, block_idx: usize) -> &HybridIdxSetBuf<E> {
&self.gen_sets[block_idx]
@ -731,18 +710,15 @@ impl<'a, 'tcx, D> DataflowAnalysis<'a, 'tcx, D> where D: BitDenotation
dead_unwinds: &'a IdxSet<mir::BasicBlock>,
denotation: D) -> Self where D: InitialFlow {
let bits_per_block = denotation.bits_per_block();
let bits_per_word = mem::size_of::<Word>() * 8;
let words_per_block = (bits_per_block + bits_per_word - 1) / bits_per_word;
let bits_per_block_rounded_up = words_per_block * bits_per_word; // a multiple of word size
let num_blocks = mir.basic_blocks().len();
let num_overall = num_blocks * bits_per_block_rounded_up;
let on_entry = Bits::new(if D::bottom_value() {
IdxSetBuf::new_filled(num_overall)
let on_entry_sets = if D::bottom_value() {
vec![IdxSetBuf::new_filled(bits_per_block); num_blocks]
} else {
IdxSetBuf::new_empty(num_overall)
});
let empties = vec![HybridIdxSetBuf::new_empty(bits_per_block); num_blocks];
vec![IdxSetBuf::new_empty(bits_per_block); num_blocks]
};
let gen_sets = vec![HybridIdxSetBuf::new_empty(bits_per_block); num_blocks];
let kill_sets = gen_sets.clone();
DataflowAnalysis {
mir,
@ -750,10 +726,9 @@ impl<'a, 'tcx, D> DataflowAnalysis<'a, 'tcx, D> where D: BitDenotation
flow_state: DataflowState {
sets: AllSets {
bits_per_block,
words_per_block,
on_entry_sets: on_entry,
gen_sets: empties.clone(),
kill_sets: empties,
on_entry_sets,
gen_sets,
kill_sets,
},
operator: denotation,
}
@ -873,5 +848,4 @@ impl<'a, 'tcx: 'a, D> DataflowAnalysis<'a, 'tcx, D> where D: BitDenotation
dirty_queue.insert(bb);
}
}
}