diff --git a/compiler/rustc_index/src/bit_set.rs b/compiler/rustc_index/src/bit_set.rs index 2de892fa797ab..0e7394006dd2d 100644 --- a/compiler/rustc_index/src/bit_set.rs +++ b/compiler/rustc_index/src/bit_set.rs @@ -800,27 +800,39 @@ 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. Also a + // performance win. + 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 = - count_ones(&self_chunk_words[0..num_words]) as ChunkSize; - 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 = count_ones(&self_chunk_words[0..num_words]) as ChunkSize; + if *self_chunk_count == chunk_domain_size { + *self_chunk = Ones; } + changed = true; } } } @@ -874,28 +886,29 @@ 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 = - count_ones(&self_chunk_words[0..num_words]) as ChunkSize; - 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 = count_ones(&self_chunk_words[0..num_words]) as ChunkSize; + if *self_chunk_count == 0 { + *self_chunk = Zeros; + } + changed = true; } } } @@ -931,28 +944,29 @@ 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 = - count_ones(&self_chunk_words[0..num_words]) as ChunkSize; - 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 = count_ones(&self_chunk_words[0..num_words]) as ChunkSize; + if *self_chunk_count == 0 { + *self_chunk = Zeros; + } + changed = true; } } }