]> git.lizzy.rs Git - rust.git/commitdiff
Reuse the `DefsUsesVisitor` in `simulate_block()`.
authorNicholas Nethercote <nnethercote@mozilla.com>
Thu, 28 Jun 2018 06:30:33 +0000 (16:30 +1000)
committerNicholas Nethercote <nnethercote@mozilla.com>
Wed, 4 Jul 2018 03:05:03 +0000 (13:05 +1000)
This avoids a bunch of allocations for the bitsets within it,
speeding up a number of NLL benchmarks, the best by 1%.

src/librustc_mir/util/liveness.rs

index 4630cdae47d627d855c5e3fa5e71e2e76fa753a3..e1d5e302c3a062fad7142faec591004c7802a1f1 100644 (file)
@@ -179,27 +179,6 @@ pub fn simulate_block<'tcx, OP>(&self, mir: &Mir<'tcx>, block: BasicBlock, mut c
             block,
             statement_index,
         };
-        let terminator_defs_uses = self.defs_uses(mir, terminator_location, &data.terminator);
-        terminator_defs_uses.apply(&mut bits);
-        callback(terminator_location, &bits);
-
-        // Compute liveness before each statement (in rev order) and invoke callback.
-        for statement in data.statements.iter().rev() {
-            statement_index -= 1;
-            let statement_location = Location {
-                block,
-                statement_index,
-            };
-            let statement_defs_uses = self.defs_uses(mir, statement_location, statement);
-            statement_defs_uses.apply(&mut bits);
-            callback(statement_location, &bits);
-        }
-    }
-
-    fn defs_uses<'tcx, V>(&self, mir: &Mir<'tcx>, location: Location, thing: &V) -> DefsUses
-    where
-        V: MirVisitable<'tcx>,
-    {
         let locals = mir.local_decls.len();
         let mut visitor = DefsUsesVisitor {
             mode: self.mode,
@@ -208,12 +187,22 @@ fn defs_uses<'tcx, V>(&self, mir: &Mir<'tcx>, location: Location, thing: &V) ->
                 uses: LocalSet::new_empty(locals),
             },
         };
-
         // Visit the various parts of the basic block in reverse. If we go
         // forward, the logic in `add_def` and `add_use` would be wrong.
-        thing.apply(location, &mut visitor);
+        visitor.update_bits_and_do_callback(terminator_location, &data.terminator, &mut bits,
+                                            &mut callback);
 
-        visitor.defs_uses
+        // Compute liveness before each statement (in rev order) and invoke callback.
+        for statement in data.statements.iter().rev() {
+            statement_index -= 1;
+            let statement_location = Location {
+                block,
+                statement_index,
+            };
+            visitor.defs_uses.clear();
+            visitor.update_bits_and_do_callback(statement_location, statement, &mut bits,
+                                                &mut callback);
+        }
     }
 }
 
@@ -304,6 +293,11 @@ struct DefsUses {
 }
 
 impl DefsUses {
+    fn clear(&mut self) {
+        self.uses.clear();
+        self.defs.clear();
+    }
+
     fn apply(&self, bits: &mut LocalSet) -> bool {
         bits.subtract(&self.defs) | bits.union(&self.uses)
     }
@@ -338,6 +332,22 @@ fn add_use(&mut self, index: Local) {
     }
 }
 
+impl DefsUsesVisitor {
+    /// Update `bits` with the effects of `value` and call `callback`. We
+    /// should always visit in reverse order. This method assumes that we have
+    /// not visited anything before; if you have, clear `bits` first.
+    fn update_bits_and_do_callback<'tcx, OP>(&mut self, location: Location,
+                                             value: &impl MirVisitable<'tcx>, bits: &mut LocalSet,
+                                             callback: &mut OP)
+    where
+        OP: FnMut(Location, &LocalSet),
+    {
+        value.apply(location, self);
+        self.defs_uses.apply(bits);
+        callback(location, bits);
+    }
+}
+
 impl<'tcx> Visitor<'tcx> for DefsUsesVisitor {
     fn visit_local(&mut self, &local: &Local, context: PlaceContext<'tcx>, _: Location) {
         match categorize(context, self.mode) {