diff --git a/compiler/rustc_index/src/bit_set.rs b/compiler/rustc_index/src/bit_set.rs index f7649c5f5c55e..e93e46a597bfa 100644 --- a/compiler/rustc_index/src/bit_set.rs +++ b/compiler/rustc_index/src/bit_set.rs @@ -803,29 +803,41 @@ impl BitRelations> for ChunkedBitSet { // words, and this happens often enough that it's a // performance win. Also, we only need to operate on the // in-use words, hence the slicing. - let op = |a, b| a | b; let num_words = num_words(chunk_domain_size as usize); - if bitwise_changes( + + // If both sides are the same, nothing will change. This + // case is very common and it's a pretty fast check, so + // it's a performance win to do it. + if self_chunk_words[0..num_words] == other_chunk_words[0..num_words] { + continue; + } + + // Do a more precise "will anything change?" test. + let op = |a, b| a | b; + if !bitwise_changes( &self_chunk_words[0..num_words], &other_chunk_words[0..num_words], op, ) { - let self_chunk_words = Rc::make_mut(self_chunk_words); - let has_changed = bitwise( - &mut self_chunk_words[0..num_words], - &other_chunk_words[0..num_words], - op, - ); - debug_assert!(has_changed); - *self_chunk_count = self_chunk_words[0..num_words] - .iter() - .map(|w| w.count_ones() as ChunkSize) - .sum(); - if *self_chunk_count == chunk_domain_size { - *self_chunk = Ones; - } - changed = true; + continue; + } + + // If we reach here, `self_chunk_words` is definitely changing. + let self_chunk_words = Rc::make_mut(self_chunk_words); + let has_changed = bitwise( + &mut self_chunk_words[0..num_words], + &other_chunk_words[0..num_words], + op, + ); + debug_assert!(has_changed); + *self_chunk_count = self_chunk_words[0..num_words] + .iter() + .map(|w| w.count_ones() as ChunkSize) + .sum(); + if *self_chunk_count == chunk_domain_size { + *self_chunk = Ones; } + changed = true; } } } @@ -882,30 +894,32 @@ impl BitRelations> for ChunkedBitSet { Mixed(self_chunk_count, self_chunk_words), Mixed(_other_chunk_count, other_chunk_words), ) => { - // See [`>>::union`] for the explanation - let op = |a: u64, b: u64| a & !b; + // See `ChunkedBitSet::union` for details on what is happening here. let num_words = num_words(chunk_domain_size as usize); - if bitwise_changes( + let op = |a: u64, b: u64| a & !b; + if !bitwise_changes( &self_chunk_words[0..num_words], &other_chunk_words[0..num_words], op, ) { - let self_chunk_words = Rc::make_mut(self_chunk_words); - let has_changed = bitwise( - &mut self_chunk_words[0..num_words], - &other_chunk_words[0..num_words], - op, - ); - debug_assert!(has_changed); - *self_chunk_count = self_chunk_words[0..num_words] - .iter() - .map(|w| w.count_ones() as ChunkSize) - .sum(); - if *self_chunk_count == 0 { - *self_chunk = Zeros; - } - changed = true; + continue; } + + let self_chunk_words = Rc::make_mut(self_chunk_words); + let has_changed = bitwise( + &mut self_chunk_words[0..num_words], + &other_chunk_words[0..num_words], + op, + ); + debug_assert!(has_changed); + *self_chunk_count = self_chunk_words[0..num_words] + .iter() + .map(|w| w.count_ones() as ChunkSize) + .sum(); + if *self_chunk_count == 0 { + *self_chunk = Zeros; + } + changed = true; } } } @@ -941,30 +955,32 @@ impl BitRelations> for ChunkedBitSet { Mixed(self_chunk_count, self_chunk_words), Mixed(_other_chunk_count, other_chunk_words), ) => { - // See [`>>::union`] for the explanation - let op = |a, b| a & b; + // See `ChunkedBitSet::union` for details on what is happening here. let num_words = num_words(chunk_domain_size as usize); - if bitwise_changes( + let op = |a, b| a & b; + if !bitwise_changes( &self_chunk_words[0..num_words], &other_chunk_words[0..num_words], op, ) { - let self_chunk_words = Rc::make_mut(self_chunk_words); - let has_changed = bitwise( - &mut self_chunk_words[0..num_words], - &other_chunk_words[0..num_words], - op, - ); - debug_assert!(has_changed); - *self_chunk_count = self_chunk_words[0..num_words] - .iter() - .map(|w| w.count_ones() as ChunkSize) - .sum(); - if *self_chunk_count == 0 { - *self_chunk = Zeros; - } - changed = true; + continue; } + + let self_chunk_words = Rc::make_mut(self_chunk_words); + let has_changed = bitwise( + &mut self_chunk_words[0..num_words], + &other_chunk_words[0..num_words], + op, + ); + debug_assert!(has_changed); + *self_chunk_count = self_chunk_words[0..num_words] + .iter() + .map(|w| w.count_ones() as ChunkSize) + .sum(); + if *self_chunk_count == 0 { + *self_chunk = Zeros; + } + changed = true; } } }