From 20cc4da711626c83d355dc116f49ad0bbd7a14e0 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 | 112 +++++++++++++++------------- 1 file changed, 59 insertions(+), 53 deletions(-) diff --git a/compiler/rustc_index/src/bit_set.rs b/compiler/rustc_index/src/bit_set.rs index f7649c5f5c55e..c249d0ff87127 100644 --- a/compiler/rustc_index/src/bit_set.rs +++ b/compiler/rustc_index/src/bit_set.rs @@ -803,29 +803,31 @@ 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 = 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; } + + 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 +884,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 +945,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; } } } From ad8b2e0761ef319ecaa27535848c183b4a857f06 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 | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/compiler/rustc_index/src/bit_set.rs b/compiler/rustc_index/src/bit_set.rs index c249d0ff87127..e93e46a597bfa 100644 --- a/compiler/rustc_index/src/bit_set.rs +++ b/compiler/rustc_index/src/bit_set.rs @@ -804,6 +804,15 @@ 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. let op = |a, b| a | b; if !bitwise_changes( &self_chunk_words[0..num_words], @@ -813,6 +822,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],