Optimize live point computation

This is just replicating the previous algorithm, but taking advantage of the
bitset structures to optimize into tighter and better optimized loops.
Particularly advantageous on enormous MIR blocks, which are relatively rare in
practice.
This commit is contained in:
Mark Rousskov 2021-11-01 10:04:01 -04:00
parent ff0e14829e
commit 03afb61b53
5 changed files with 278 additions and 29 deletions

View file

@ -370,6 +370,101 @@ fn sparse_matrix_operations() {
}
}
#[test]
fn dense_insert_range() {
#[track_caller]
fn check<R>(domain: usize, range: R)
where
R: RangeBounds<usize> + Clone + IntoIterator<Item = usize> + std::fmt::Debug,
{
let mut set = BitSet::new_empty(domain);
set.insert_range(range.clone());
for i in set.iter() {
assert!(range.contains(&i));
}
for i in range.clone() {
assert!(set.contains(i), "{} in {:?}, inserted {:?}", i, set, range);
}
}
check(300, 10..10);
check(300, WORD_BITS..WORD_BITS * 2);
check(300, WORD_BITS - 1..WORD_BITS * 2);
check(300, WORD_BITS - 1..WORD_BITS);
check(300, 10..100);
check(300, 10..30);
check(300, 0..5);
check(300, 0..250);
check(300, 200..250);
check(300, 10..=10);
check(300, WORD_BITS..=WORD_BITS * 2);
check(300, WORD_BITS - 1..=WORD_BITS * 2);
check(300, WORD_BITS - 1..=WORD_BITS);
check(300, 10..=100);
check(300, 10..=30);
check(300, 0..=5);
check(300, 0..=250);
check(300, 200..=250);
for i in 0..WORD_BITS * 2 {
for j in i..WORD_BITS * 2 {
check(WORD_BITS * 2, i..j);
check(WORD_BITS * 2, i..=j);
check(300, i..j);
check(300, i..=j);
}
}
}
#[test]
fn dense_last_set_before() {
fn easy(set: &BitSet<usize>, needle: impl RangeBounds<usize>) -> Option<usize> {
let mut last_leq = None;
for e in set.iter() {
if needle.contains(&e) {
last_leq = Some(e);
}
}
last_leq
}
#[track_caller]
fn cmp(set: &BitSet<usize>, needle: impl RangeBounds<usize> + Clone + std::fmt::Debug) {
assert_eq!(
set.last_set_in(needle.clone()),
easy(set, needle.clone()),
"{:?} in {:?}",
needle,
set
);
}
let mut set = BitSet::new_empty(300);
cmp(&set, 50..=50);
set.insert(WORD_BITS);
cmp(&set, WORD_BITS..=WORD_BITS);
set.insert(WORD_BITS - 1);
cmp(&set, 0..=WORD_BITS - 1);
cmp(&set, 0..=5);
cmp(&set, 10..100);
set.insert(100);
cmp(&set, 100..110);
cmp(&set, 99..100);
cmp(&set, 99..=100);
for i in 0..=WORD_BITS * 2 {
for j in i..=WORD_BITS * 2 {
for k in 0..WORD_BITS * 2 {
let mut set = BitSet::new_empty(300);
cmp(&set, i..j);
cmp(&set, i..=j);
set.insert(k);
cmp(&set, i..j);
cmp(&set, i..=j);
}
}
}
}
/// Merge dense hybrid set into empty sparse hybrid set.
#[bench]
fn union_hybrid_sparse_empty_to_dense(b: &mut Bencher) {