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 a540812f4a3..139d17d2e1c 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 @@ impl DropRangesBuilder { 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 @@ impl DropRangesBuilder { }; 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 @@ impl DropRangesBuilder { 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 };