From 08683f003cab472efc0481c349cb69dfb137c4c1 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Thu, 28 Jun 2018 16:20:32 +1000 Subject: [PATCH] Rename `IdxSet::clone_from`. The current situation is something of a mess. - `IdxSetBuf` derefs to `IdxSet`. - `IdxSetBuf` implements `Clone`, and therefore has a provided `clone_from` method, which does allocation and so is expensive. - `IdxSet` has a `clone_from` method that is non-allocating and therefore cheap, but this method is not from the `Clone` trait. As a result, if you have an `IdxSetBuf` called `b`, if you call `b.clone_from(b2)` you'll get the expensive `IdxSetBuf` method, but if you call `(*b).clone_from(b2)` you'll get the cheap `IdxSetBuf` method. `liveness_of_locals()` does the former, presumably unintentionally, and therefore does lots of unnecessary allocations. Having a `clone_from` method that isn't from the `Clone` trait is a bad idea in general, so this patch renames it as `overwrite`. This avoids the unnecessary allocations in `liveness_of_locals()`, speeding up most NLL benchmarks, the best by 1.5%. It also means that calls of the form `(*b).clone_from(b2)` can be rewritten as `b.overwrite(b2)`. --- src/librustc_data_structures/indexed_set.rs | 4 +++- src/librustc_mir/dataflow/at_location.rs | 2 +- src/librustc_mir/dataflow/mod.rs | 2 +- src/librustc_mir/util/liveness.rs | 4 ++-- 4 files changed, 7 insertions(+), 5 deletions(-) diff --git a/src/librustc_data_structures/indexed_set.rs b/src/librustc_data_structures/indexed_set.rs index c9495587c46..30b87c0390a 100644 --- a/src/librustc_data_structures/indexed_set.rs +++ b/src/librustc_data_structures/indexed_set.rs @@ -233,7 +233,9 @@ impl IdxSet { &mut self.bits } - pub fn clone_from(&mut self, other: &IdxSet) { + /// Efficiently overwrite `self` with `other`. Panics if `self` and `other` + /// don't have the same length. + pub fn overwrite(&mut self, other: &IdxSet) { self.words_mut().clone_from_slice(other.words()); } diff --git a/src/librustc_mir/dataflow/at_location.rs b/src/librustc_mir/dataflow/at_location.rs index a89d1afae86..05453bd58c4 100644 --- a/src/librustc_mir/dataflow/at_location.rs +++ b/src/librustc_mir/dataflow/at_location.rs @@ -139,7 +139,7 @@ impl FlowsAtLocation for FlowAtLocation where BD: BitDenotation { fn reset_to_entry_of(&mut self, bb: BasicBlock) { - (*self.curr_state).clone_from(self.base_results.sets().on_entry_set_for(bb.index())); + self.curr_state.overwrite(self.base_results.sets().on_entry_set_for(bb.index())); } fn reconstruct_statement_effect(&mut self, loc: Location) { diff --git a/src/librustc_mir/dataflow/mod.rs b/src/librustc_mir/dataflow/mod.rs index 85458c7d684..98cd9c35d88 100644 --- a/src/librustc_mir/dataflow/mod.rs +++ b/src/librustc_mir/dataflow/mod.rs @@ -242,7 +242,7 @@ impl<'b, 'a: 'b, 'tcx: 'a, BD> PropagationContext<'b, 'a, 'tcx, BD> where BD: Bi { let sets = builder.flow_state.sets.for_block(bb_idx); debug_assert!(in_out.words().len() == sets.on_entry.words().len()); - in_out.clone_from(sets.on_entry); + in_out.overwrite(sets.on_entry); in_out.union(sets.gen_set); in_out.subtract(sets.kill_set); } diff --git a/src/librustc_mir/util/liveness.rs b/src/librustc_mir/util/liveness.rs index cfb1a2cd28b..34f8141141d 100644 --- a/src/librustc_mir/util/liveness.rs +++ b/src/librustc_mir/util/liveness.rs @@ -141,14 +141,14 @@ pub fn liveness_of_locals<'tcx>(mir: &Mir<'tcx>, mode: LivenessMode) -> Liveness for &successor in mir.basic_blocks()[b].terminator().successors() { bits.union(&ins[successor]); } - outs[b].clone_from(&bits); + outs[b].overwrite(&bits); // bits = use ∪ (bits - def) def_use[b].apply(&mut bits); // update bits on entry and flag if they have changed if ins[b] != bits { - ins[b].clone_from(&bits); + ins[b].overwrite(&bits); changed = true; } }