Skip to content
This repository was archived by the owner on May 28, 2025. It is now read-only.

Commit 890dc65

Browse files
Tage Johanssonlqd
authored andcommitted
Implement union_not for ThinBitSet.
1 parent bec1072 commit 890dc65

File tree

5 files changed

+59
-17
lines changed

5 files changed

+59
-17
lines changed

compiler/rustc_index/src/bit_set/old_dense_bit_set.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -206,7 +206,7 @@ impl<T: Idx> DenseBitSet<T> {
206206
///
207207
/// FIXME: Incorporate this into [`BitRelations`] and fill out
208208
/// implementations for other bitset types, if needed.
209-
pub fn union_not(&mut self, other: &DenseBitSet<T>) {
209+
pub fn union_not(&mut self, other: &DenseBitSet<T>, _domain_size: usize) {
210210
assert_eq!(self.domain_size, other.domain_size);
211211

212212
// FIXME(Zalathar): If we were to forcibly _set_ all excess bits before

compiler/rustc_index/src/bit_set/tests.rs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,15 @@ fn union_not() {
9292
b.insert(63);
9393
b.insert(81); // Already in `a`.
9494
b.insert(90);
95+
96+
a.union_not(&b, 100);
97+
98+
// After union-not, `a` should contain all values in the domain, except for
99+
// the ones that are in `b` and were _not_ already in `a`.
100+
assert_eq!(
101+
a.iter().collect::<Vec<_>>(),
102+
(0usize..100).filter(|&x| !matches!(x, 7 | 63 | 90)).collect::<Vec<_>>(),
103+
);
95104
}
96105

97106
#[test]

compiler/rustc_index/src/bit_set/thin_bit_set.rs

Lines changed: 43 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -342,6 +342,39 @@ impl<T> ThinBitSet<T> {
342342
}
343343
}
344344

345+
/// Sets `self = self | !other` for all elements less than `domain_size`.
346+
#[inline(always)]
347+
pub fn union_not(&mut self, other: &Self, domain_size: usize) {
348+
if self.is_inline() {
349+
assert!(other.is_inline());
350+
351+
let self_word = unsafe { &mut self.inline };
352+
let other_word = unsafe { other.inline };
353+
354+
debug_assert!(domain_size <= Self::INLINE_CAPACITY);
355+
356+
*self_word |= !other_word & !(Word::MAX >> domain_size);
357+
} else if other.is_empty_unallocated() {
358+
self.insert_all(domain_size);
359+
} else {
360+
let self_words = self.on_heap_get_or_alloc().as_mut_slice();
361+
let other_words = other.on_heap().unwrap().as_slice();
362+
363+
// Set all but the last word if domain_size is not divisible by `WORD_BITS`.
364+
for (self_word, other_word) in
365+
self_words.iter_mut().zip(other_words).take(domain_size / WORD_BITS)
366+
{
367+
*self_word |= !other_word;
368+
}
369+
370+
let remaining_bits = domain_size % WORD_BITS;
371+
if remaining_bits > 0 {
372+
let last_idx = domain_size / WORD_BITS;
373+
self_words[last_idx] |= !other_words[last_idx] & !(Word::MAX << remaining_bits);
374+
}
375+
}
376+
}
377+
345378
/// Common function for union/intersection-like operations.
346379
///
347380
/// This function takes two bit sets—one mutably, one immutably. Neither must be the
@@ -426,11 +459,6 @@ impl<T> ThinBitSet<T> {
426459
}
427460
}
428461

429-
#[inline(always)]
430-
pub fn union_not(&mut self, _other: &Self) {
431-
todo!()
432-
}
433-
434462
super::bit_relations_inherent_impls! {}
435463
}
436464

@@ -1483,22 +1511,27 @@ mod tests {
14831511
assert_eq!(set_2.remove(elem), set_2_reference.remove(elem));
14841512
}
14851513
}
1486-
70..79 => {
1514+
70..76 => {
14871515
// Union
14881516
assert_eq!(set_1.union(&set_2), set_1_reference.union(&set_2_reference));
14891517
}
1490-
79..88 => {
1518+
76..82 => {
14911519
// Intersection
14921520
assert_eq!(
14931521
set_1.intersect(&set_2),
14941522
set_1_reference.intersect(&set_2_reference)
14951523
);
14961524
}
1497-
88..97 => {
1525+
82..88 => {
14981526
// Subtraction
14991527
assert_eq!(set_1.subtract(&set_2), set_1_reference.subtract(&set_2_reference));
15001528
}
1501-
97..99 => {
1529+
88..94 => {
1530+
// Union_not
1531+
set_1.union_not(&set_2, domain_size);
1532+
set_1_reference.union_not(&set_2_reference, domain_size);
1533+
}
1534+
94..97 => {
15021535
// Clear
15031536
if rng.next_bool() {
15041537
set_1.clear();
@@ -1508,7 +1541,7 @@ mod tests {
15081541
set_2_reference.clear();
15091542
}
15101543
}
1511-
99..100 => {
1544+
97..100 => {
15121545
// Test new_filled().
15131546
if rng.next_bool() {
15141547
set_1 = ThinBitSet::new_filled(domain_size);

compiler/rustc_index/src/bit_set/twin_bit_set.rs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -49,10 +49,10 @@ macro_rules! compare_results_clone_arg(
4949
);
5050

5151
macro_rules! compare_results_with_self(
52-
($self:ident, $method:tt, $other:expr) => {
52+
($self:ident, $method:tt, $other:expr $(, $extra_arg:expr)?) => {
5353
{
54-
let thin_res = $self.thin.$method(&$other.thin);
55-
let old_res = $self.old.$method(&$other.old);
54+
let thin_res = $self.thin.$method(&$other.thin $(, $extra_arg)?);
55+
let old_res = $self.old.$method(&$other.old $(, $extra_arg)?);
5656
$self.assert_valid();
5757
assert_eq!(thin_res, old_res, "TwinBitSet give different results in {}", stringify!($method));
5858
thin_res
@@ -154,8 +154,8 @@ impl<T: Idx> DenseBitSet<T> {
154154
bit_relations_inherent_impls! {}
155155

156156
/// Sets `self = self | !other`.
157-
pub fn union_not(&mut self, other: &DenseBitSet<T>) {
158-
compare_results_with_self!(self, union_not, other)
157+
pub fn union_not(&mut self, other: &DenseBitSet<T>, domain_size: usize) {
158+
compare_results_with_self!(self, union_not, other, domain_size)
159159
}
160160

161161
#[inline]

compiler/rustc_mir_transform/src/coverage/counters/balanced_flow.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@ impl<G: graph::DirectedGraph> BalancedFlowGraph<G> {
7272
// Next, find all nodes that are currently not reverse-reachable from
7373
// `sink_edge_nodes`, and add them to the set as well.
7474
dfs.complete_search();
75-
sink_edge_nodes.union_not(dfs.visited_set());
75+
sink_edge_nodes.union_not(dfs.visited_set(), graph.num_nodes());
7676

7777
// The sink node is 1 higher than the highest real node.
7878
let sink = G::Node::new(graph.num_nodes());

0 commit comments

Comments
 (0)