Skip to content

Commit b638d8c

Browse files
committed
Auto merge of #53656 - nnethercote:HybridIdxSet-tweaks, r=nikomatsakis
`HybridIdxSet` tweaks A couple of tweaks to `HybridIdxSet`. r? @nikomatsakis
2 parents 291d958 + 626b298 commit b638d8c

File tree

4 files changed

+110
-84
lines changed

4 files changed

+110
-84
lines changed

src/librustc_data_structures/indexed_set.rs

+100-74
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,20 @@ use bitslice::{bitwise, Union, Subtract, Intersect};
1919
use indexed_vec::Idx;
2020
use rustc_serialize;
2121

22+
/// This is implemented by all the index sets so that IdxSet::union() can be
23+
/// passed any type of index set.
24+
pub trait UnionIntoIdxSet<T: Idx> {
25+
// Performs `other = other | self`.
26+
fn union_into(&self, other: &mut IdxSet<T>) -> bool;
27+
}
28+
29+
/// This is implemented by all the index sets so that IdxSet::subtract() can be
30+
/// passed any type of index set.
31+
pub trait SubtractFromIdxSet<T: Idx> {
32+
// Performs `other = other - self`.
33+
fn subtract_from(&self, other: &mut IdxSet<T>) -> bool;
34+
}
35+
2236
/// Represents a set of some element type E, where each E is identified by some
2337
/// unique index type `T`.
2438
///
@@ -68,34 +82,34 @@ impl<T: Idx> fmt::Debug for IdxSet<T> {
6882
}
6983

7084
impl<T: Idx> IdxSet<T> {
71-
fn new(init: Word, universe_size: usize) -> Self {
72-
let num_words = (universe_size + (BITS_PER_WORD - 1)) / BITS_PER_WORD;
85+
fn new(init: Word, domain_size: usize) -> Self {
86+
let num_words = (domain_size + (BITS_PER_WORD - 1)) / BITS_PER_WORD;
7387
IdxSet {
7488
_pd: Default::default(),
7589
bits: vec![init; num_words],
7690
}
7791
}
7892

79-
/// Creates set holding every element whose index falls in range 0..universe_size.
80-
pub fn new_filled(universe_size: usize) -> Self {
81-
let mut result = Self::new(!0, universe_size);
82-
result.trim_to(universe_size);
93+
/// Creates set holding every element whose index falls in range 0..domain_size.
94+
pub fn new_filled(domain_size: usize) -> Self {
95+
let mut result = Self::new(!0, domain_size);
96+
result.trim_to(domain_size);
8397
result
8498
}
8599

86100
/// Creates set holding no elements.
87-
pub fn new_empty(universe_size: usize) -> Self {
88-
Self::new(0, universe_size)
101+
pub fn new_empty(domain_size: usize) -> Self {
102+
Self::new(0, domain_size)
89103
}
90104

91105
/// Duplicates as a hybrid set.
92106
pub fn to_hybrid(&self) -> HybridIdxSet<T> {
93-
// This universe_size may be slightly larger than the one specified
107+
// This domain_size may be slightly larger than the one specified
94108
// upon creation, due to rounding up to a whole word. That's ok.
95-
let universe_size = self.bits.len() * BITS_PER_WORD;
109+
let domain_size = self.bits.len() * BITS_PER_WORD;
96110

97111
// Note: we currently don't bother trying to make a Sparse set.
98-
HybridIdxSet::Dense(self.to_owned(), universe_size)
112+
HybridIdxSet::Dense(self.to_owned(), domain_size)
99113
}
100114

101115
/// Removes all elements
@@ -105,29 +119,29 @@ impl<T: Idx> IdxSet<T> {
105119
}
106120
}
107121

108-
/// Sets all elements up to `universe_size`
109-
pub fn set_up_to(&mut self, universe_size: usize) {
122+
/// Sets all elements up to `domain_size`
123+
pub fn set_up_to(&mut self, domain_size: usize) {
110124
for b in &mut self.bits {
111125
*b = !0;
112126
}
113-
self.trim_to(universe_size);
127+
self.trim_to(domain_size);
114128
}
115129

116-
/// Clear all elements above `universe_size`.
117-
fn trim_to(&mut self, universe_size: usize) {
130+
/// Clear all elements above `domain_size`.
131+
fn trim_to(&mut self, domain_size: usize) {
118132
// `trim_block` is the first block where some bits have
119133
// to be cleared.
120-
let trim_block = universe_size / BITS_PER_WORD;
134+
let trim_block = domain_size / BITS_PER_WORD;
121135

122136
// all the blocks above it have to be completely cleared.
123137
if trim_block < self.bits.len() {
124138
for b in &mut self.bits[trim_block+1..] {
125139
*b = 0;
126140
}
127141

128-
// at that block, the `universe_size % BITS_PER_WORD` lsbs
142+
// at that block, the `domain_size % BITS_PER_WORD` LSBs
129143
// should remain.
130-
let remaining_bits = universe_size % BITS_PER_WORD;
144+
let remaining_bits = domain_size % BITS_PER_WORD;
131145
let mask = (1<<remaining_bits)-1;
132146
self.bits[trim_block] &= mask;
133147
}
@@ -164,48 +178,14 @@ impl<T: Idx> IdxSet<T> {
164178

165179
/// Set `self = self | other` and return true if `self` changed
166180
/// (i.e., if new bits were added).
167-
pub fn union(&mut self, other: &IdxSet<T>) -> bool {
168-
bitwise(self.words_mut(), other.words(), &Union)
169-
}
170-
171-
/// Like `union()`, but takes a `SparseIdxSet` argument.
172-
fn union_sparse(&mut self, other: &SparseIdxSet<T>) -> bool {
173-
let mut changed = false;
174-
for elem in other.iter() {
175-
changed |= self.add(&elem);
176-
}
177-
changed
178-
}
179-
180-
/// Like `union()`, but takes a `HybridIdxSet` argument.
181-
pub fn union_hybrid(&mut self, other: &HybridIdxSet<T>) -> bool {
182-
match other {
183-
HybridIdxSet::Sparse(sparse, _) => self.union_sparse(sparse),
184-
HybridIdxSet::Dense(dense, _) => self.union(dense),
185-
}
181+
pub fn union(&mut self, other: &impl UnionIntoIdxSet<T>) -> bool {
182+
other.union_into(self)
186183
}
187184

188185
/// Set `self = self - other` and return true if `self` changed.
189186
/// (i.e., if any bits were removed).
190-
pub fn subtract(&mut self, other: &IdxSet<T>) -> bool {
191-
bitwise(self.words_mut(), other.words(), &Subtract)
192-
}
193-
194-
/// Like `subtract()`, but takes a `SparseIdxSet` argument.
195-
fn subtract_sparse(&mut self, other: &SparseIdxSet<T>) -> bool {
196-
let mut changed = false;
197-
for elem in other.iter() {
198-
changed |= self.remove(&elem);
199-
}
200-
changed
201-
}
202-
203-
/// Like `subtract()`, but takes a `HybridIdxSet` argument.
204-
pub fn subtract_hybrid(&mut self, other: &HybridIdxSet<T>) -> bool {
205-
match other {
206-
HybridIdxSet::Sparse(sparse, _) => self.subtract_sparse(sparse),
207-
HybridIdxSet::Dense(dense, _) => self.subtract(dense),
208-
}
187+
pub fn subtract(&mut self, other: &impl SubtractFromIdxSet<T>) -> bool {
188+
other.subtract_from(self)
209189
}
210190

211191
/// Set `self = self & other` and return true if `self` changed.
@@ -223,6 +203,18 @@ impl<T: Idx> IdxSet<T> {
223203
}
224204
}
225205

206+
impl<T: Idx> UnionIntoIdxSet<T> for IdxSet<T> {
207+
fn union_into(&self, other: &mut IdxSet<T>) -> bool {
208+
bitwise(other.words_mut(), self.words(), &Union)
209+
}
210+
}
211+
212+
impl<T: Idx> SubtractFromIdxSet<T> for IdxSet<T> {
213+
fn subtract_from(&self, other: &mut IdxSet<T>) -> bool {
214+
bitwise(other.words_mut(), self.words(), &Subtract)
215+
}
216+
}
217+
226218
pub struct Iter<'a, T: Idx> {
227219
cur: Option<(Word, usize)>,
228220
iter: iter::Enumerate<slice::Iter<'a, Word>>,
@@ -293,8 +285,8 @@ impl<T: Idx> SparseIdxSet<T> {
293285
}
294286
}
295287

296-
fn to_dense(&self, universe_size: usize) -> IdxSet<T> {
297-
let mut dense = IdxSet::new_empty(universe_size);
288+
fn to_dense(&self, domain_size: usize) -> IdxSet<T> {
289+
let mut dense = IdxSet::new_empty(domain_size);
298290
for elem in self.0.iter() {
299291
dense.add(elem);
300292
}
@@ -308,6 +300,26 @@ impl<T: Idx> SparseIdxSet<T> {
308300
}
309301
}
310302

303+
impl<T: Idx> UnionIntoIdxSet<T> for SparseIdxSet<T> {
304+
fn union_into(&self, other: &mut IdxSet<T>) -> bool {
305+
let mut changed = false;
306+
for elem in self.iter() {
307+
changed |= other.add(&elem);
308+
}
309+
changed
310+
}
311+
}
312+
313+
impl<T: Idx> SubtractFromIdxSet<T> for SparseIdxSet<T> {
314+
fn subtract_from(&self, other: &mut IdxSet<T>) -> bool {
315+
let mut changed = false;
316+
for elem in self.iter() {
317+
changed |= other.remove(&elem);
318+
}
319+
changed
320+
}
321+
}
322+
311323
pub struct SparseIter<'a, T: Idx> {
312324
iter: slice::Iter<'a, T>,
313325
}
@@ -323,28 +335,24 @@ impl<'a, T: Idx> Iterator for SparseIter<'a, T> {
323335
/// Like IdxSet, but with a hybrid representation: sparse when there are few
324336
/// elements in the set, but dense when there are many. It's especially
325337
/// efficient for sets that typically have a small number of elements, but a
326-
/// large `universe_size`, and are cleared frequently.
338+
/// large `domain_size`, and are cleared frequently.
327339
#[derive(Clone, Debug)]
328340
pub enum HybridIdxSet<T: Idx> {
329341
Sparse(SparseIdxSet<T>, usize),
330342
Dense(IdxSet<T>, usize),
331343
}
332344

333345
impl<T: Idx> HybridIdxSet<T> {
334-
pub fn new_empty(universe_size: usize) -> Self {
335-
HybridIdxSet::Sparse(SparseIdxSet::new(), universe_size)
346+
pub fn new_empty(domain_size: usize) -> Self {
347+
HybridIdxSet::Sparse(SparseIdxSet::new(), domain_size)
336348
}
337349

338-
fn universe_size(&mut self) -> usize {
339-
match *self {
350+
pub fn clear(&mut self) {
351+
let domain_size = match *self {
340352
HybridIdxSet::Sparse(_, size) => size,
341353
HybridIdxSet::Dense(_, size) => size,
342-
}
343-
}
344-
345-
pub fn clear(&mut self) {
346-
let universe_size = self.universe_size();
347-
*self = HybridIdxSet::new_empty(universe_size);
354+
};
355+
*self = HybridIdxSet::new_empty(domain_size);
348356
}
349357

350358
/// Returns true iff set `self` contains `elem`.
@@ -374,11 +382,11 @@ impl<T: Idx> HybridIdxSet<T> {
374382
// appease the borrow checker.
375383
let dummy = HybridIdxSet::Sparse(SparseIdxSet::new(), 0);
376384
match mem::replace(self, dummy) {
377-
HybridIdxSet::Sparse(sparse, universe_size) => {
378-
let mut dense = sparse.to_dense(universe_size);
385+
HybridIdxSet::Sparse(sparse, domain_size) => {
386+
let mut dense = sparse.to_dense(domain_size);
379387
let changed = dense.add(elem);
380388
assert!(changed);
381-
mem::replace(self, HybridIdxSet::Dense(dense, universe_size));
389+
mem::replace(self, HybridIdxSet::Dense(dense, domain_size));
382390
changed
383391
}
384392
_ => panic!("impossible"),
@@ -401,7 +409,7 @@ impl<T: Idx> HybridIdxSet<T> {
401409
/// Converts to a dense set, consuming itself in the process.
402410
pub fn to_dense(self) -> IdxSet<T> {
403411
match self {
404-
HybridIdxSet::Sparse(sparse, universe_size) => sparse.to_dense(universe_size),
412+
HybridIdxSet::Sparse(sparse, domain_size) => sparse.to_dense(domain_size),
405413
HybridIdxSet::Dense(dense, _) => dense,
406414
}
407415
}
@@ -415,6 +423,24 @@ impl<T: Idx> HybridIdxSet<T> {
415423
}
416424
}
417425

426+
impl<T: Idx> UnionIntoIdxSet<T> for HybridIdxSet<T> {
427+
fn union_into(&self, other: &mut IdxSet<T>) -> bool {
428+
match self {
429+
HybridIdxSet::Sparse(sparse, _) => sparse.union_into(other),
430+
HybridIdxSet::Dense(dense, _) => dense.union_into(other),
431+
}
432+
}
433+
}
434+
435+
impl<T: Idx> SubtractFromIdxSet<T> for HybridIdxSet<T> {
436+
fn subtract_from(&self, other: &mut IdxSet<T>) -> bool {
437+
match self {
438+
HybridIdxSet::Sparse(sparse, _) => sparse.subtract_from(other),
439+
HybridIdxSet::Dense(dense, _) => dense.subtract_from(other),
440+
}
441+
}
442+
}
443+
418444
pub enum HybridIter<'a, T: Idx> {
419445
Sparse(SparseIter<'a, T>),
420446
Dense(Iter<'a, T>),

src/librustc_mir/dataflow/at_location.rs

+4-4
Original file line numberDiff line numberDiff line change
@@ -129,8 +129,8 @@ where
129129
F: FnOnce(Iter<BD::Idx>),
130130
{
131131
let mut curr_state = self.curr_state.clone();
132-
curr_state.union_hybrid(&self.stmt_gen);
133-
curr_state.subtract_hybrid(&self.stmt_kill);
132+
curr_state.union(&self.stmt_gen);
133+
curr_state.subtract(&self.stmt_kill);
134134
f(curr_state.iter());
135135
}
136136
}
@@ -193,8 +193,8 @@ impl<BD> FlowsAtLocation for FlowAtLocation<BD>
193193
}
194194

195195
fn apply_local_effect(&mut self, _loc: Location) {
196-
self.curr_state.union_hybrid(&self.stmt_gen);
197-
self.curr_state.subtract_hybrid(&self.stmt_kill);
196+
self.curr_state.union(&self.stmt_gen);
197+
self.curr_state.subtract(&self.stmt_kill);
198198
}
199199
}
200200

src/librustc_mir/dataflow/mod.rs

+4-4
Original file line numberDiff line numberDiff line change
@@ -241,8 +241,8 @@ impl<'b, 'a: 'b, 'tcx: 'a, BD> PropagationContext<'b, 'a, 'tcx, BD> where BD: Bi
241241
let sets = self.builder.flow_state.sets.for_block(bb.index());
242242
debug_assert!(in_out.words().len() == sets.on_entry.words().len());
243243
in_out.overwrite(sets.on_entry);
244-
in_out.union_hybrid(sets.gen_set);
245-
in_out.subtract_hybrid(sets.kill_set);
244+
in_out.union(sets.gen_set);
245+
in_out.subtract(sets.kill_set);
246246
}
247247
self.builder.propagate_bits_into_graph_successors_of(
248248
in_out, (bb, bb_data), &mut dirty_queue);
@@ -534,8 +534,8 @@ impl<'a, E:Idx> BlockSets<'a, E> {
534534
}
535535

536536
fn apply_local_effect(&mut self) {
537-
self.on_entry.union_hybrid(&self.gen_set);
538-
self.on_entry.subtract_hybrid(&self.kill_set);
537+
self.on_entry.union(self.gen_set);
538+
self.on_entry.subtract(self.kill_set);
539539
}
540540
}
541541

src/librustc_mir/transform/rustc_peek.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -209,8 +209,8 @@ fn each_block<'a, 'tcx, O>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
209209
&mut sets, Location { block: bb, statement_index: j });
210210
results.0.operator.statement_effect(
211211
&mut sets, Location { block: bb, statement_index: j });
212-
sets.on_entry.union_hybrid(sets.gen_set);
213-
sets.on_entry.subtract_hybrid(sets.kill_set);
212+
sets.on_entry.union(sets.gen_set);
213+
sets.on_entry.subtract(sets.kill_set);
214214
}
215215

216216
results.0.operator.before_terminator_effect(

0 commit comments

Comments
 (0)