Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit 36b495f

Browse files
committedFeb 22, 2022
Introduce ChunkedBitSet and use it for some dataflow analyses.
This reduces peak memory usage significantly for some programs with very large functions, such as: - `keccak`, `unicode_normalization`, and `match-stress-enum`, from the `rustc-perf` benchmark suite; - `http-0.2.6` from crates.io. The new type is used in the analyses where the bitsets can get huge (e.g. 10s of thousands of bits): `MaybeInitializedPlaces`, `MaybeUninitializedPlaces`, and `EverInitializedPlaces`. Some refactoring was required in `rustc_mir_dataflow`. All existing analysis domains are either `BitSet` or a trivial wrapper around `BitSet`, and access in a few places is done via `Borrow<BitSet>` or `BorrowMut<BitSet>`. Now that some of these domains are `ClusterBitSet`, that no longer works. So this commit replaces the `Borrow`/`BorrowMut` usage with a new trait `BitSetExt` containing the needed bitset operations. The impls just forward these to the underlying bitset type. This required fiddling with trait bounds in a few places. The commit also: - Moves `static_assert_size` from `rustc_data_structures` to `rustc_index` so it can be used in the latter; the former now re-exports it so existing users are unaffected. - Factors out some common "clear excess bits in the final word" functionality in `bit_set.rs`. - Uses `fill` in a few places instead of loops.
1 parent 523a1b1 commit 36b495f

File tree

14 files changed

+804
-73
lines changed

14 files changed

+804
-73
lines changed
 

‎compiler/rustc_borrowck/src/lib.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ use rustc_errors::{Applicability, Diagnostic, DiagnosticBuilder, ErrorReported};
2222
use rustc_hir as hir;
2323
use rustc_hir::def_id::LocalDefId;
2424
use rustc_hir::Node;
25-
use rustc_index::bit_set::BitSet;
25+
use rustc_index::bit_set::ChunkedBitSet;
2626
use rustc_index::vec::IndexVec;
2727
use rustc_infer::infer::{InferCtxt, TyCtxtInferExt};
2828
use rustc_middle::mir::{
@@ -1667,7 +1667,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
16671667
location: Location,
16681668
desired_action: InitializationRequiringAction,
16691669
place_span: (PlaceRef<'tcx>, Span),
1670-
maybe_uninits: &BitSet<MovePathIndex>,
1670+
maybe_uninits: &ChunkedBitSet<MovePathIndex>,
16711671
from: u64,
16721672
to: u64,
16731673
) {

‎compiler/rustc_data_structures/src/lib.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,8 @@ extern crate cfg_if;
3737
#[macro_use]
3838
extern crate rustc_macros;
3939

40+
pub use rustc_index::static_assert_size;
41+
4042
#[inline(never)]
4143
#[cold]
4244
pub fn cold_path<F: FnOnce() -> R, R>(f: F) -> R {

‎compiler/rustc_data_structures/src/macros.rs

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,3 @@
1-
/// Type size assertion. The first argument is a type and the second argument is its expected size.
2-
#[macro_export]
3-
macro_rules! static_assert_size {
4-
($ty:ty, $size:expr) => {
5-
const _: [(); $size] = [(); ::std::mem::size_of::<$ty>()];
6-
};
7-
}
8-
91
#[macro_export]
102
macro_rules! enum_from_u32 {
113
($(#[$attr:meta])* pub enum $name:ident {

‎compiler/rustc_index/src/bit_set.rs

Lines changed: 471 additions & 27 deletions
Large diffs are not rendered by default.

‎compiler/rustc_index/src/bit_set/tests.rs

Lines changed: 195 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -147,6 +147,201 @@ fn hybrid_bitset() {
147147
assert!(dense0.is_empty());
148148
}
149149

150+
#[test]
151+
fn chunked_bitset() {
152+
let mut b0 = ChunkedBitSet::<usize>::new_empty(0);
153+
let b0b = b0.clone();
154+
assert_eq!(b0, ChunkedBitSet { domain_size: 0, chunks: Box::new([]), marker: PhantomData });
155+
156+
// There are no valid insert/remove/contains operations on a 0-domain
157+
// bitset, but we can test `union`.
158+
b0.assert_valid();
159+
assert!(!b0.union(&b0b));
160+
assert_eq!(b0.chunks(), vec![]);
161+
assert_eq!(b0.count(), 0);
162+
b0.assert_valid();
163+
164+
//-----------------------------------------------------------------------
165+
166+
let mut b1 = ChunkedBitSet::<usize>::new_empty(1);
167+
assert_eq!(
168+
b1,
169+
ChunkedBitSet { domain_size: 1, chunks: Box::new([Zeros(1)]), marker: PhantomData }
170+
);
171+
172+
b1.assert_valid();
173+
assert!(!b1.contains(0));
174+
assert_eq!(b1.count(), 0);
175+
assert!(b1.insert(0));
176+
assert!(b1.contains(0));
177+
assert_eq!(b1.count(), 1);
178+
assert_eq!(b1.chunks(), [Ones(1)]);
179+
assert!(!b1.insert(0));
180+
assert!(b1.remove(0));
181+
assert!(!b1.contains(0));
182+
assert_eq!(b1.count(), 0);
183+
assert_eq!(b1.chunks(), [Zeros(1)]);
184+
b1.assert_valid();
185+
186+
//-----------------------------------------------------------------------
187+
188+
let mut b100 = ChunkedBitSet::<usize>::new_filled(100);
189+
assert_eq!(
190+
b100,
191+
ChunkedBitSet { domain_size: 100, chunks: Box::new([Ones(100)]), marker: PhantomData }
192+
);
193+
194+
b100.assert_valid();
195+
for i in 0..100 {
196+
assert!(b100.contains(i));
197+
}
198+
assert_eq!(b100.count(), 100);
199+
assert!(b100.remove(3));
200+
assert!(b100.insert(3));
201+
assert_eq!(b100.chunks(), vec![Ones(100)]);
202+
assert!(
203+
b100.remove(20) && b100.remove(30) && b100.remove(40) && b100.remove(99) && b100.insert(30)
204+
);
205+
assert_eq!(b100.count(), 97);
206+
assert!(!b100.contains(20) && b100.contains(30) && !b100.contains(99) && b100.contains(50));
207+
assert_eq!(
208+
b100.chunks(),
209+
vec![Mixed(
210+
100,
211+
97,
212+
#[rustfmt::skip]
213+
Rc::new([
214+
0b11111111_11111111_11111110_11111111_11111111_11101111_11111111_11111111,
215+
0b00000000_00000000_00000000_00000111_11111111_11111111_11111111_11111111,
216+
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
217+
0, 0, 0, 0, 0,
218+
])
219+
)],
220+
);
221+
b100.assert_valid();
222+
let mut num_removed = 0;
223+
for i in 0..100 {
224+
if b100.remove(i) {
225+
num_removed += 1;
226+
}
227+
}
228+
assert_eq!(num_removed, 97);
229+
assert_eq!(b100.chunks(), vec![Zeros(100)]);
230+
b100.assert_valid();
231+
232+
//-----------------------------------------------------------------------
233+
234+
let mut b2548 = ChunkedBitSet::<usize>::new_empty(2548);
235+
assert_eq!(
236+
b2548,
237+
ChunkedBitSet {
238+
domain_size: 2548,
239+
chunks: Box::new([Zeros(2048), Zeros(500)]),
240+
marker: PhantomData,
241+
}
242+
);
243+
244+
b2548.assert_valid();
245+
b2548.insert(14);
246+
b2548.remove(14);
247+
assert_eq!(b2548.chunks(), vec![Zeros(2048), Zeros(500)]);
248+
b2548.insert_all();
249+
for i in 0..2548 {
250+
assert!(b2548.contains(i));
251+
}
252+
assert_eq!(b2548.count(), 2548);
253+
assert_eq!(b2548.chunks(), vec![Ones(2048), Ones(500)]);
254+
b2548.assert_valid();
255+
256+
//-----------------------------------------------------------------------
257+
258+
let mut b4096 = ChunkedBitSet::<usize>::new_empty(4096);
259+
assert_eq!(
260+
b4096,
261+
ChunkedBitSet {
262+
domain_size: 4096,
263+
chunks: Box::new([Zeros(2048), Zeros(2048)]),
264+
marker: PhantomData,
265+
}
266+
);
267+
268+
b4096.assert_valid();
269+
for i in 0..4096 {
270+
assert!(!b4096.contains(i));
271+
}
272+
assert!(b4096.insert(0) && b4096.insert(4095) && !b4096.insert(4095));
273+
assert!(
274+
b4096.contains(0) && !b4096.contains(2047) && !b4096.contains(2048) && b4096.contains(4095)
275+
);
276+
assert_eq!(
277+
b4096.chunks(),
278+
#[rustfmt::skip]
279+
vec![
280+
Mixed(2048, 1, Rc::new([
281+
1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
282+
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
283+
])),
284+
Mixed(2048, 1, Rc::new([
285+
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
286+
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x8000_0000_0000_0000
287+
])),
288+
],
289+
);
290+
assert_eq!(b4096.count(), 2);
291+
b4096.assert_valid();
292+
293+
//-----------------------------------------------------------------------
294+
295+
let mut b10000 = ChunkedBitSet::<usize>::new_empty(10000);
296+
assert_eq!(
297+
b10000,
298+
ChunkedBitSet {
299+
domain_size: 10000,
300+
chunks: Box::new([Zeros(2048), Zeros(2048), Zeros(2048), Zeros(2048), Zeros(1808),]),
301+
marker: PhantomData,
302+
}
303+
);
304+
305+
b10000.assert_valid();
306+
assert!(b10000.insert(3000) && b10000.insert(5000));
307+
assert_eq!(
308+
b10000.chunks(),
309+
#[rustfmt::skip]
310+
vec![
311+
Zeros(2048),
312+
Mixed(2048, 1, Rc::new([
313+
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x0100_0000_0000_0000, 0,
314+
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
315+
])),
316+
Mixed(2048, 1, Rc::new([
317+
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x0100, 0,
318+
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
319+
])),
320+
Zeros(2048),
321+
Zeros(1808),
322+
],
323+
);
324+
let mut b10000b = ChunkedBitSet::<usize>::new_empty(10000);
325+
b10000b.clone_from(&b10000);
326+
assert_eq!(b10000, b10000b);
327+
for i in 6000..7000 {
328+
b10000b.insert(i);
329+
}
330+
assert_eq!(b10000b.count(), 1002);
331+
b10000b.assert_valid();
332+
b10000b.clone_from(&b10000);
333+
assert_eq!(b10000b.count(), 2);
334+
for i in 2000..8000 {
335+
b10000b.insert(i);
336+
}
337+
b10000.union(&b10000b);
338+
assert_eq!(b10000.count(), 6000);
339+
b10000.union(&b10000b);
340+
assert_eq!(b10000.count(), 6000);
341+
b10000.assert_valid();
342+
b10000b.assert_valid();
343+
}
344+
150345
#[test]
151346
fn grow() {
152347
let mut set: GrowableBitSet<usize> = GrowableBitSet::with_capacity(65);

‎compiler/rustc_index/src/lib.rs

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,21 @@
11
#![feature(allow_internal_unstable)]
22
#![feature(bench_black_box)]
33
#![feature(extend_one)]
4+
#![feature(let_else)]
45
#![feature(min_specialization)]
6+
#![feature(new_uninit)]
57
#![feature(step_trait)]
8+
#![feature(stmt_expr_attributes)]
69
#![feature(test)]
7-
#![feature(let_else)]
810

911
pub mod bit_set;
1012
pub mod interval;
1113
pub mod vec;
14+
15+
/// Type size assertion. The first argument is a type and the second argument is its expected size.
16+
#[macro_export]
17+
macro_rules! static_assert_size {
18+
($ty:ty, $size:expr) => {
19+
const _: [(); $size] = [(); ::std::mem::size_of::<$ty>()];
20+
};
21+
}

‎compiler/rustc_mir_dataflow/src/framework/cursor.rs

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,12 @@
11
//! Random access inspection of the results of a dataflow analysis.
22
3+
use crate::framework::BitSetExt;
4+
35
use std::borrow::Borrow;
46
use std::cmp::Ordering;
57

8+
#[cfg(debug_assertions)]
69
use rustc_index::bit_set::BitSet;
7-
use rustc_index::vec::Idx;
810
use rustc_middle::mir::{self, BasicBlock, Location};
911

1012
use super::{Analysis, Direction, Effect, EffectIndex, Results};
@@ -209,13 +211,13 @@ where
209211
}
210212
}
211213

212-
impl<'mir, 'tcx, A, R, T> ResultsCursor<'mir, 'tcx, A, R>
214+
impl<'mir, 'tcx, A, R> ResultsCursor<'mir, 'tcx, A, R>
213215
where
214-
A: Analysis<'tcx, Domain = BitSet<T>>,
215-
T: Idx,
216+
A: crate::GenKillAnalysis<'tcx>,
217+
A::Domain: BitSetExt<A::Idx>,
216218
R: Borrow<Results<'tcx, A>>,
217219
{
218-
pub fn contains(&self, elem: T) -> bool {
220+
pub fn contains(&self, elem: A::Idx) -> bool {
219221
self.get().contains(elem)
220222
}
221223
}

‎compiler/rustc_mir_dataflow/src/framework/engine.rs

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
//! A solver for dataflow problems.
22
3-
use std::borrow::BorrowMut;
3+
use crate::framework::BitSetExt;
4+
45
use std::ffi::OsString;
56
use std::path::PathBuf;
67

@@ -91,7 +92,7 @@ where
9192
impl<'a, 'tcx, A, D, T> Engine<'a, 'tcx, A>
9293
where
9394
A: GenKillAnalysis<'tcx, Idx = T, Domain = D>,
94-
D: Clone + JoinSemiLattice + GenKill<T> + BorrowMut<BitSet<T>>,
95+
D: Clone + JoinSemiLattice + GenKill<T> + BitSetExt<T>,
9596
T: Idx,
9697
{
9798
/// Creates a new `Engine` to solve a gen-kill dataflow problem.
@@ -106,7 +107,7 @@ where
106107

107108
// Otherwise, compute and store the cumulative transfer function for each block.
108109

109-
let identity = GenKillSet::identity(analysis.bottom_value(body).borrow().domain_size());
110+
let identity = GenKillSet::identity(analysis.bottom_value(body).domain_size());
110111
let mut trans_for_block = IndexVec::from_elem(identity, body.basic_blocks());
111112

112113
for (block, block_data) in body.basic_blocks().iter_enumerated() {
@@ -115,7 +116,7 @@ where
115116
}
116117

117118
let apply_trans = Box::new(move |bb: BasicBlock, state: &mut A::Domain| {
118-
trans_for_block[bb].apply(state.borrow_mut());
119+
trans_for_block[bb].apply(state);
119120
});
120121

121122
Self::new(tcx, body, analysis, Some(apply_trans as Box<_>))

‎compiler/rustc_mir_dataflow/src/framework/fmt.rs

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
//! Custom formatting traits used when outputting Graphviz diagrams with the results of a dataflow
22
//! analysis.
33
4-
use rustc_index::bit_set::{BitSet, HybridBitSet};
4+
use rustc_index::bit_set::{BitSet, ChunkedBitSet, HybridBitSet};
55
use rustc_index::vec::Idx;
66
use std::fmt;
77

@@ -133,6 +133,19 @@ where
133133
}
134134
}
135135

136+
impl<T, C> DebugWithContext<C> for ChunkedBitSet<T>
137+
where
138+
T: Idx + DebugWithContext<C>,
139+
{
140+
fn fmt_with(&self, _ctxt: &C, _f: &mut fmt::Formatter<'_>) -> fmt::Result {
141+
unimplemented!("implement when/if needed");
142+
}
143+
144+
fn fmt_diff_with(&self, _old: &Self, _ctxt: &C, _f: &mut fmt::Formatter<'_>) -> fmt::Result {
145+
unimplemented!("implement when/if needed");
146+
}
147+
}
148+
136149
impl<T, C> DebugWithContext<C> for &'_ T
137150
where
138151
T: DebugWithContext<C>,

‎compiler/rustc_mir_dataflow/src/framework/lattice.rs

Lines changed: 27 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,8 @@
3838
//! [Hasse diagram]: https://en.wikipedia.org/wiki/Hasse_diagram
3939
//! [poset]: https://en.wikipedia.org/wiki/Partially_ordered_set
4040
41-
use rustc_index::bit_set::BitSet;
41+
use crate::framework::BitSetExt;
42+
use rustc_index::bit_set::{BitSet, ChunkedBitSet, HybridBitSet};
4243
use rustc_index::vec::{Idx, IndexVec};
4344
use std::iter;
4445

@@ -145,6 +146,18 @@ impl<T: Idx> MeetSemiLattice for BitSet<T> {
145146
}
146147
}
147148

149+
impl<T: Idx> JoinSemiLattice for ChunkedBitSet<T> {
150+
fn join(&mut self, other: &Self) -> bool {
151+
self.union(other)
152+
}
153+
}
154+
155+
impl<T: Idx> MeetSemiLattice for ChunkedBitSet<T> {
156+
fn meet(&mut self, other: &Self) -> bool {
157+
self.intersect(other)
158+
}
159+
}
160+
148161
/// The counterpart of a given semilattice `T` using the [inverse order].
149162
///
150163
/// The dual of a join-semilattice is a meet-semilattice and vice versa. For example, the dual of a
@@ -155,15 +168,21 @@ impl<T: Idx> MeetSemiLattice for BitSet<T> {
155168
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
156169
pub struct Dual<T>(pub T);
157170

158-
impl<T> std::borrow::Borrow<T> for Dual<T> {
159-
fn borrow(&self) -> &T {
160-
&self.0
171+
impl<T: Idx> BitSetExt<T> for Dual<BitSet<T>> {
172+
fn domain_size(&self) -> usize {
173+
self.0.domain_size()
174+
}
175+
176+
fn contains(&self, elem: T) -> bool {
177+
self.0.contains(elem)
178+
}
179+
180+
fn union(&mut self, other: &HybridBitSet<T>) {
181+
self.0.union(other);
161182
}
162-
}
163183

164-
impl<T> std::borrow::BorrowMut<T> for Dual<T> {
165-
fn borrow_mut(&mut self) -> &mut T {
166-
&mut self.0
184+
fn subtract(&mut self, other: &HybridBitSet<T>) {
185+
self.0.subtract(other);
167186
}
168187
}
169188

‎compiler/rustc_mir_dataflow/src/framework/mod.rs

Lines changed: 58 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -30,10 +30,9 @@
3030
//!
3131
//! [gen-kill]: https://en.wikipedia.org/wiki/Data-flow_analysis#Bit_vector_problems
3232
33-
use std::borrow::BorrowMut;
3433
use std::cmp::Ordering;
3534

36-
use rustc_index::bit_set::{BitSet, HybridBitSet};
35+
use rustc_index::bit_set::{BitSet, ChunkedBitSet, HybridBitSet};
3736
use rustc_index::vec::Idx;
3837
use rustc_middle::mir::{self, BasicBlock, Location};
3938
use rustc_middle::ty::TyCtxt;
@@ -52,6 +51,51 @@ pub use self::engine::{Engine, Results};
5251
pub use self::lattice::{JoinSemiLattice, MeetSemiLattice};
5352
pub use self::visitor::{visit_results, ResultsVisitable, ResultsVisitor};
5453

54+
/// Analysis domains are all bitsets of various kinds. This trait holds
55+
/// operations needed by all of them.
56+
pub trait BitSetExt<T> {
57+
fn domain_size(&self) -> usize;
58+
fn contains(&self, elem: T) -> bool;
59+
fn union(&mut self, other: &HybridBitSet<T>);
60+
fn subtract(&mut self, other: &HybridBitSet<T>);
61+
}
62+
63+
impl<T: Idx> BitSetExt<T> for BitSet<T> {
64+
fn domain_size(&self) -> usize {
65+
self.domain_size()
66+
}
67+
68+
fn contains(&self, elem: T) -> bool {
69+
self.contains(elem)
70+
}
71+
72+
fn union(&mut self, other: &HybridBitSet<T>) {
73+
self.union(other);
74+
}
75+
76+
fn subtract(&mut self, other: &HybridBitSet<T>) {
77+
self.subtract(other);
78+
}
79+
}
80+
81+
impl<T: Idx> BitSetExt<T> for ChunkedBitSet<T> {
82+
fn domain_size(&self) -> usize {
83+
self.domain_size()
84+
}
85+
86+
fn contains(&self, elem: T) -> bool {
87+
self.contains(elem)
88+
}
89+
90+
fn union(&mut self, other: &HybridBitSet<T>) {
91+
self.union(other);
92+
}
93+
94+
fn subtract(&mut self, other: &HybridBitSet<T>) {
95+
self.subtract(other);
96+
}
97+
}
98+
5599
/// Define the domain of a dataflow problem.
56100
///
57101
/// This trait specifies the lattice on which this analysis operates (the domain) as well as its
@@ -303,7 +347,7 @@ pub trait GenKillAnalysis<'tcx>: Analysis<'tcx> {
303347
impl<'tcx, A> Analysis<'tcx> for A
304348
where
305349
A: GenKillAnalysis<'tcx>,
306-
A::Domain: GenKill<A::Idx> + BorrowMut<BitSet<A::Idx>>,
350+
A::Domain: GenKill<A::Idx> + BitSetExt<A::Idx>,
307351
{
308352
fn apply_statement_effect(
309353
&self,
@@ -435,7 +479,7 @@ impl<T: Idx> GenKillSet<T> {
435479
}
436480
}
437481

438-
pub fn apply(&self, state: &mut BitSet<T>) {
482+
pub fn apply(&self, state: &mut impl BitSetExt<T>) {
439483
state.union(&self.gen);
440484
state.subtract(&self.kill);
441485
}
@@ -463,6 +507,16 @@ impl<T: Idx> GenKill<T> for BitSet<T> {
463507
}
464508
}
465509

510+
impl<T: Idx> GenKill<T> for ChunkedBitSet<T> {
511+
fn gen(&mut self, elem: T) {
512+
self.insert(elem);
513+
}
514+
515+
fn kill(&mut self, elem: T) {
516+
self.remove(elem);
517+
}
518+
}
519+
466520
impl<T: Idx> GenKill<T> for lattice::Dual<BitSet<T>> {
467521
fn gen(&mut self, elem: T) {
468522
self.0.insert(elem);

‎compiler/rustc_mir_dataflow/src/impls/mod.rs

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
//! bitvectors attached to each basic block, represented via a
33
//! zero-sized structure.
44
5-
use rustc_index::bit_set::BitSet;
5+
use rustc_index::bit_set::{BitSet, ChunkedBitSet};
66
use rustc_index::vec::Idx;
77
use rustc_middle::mir::visit::{MirVisitable, Visitor};
88
use rustc_middle::mir::{self, Body, Location};
@@ -286,12 +286,12 @@ impl<'a, 'tcx> DefinitelyInitializedPlaces<'a, 'tcx> {
286286
}
287287

288288
impl<'tcx> AnalysisDomain<'tcx> for MaybeInitializedPlaces<'_, 'tcx> {
289-
type Domain = BitSet<MovePathIndex>;
289+
type Domain = ChunkedBitSet<MovePathIndex>;
290290
const NAME: &'static str = "maybe_init";
291291

292292
fn bottom_value(&self, _: &mir::Body<'tcx>) -> Self::Domain {
293293
// bottom = uninitialized
294-
BitSet::new_empty(self.move_data().move_paths.len())
294+
ChunkedBitSet::new_empty(self.move_data().move_paths.len())
295295
}
296296

297297
fn initialize_start_block(&self, _: &mir::Body<'tcx>, state: &mut Self::Domain) {
@@ -417,13 +417,13 @@ impl<'tcx> GenKillAnalysis<'tcx> for MaybeInitializedPlaces<'_, 'tcx> {
417417
}
418418

419419
impl<'tcx> AnalysisDomain<'tcx> for MaybeUninitializedPlaces<'_, 'tcx> {
420-
type Domain = BitSet<MovePathIndex>;
420+
type Domain = ChunkedBitSet<MovePathIndex>;
421421

422422
const NAME: &'static str = "maybe_uninit";
423423

424424
fn bottom_value(&self, _: &mir::Body<'tcx>) -> Self::Domain {
425425
// bottom = initialized (start_block_effect counters this at outset)
426-
BitSet::new_empty(self.move_data().move_paths.len())
426+
ChunkedBitSet::new_empty(self.move_data().move_paths.len())
427427
}
428428

429429
// sets on_entry bits for Arg places
@@ -606,13 +606,13 @@ impl<'tcx> GenKillAnalysis<'tcx> for DefinitelyInitializedPlaces<'_, 'tcx> {
606606
}
607607

608608
impl<'tcx> AnalysisDomain<'tcx> for EverInitializedPlaces<'_, 'tcx> {
609-
type Domain = BitSet<InitIndex>;
609+
type Domain = ChunkedBitSet<InitIndex>;
610610

611611
const NAME: &'static str = "ever_init";
612612

613613
fn bottom_value(&self, _: &mir::Body<'tcx>) -> Self::Domain {
614614
// bottom = no initialized variables by default
615-
BitSet::new_empty(self.move_data().inits.len())
615+
ChunkedBitSet::new_empty(self.move_data().inits.len())
616616
}
617617

618618
fn initialize_start_block(&self, body: &mir::Body<'tcx>, state: &mut Self::Domain) {

‎compiler/rustc_mir_dataflow/src/rustc_peek.rs

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,3 @@
1-
use std::borrow::Borrow;
2-
31
use rustc_ast::ast;
42
use rustc_span::symbol::sym;
53
use rustc_span::Span;
@@ -10,6 +8,7 @@ use rustc_middle::mir::MirPass;
108
use rustc_middle::mir::{self, Body, Local, Location};
119
use rustc_middle::ty::{self, Ty, TyCtxt};
1210

11+
use crate::framework::BitSetExt;
1312
use crate::impls::{
1413
DefinitelyInitializedPlaces, MaybeInitializedPlaces, MaybeLiveLocals, MaybeUninitializedPlaces,
1514
};
@@ -248,7 +247,7 @@ pub trait RustcPeekAt<'tcx>: Analysis<'tcx> {
248247
impl<'tcx, A, D> RustcPeekAt<'tcx> for A
249248
where
250249
A: Analysis<'tcx, Domain = D> + HasMoveData<'tcx>,
251-
D: JoinSemiLattice + Clone + Borrow<BitSet<MovePathIndex>>,
250+
D: JoinSemiLattice + Clone + BitSetExt<MovePathIndex>,
252251
{
253252
fn peek_at(
254253
&self,
@@ -259,7 +258,7 @@ where
259258
) {
260259
match self.move_data().rev_lookup.find(place.as_ref()) {
261260
LookupResult::Exact(peek_mpi) => {
262-
let bit_state = flow_state.borrow().contains(peek_mpi);
261+
let bit_state = flow_state.contains(peek_mpi);
263262
debug!("rustc_peek({:?} = &{:?}) bit_state: {}", call.arg, place, bit_state);
264263
if !bit_state {
265264
tcx.sess.span_err(call.span, "rustc_peek: bit not set");

‎compiler/rustc_mir_transform/src/remove_uninit_drops.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use rustc_index::bit_set::BitSet;
1+
use rustc_index::bit_set::ChunkedBitSet;
22
use rustc_middle::mir::{Body, Field, Rvalue, Statement, StatementKind, TerminatorKind};
33
use rustc_middle::ty::subst::SubstsRef;
44
use rustc_middle::ty::{self, ParamEnv, Ty, TyCtxt, VariantDef};
@@ -89,7 +89,7 @@ impl<'tcx> MirPass<'tcx> for RemoveUninitDrops {
8989
fn is_needs_drop_and_init<'tcx>(
9090
tcx: TyCtxt<'tcx>,
9191
param_env: ParamEnv<'tcx>,
92-
maybe_inits: &BitSet<MovePathIndex>,
92+
maybe_inits: &ChunkedBitSet<MovePathIndex>,
9393
move_data: &MoveData<'tcx>,
9494
ty: Ty<'tcx>,
9595
mpi: MovePathIndex,

0 commit comments

Comments
 (0)
Please sign in to comment.