Skip to content

Commit e63e53a

Browse files
authored
Rollup merge of #141871 - nia-e:fix-bitset, r=eholk
index: add method for checking range on DenseBitSet Micro-optimisation that Miri benefits from with the new isolated allocator for native-libs mode. Also possibly just a useful method to have on `DenseBitSet`
2 parents 88620b4 + a0c19ee commit e63e53a

File tree

3 files changed

+46
-4
lines changed

3 files changed

+46
-4
lines changed

compiler/rustc_index/src/bit_set.rs

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -234,6 +234,32 @@ impl<T: Idx> DenseBitSet<T> {
234234
self.clear_excess_bits();
235235
}
236236

237+
/// Checks whether any bit in the given range is a 1.
238+
#[inline]
239+
pub fn contains_any(&self, elems: impl RangeBounds<T>) -> bool {
240+
let Some((start, end)) = inclusive_start_end(elems, self.domain_size) else {
241+
return false;
242+
};
243+
let (start_word_index, start_mask) = word_index_and_mask(start);
244+
let (end_word_index, end_mask) = word_index_and_mask(end);
245+
246+
if start_word_index == end_word_index {
247+
self.words[start_word_index] & (end_mask | (end_mask - start_mask)) != 0
248+
} else {
249+
if self.words[start_word_index] & !(start_mask - 1) != 0 {
250+
return true;
251+
}
252+
253+
let remaining = start_word_index + 1..end_word_index;
254+
if remaining.start <= remaining.end {
255+
self.words[remaining].iter().any(|&w| w != 0)
256+
|| self.words[end_word_index] & (end_mask | (end_mask - 1)) != 0
257+
} else {
258+
false
259+
}
260+
}
261+
}
262+
237263
/// Returns `true` if the set has changed.
238264
#[inline]
239265
pub fn remove(&mut self, elem: T) -> bool {

compiler/rustc_index/src/bit_set/tests.rs

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -692,6 +692,25 @@ fn dense_last_set_before() {
692692
}
693693
}
694694

695+
#[test]
696+
fn dense_contains_any() {
697+
let mut set: DenseBitSet<usize> = DenseBitSet::new_empty(300);
698+
assert!(!set.contains_any(0..300));
699+
set.insert_range(10..20);
700+
set.insert_range(60..70);
701+
set.insert_range(150..=250);
702+
703+
assert!(set.contains_any(0..30));
704+
assert!(set.contains_any(5..100));
705+
assert!(set.contains_any(250..255));
706+
707+
assert!(!set.contains_any(20..59));
708+
assert!(!set.contains_any(256..290));
709+
710+
set.insert(22);
711+
assert!(set.contains_any(20..59));
712+
}
713+
695714
#[bench]
696715
fn bench_insert(b: &mut Bencher) {
697716
let mut bs = DenseBitSet::new_filled(99999usize);

src/tools/miri/src/alloc/isolated_alloc.rs

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -145,10 +145,7 @@ impl IsolatedAlloc {
145145
if pinfo.domain_size() < offset_pinfo + size_pinfo {
146146
break;
147147
}
148-
// FIXME: is there a more efficient way to check whether the entire range is unset
149-
// in the bitset?
150-
let range_avail = !(offset_pinfo..offset_pinfo + size_pinfo).any(|i| pinfo.contains(i));
151-
if range_avail {
148+
if !pinfo.contains_any(offset_pinfo..offset_pinfo + size_pinfo) {
152149
pinfo.insert_range(offset_pinfo..offset_pinfo + size_pinfo);
153150
// SAFETY: We checked the available bytes after `idx` in the call
154151
// to `domain_size` above and asserted there are at least `idx +

0 commit comments

Comments
 (0)