about summary refs log tree commit diff
diff options
context:
space:
mode:
authorMatthias Krüger <476013+matthiaskrgr@users.noreply.github.com>2025-06-04 07:54:34 +0200
committerGitHub <noreply@github.com>2025-06-04 07:54:34 +0200
commite63e53a3f64051a80d47e42ea56e740c8879100d (patch)
tree33146426c0d1a8bfeff4f0308a843dbb07d9b4e7
parent88620b400e0dceb982af11f2309516ef088cbffa (diff)
parenta0c19ee577542cbc9dbdead54c91e661aa6396de (diff)
downloadrust-e63e53a3f64051a80d47e42ea56e740c8879100d.tar.gz
rust-e63e53a3f64051a80d47e42ea56e740c8879100d.zip
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`
-rw-r--r--compiler/rustc_index/src/bit_set.rs26
-rw-r--r--compiler/rustc_index/src/bit_set/tests.rs19
-rw-r--r--src/tools/miri/src/alloc/isolated_alloc.rs5
3 files changed, 46 insertions, 4 deletions
diff --git a/compiler/rustc_index/src/bit_set.rs b/compiler/rustc_index/src/bit_set.rs
index 07934389158..a4885aabe1f 100644
--- a/compiler/rustc_index/src/bit_set.rs
+++ b/compiler/rustc_index/src/bit_set.rs
@@ -234,6 +234,32 @@ impl<T: Idx> DenseBitSet<T> {
         self.clear_excess_bits();
     }
 
+    /// Checks whether any bit in the given range is a 1.
+    #[inline]
+    pub fn contains_any(&self, elems: impl RangeBounds<T>) -> bool {
+        let Some((start, end)) = inclusive_start_end(elems, self.domain_size) else {
+            return false;
+        };
+        let (start_word_index, start_mask) = word_index_and_mask(start);
+        let (end_word_index, end_mask) = word_index_and_mask(end);
+
+        if start_word_index == end_word_index {
+            self.words[start_word_index] & (end_mask | (end_mask - start_mask)) != 0
+        } else {
+            if self.words[start_word_index] & !(start_mask - 1) != 0 {
+                return true;
+            }
+
+            let remaining = start_word_index + 1..end_word_index;
+            if remaining.start <= remaining.end {
+                self.words[remaining].iter().any(|&w| w != 0)
+                    || self.words[end_word_index] & (end_mask | (end_mask - 1)) != 0
+            } else {
+                false
+            }
+        }
+    }
+
     /// Returns `true` if the set has changed.
     #[inline]
     pub fn remove(&mut self, elem: T) -> bool {
diff --git a/compiler/rustc_index/src/bit_set/tests.rs b/compiler/rustc_index/src/bit_set/tests.rs
index 323a66ddc6f..9ce4cf4293f 100644
--- a/compiler/rustc_index/src/bit_set/tests.rs
+++ b/compiler/rustc_index/src/bit_set/tests.rs
@@ -692,6 +692,25 @@ fn dense_last_set_before() {
     }
 }
 
+#[test]
+fn dense_contains_any() {
+    let mut set: DenseBitSet<usize> = DenseBitSet::new_empty(300);
+    assert!(!set.contains_any(0..300));
+    set.insert_range(10..20);
+    set.insert_range(60..70);
+    set.insert_range(150..=250);
+
+    assert!(set.contains_any(0..30));
+    assert!(set.contains_any(5..100));
+    assert!(set.contains_any(250..255));
+
+    assert!(!set.contains_any(20..59));
+    assert!(!set.contains_any(256..290));
+
+    set.insert(22);
+    assert!(set.contains_any(20..59));
+}
+
 #[bench]
 fn bench_insert(b: &mut Bencher) {
     let mut bs = DenseBitSet::new_filled(99999usize);
diff --git a/src/tools/miri/src/alloc/isolated_alloc.rs b/src/tools/miri/src/alloc/isolated_alloc.rs
index 7b74d171373..3a7879f372a 100644
--- a/src/tools/miri/src/alloc/isolated_alloc.rs
+++ b/src/tools/miri/src/alloc/isolated_alloc.rs
@@ -145,10 +145,7 @@ impl IsolatedAlloc {
             if pinfo.domain_size() < offset_pinfo + size_pinfo {
                 break;
             }
-            // FIXME: is there a more efficient way to check whether the entire range is unset
-            // in the bitset?
-            let range_avail = !(offset_pinfo..offset_pinfo + size_pinfo).any(|i| pinfo.contains(i));
-            if range_avail {
+            if !pinfo.contains_any(offset_pinfo..offset_pinfo + size_pinfo) {
                 pinfo.insert_range(offset_pinfo..offset_pinfo + size_pinfo);
                 // SAFETY: We checked the available bytes after `idx` in the call
                 // to `domain_size` above and asserted there are at least `idx +