From facb9aca792f46d7a72116e2e0c3110bdebd1204 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Mon, 13 Oct 2025 19:12:23 +1100 Subject: [PATCH 1/2] Refactor some `ChunkedBitSet` operations. For less indentation, mostly. --- compiler/rustc_index/src/bit_set.rs | 97 +++++++++++++++-------------- 1 file changed, 50 insertions(+), 47 deletions(-) diff --git a/compiler/rustc_index/src/bit_set.rs b/compiler/rustc_index/src/bit_set.rs index 2de892fa797ab..7c146252407eb 100644 --- a/compiler/rustc_index/src/bit_set.rs +++ b/compiler/rustc_index/src/bit_set.rs @@ -800,27 +800,28 @@ 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( + 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; + } + + 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 +875,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 +933,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; } } } From 60481827f6f4c22239265ec001e95ae7a023badf Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Mon, 13 Oct 2025 19:17:27 +1100 Subject: [PATCH 2/2] Add a `!=` check to ChunkedBitSet::union. It's a big speed win for cranelift-codegen-0.119.0. --- compiler/rustc_index/src/bit_set.rs | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/compiler/rustc_index/src/bit_set.rs b/compiler/rustc_index/src/bit_set.rs index 7c146252407eb..0e7394006dd2d 100644 --- a/compiler/rustc_index/src/bit_set.rs +++ b/compiler/rustc_index/src/bit_set.rs @@ -801,6 +801,16 @@ impl BitRelations> for ChunkedBitSet { // performance win. Also, we only need to operate on the // in-use words, hence the slicing. let num_words = num_words(chunk_domain_size as usize); + + // 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], @@ -810,6 +820,7 @@ impl BitRelations> for ChunkedBitSet { 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],