From f730bd0dad555e2a5db4b0110b0888ca515f6fef Mon Sep 17 00:00:00 2001 From: Eric Holk Date: Thu, 16 Dec 2021 17:15:35 -0800 Subject: [PATCH] Track changed bitsets in CFG propagation This reduces the amount of work done, especially in later iterations, by only processing nodes whose predecessors changed in the previous iteration, or earlier in the current iteration. This also has the side effect of completely ignoring all unreachable nodes. --- .../drop_ranges/cfg_propagate.rs | 29 +++++++++++++++++-- 1 file changed, 26 insertions(+), 3 deletions(-) diff --git a/compiler/rustc_typeck/src/check/generator_interior/drop_ranges/cfg_propagate.rs b/compiler/rustc_typeck/src/check/generator_interior/drop_ranges/cfg_propagate.rs index a540812f4a32..139d17d2e1ca 100644 --- a/compiler/rustc_typeck/src/check/generator_interior/drop_ranges/cfg_propagate.rs +++ b/compiler/rustc_typeck/src/check/generator_interior/drop_ranges/cfg_propagate.rs @@ -10,10 +10,28 @@ pub fn propagate_to_fixpoint(&mut self) { trace!("predecessors: {:#?}", preds.iter_enumerated().collect::>()); let mut new_state = BitSet::new_empty(self.num_values()); + let mut changed_nodes = BitSet::new_empty(self.nodes.len()); + let mut unchanged_mask = BitSet::new_filled(self.nodes.len()); + changed_nodes.insert(0u32.into()); let mut propagate = || { let mut changed = false; + unchanged_mask.insert_all(); for id in self.nodes.indices() { + trace!("processing {:?}, changed_nodes: {:?}", id, changed_nodes); + // Check if any predecessor has changed, and if not then short-circuit. + // + // We handle the start node specially, since it doesn't have any predecessors, + // but we need to start somewhere. + if match id.index() { + 0 => !changed_nodes.contains(id), + _ => !preds[id].iter().any(|pred| changed_nodes.contains(*pred)), + } { + trace!("short-circuiting because none of {:?} have changed", preds[id]); + unchanged_mask.remove(id); + continue; + } + if id.index() == 0 { new_state.clear(); } else { @@ -23,8 +41,7 @@ pub fn propagate_to_fixpoint(&mut self) { }; for pred in &preds[id] { - let state = &self.nodes[*pred].drop_state; - new_state.intersect(state); + new_state.intersect(&self.nodes[*pred].drop_state); } for drop in &self.nodes[id].drops { @@ -35,9 +52,15 @@ pub fn propagate_to_fixpoint(&mut self) { new_state.remove(*reinit); } - changed |= self.nodes[id].drop_state.intersect(&new_state); + if self.nodes[id].drop_state.intersect(&new_state) { + changed_nodes.insert(id); + changed = true; + } else { + unchanged_mask.remove(id); + } } + changed_nodes.intersect(&unchanged_mask); changed };