-
Notifications
You must be signed in to change notification settings - Fork 12.7k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
only compute liveness for variables whose types include regions #52115
only compute liveness for variables whose types include regions #52115
Conversation
The job Click to expand the log.
I'm a bot! I can only do what humans tell me to, so if this was not helpful or you have suggestions for improvements, please ping or otherwise contact |
@@ -201,9 +202,9 @@ pub(in borrow_check) fn compute_regions<'cx, 'gcx, 'tcx>( | |||
(regioncx, polonius_output, closure_region_requirements) | |||
} | |||
|
|||
fn dump_mir_results<'a, 'gcx, 'tcx>( | |||
fn dump_mir_results<'a, 'gcx, 'tcx, V: Idx>( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would probably not parameterize this function...
infcx: &InferCtxt<'a, 'gcx, 'tcx>, | ||
liveness: &LivenessResults, | ||
liveness: &LivenessResults<V>, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
...but instead here have LivenessResults<Local>
(at least to start -- later we'll change this I think)
@@ -392,7 +393,7 @@ impl ToRegionVid for RegionVid { | |||
} | |||
} | |||
|
|||
fn live_variable_set(regular: &LocalSet, drops: &LocalSet) -> String { | |||
fn live_variable_set<V: Idx>(regular: &LocalSet<V>, drops: &LocalSet<V>) -> String { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Similarly, for this first refactoring, we would have LocalSet<Local>
here -- the idea is that the liveness computation is generic over the index, but we as the users of it still want to compute the liveness of every MIR local variable to start
cx: &mut TypeChecker<'_, 'gcx, 'tcx>, | ||
mir: &Mir<'tcx>, | ||
liveness: &LivenessResults, | ||
liveness: &LivenessResults<V>, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Again, this would be LivenessResults<Local>
to start
@@ -54,16 +55,17 @@ pub(super) fn generate<'gcx, 'tcx>( | |||
} | |||
} | |||
|
|||
struct TypeLivenessGenerator<'gen, 'typeck, 'flow, 'gcx, 'tcx> | |||
struct TypeLivenessGenerator<'gen, 'typeck, 'flow, 'gcx, 'tcx, V> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Again, no need for V
here, as we are consuming the results
src/librustc_mir/util/liveness.rs
Outdated
|
||
/// This gives the result of the liveness analysis at the boundary of | ||
/// basic blocks. You can use `simulate_block` to obtain the | ||
/// intra-block results. | ||
pub struct LivenessResult { | ||
pub struct LivenessResult<V: Idx> { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We should probably add some kind of trait like LiveVariableMap
, which would look kind of like so:
trait LiveVariableMap {
type LiveVar;
fn from_local(&self, local: Local) -> Option<Self::LiveVar>;
fn from_live_var(&self, local: Self::LiveVar) -> Local;
}
We would also make an "identity map" type that we use for now:
struct IdentityMap;
impl LiveVariableMap for IdentityMap {
type LiveVar = Local;
fn from_local(&self, local: Local) -> Option<Local> {
Some(local)
}
fn from_live_var(&self, local: Self::LiveVar) -> Local {
local
}
}
src/librustc_mir/util/liveness.rs
Outdated
struct DefsUses { | ||
defs: LocalSet, | ||
uses: LocalSet, | ||
struct DefsUses<V: Idx> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This struct is going to need to take the &impl LiveVariableMap
and store it in a field (map
, say)
src/librustc_mir/util/liveness.rs
Outdated
impl LivenessResults { | ||
pub fn compute<'tcx>(mir: &Mir<'tcx>) -> LivenessResults { | ||
impl<V: Idx> LivenessResults<V> { | ||
pub fn compute<'tcx>(mir: &Mir<'tcx>) -> LivenessResults<V> { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This would also take a &impl LiveVariableMap<LiveVar = V>
src/librustc_mir/util/liveness.rs
Outdated
fn clear(&mut self) { | ||
self.uses.clear(); | ||
self.defs.clear(); | ||
} | ||
|
||
fn apply(&self, bits: &mut LocalSet) -> bool { | ||
fn apply(&self, bits: &mut LocalSet<V>) -> bool { | ||
bits.subtract(&self.defs) | bits.union(&self.uses) | ||
} | ||
|
This comment was marked as resolved.
This comment was marked as resolved.
Sorry, something went wrong.
@@ -388,12 +393,12 @@ fn block<'tcx>(mode: LivenessMode, b: &BasicBlockData<'tcx>, locals: usize) -> D | |||
visitor.defs_uses | |||
} | |||
|
|||
pub fn dump_mir<'a, 'tcx>( | |||
pub fn dump_mir<'a, 'tcx, V: Idx>( |
This comment was marked as resolved.
This comment was marked as resolved.
Sorry, something went wrong.
This comment was marked as resolved.
This comment was marked as resolved.
Sorry, something went wrong.
The job Click to expand the log.
I'm a bot! I can only do what humans tell me to, so if this was not helpful or you have suggestions for improvements, please ping or otherwise contact |
The job Click to expand the log.
I'm a bot! I can only do what humans tell me to, so if this was not helpful or you have suggestions for improvements, please ping or otherwise contact |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ok I have to run but here is a first round of feedback
@@ -33,10 +34,10 @@ use super::TypeChecker; | |||
/// | |||
/// NB. This computation requires normalization; therefore, it must be | |||
/// performed before | |||
pub(super) fn generate<'gcx, 'tcx>( | |||
pub(super) fn generate<'gcx, 'tcx, V: LiveVariableMap>( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think this file should be generic over V
...
src/librustc_mir/util/liveness.rs
Outdated
use rustc::mir::visit::MirVisitable; | ||
use std::path::{Path, PathBuf}; | ||
use std::fs; | ||
use rustc::ty::TyCtxt; | ||
use std::io::{self, Write}; | ||
use transform::MirSource; | ||
|
||
pub type LocalSet = IdxSetBuf<Local>; | ||
pub type LocalSet<V: LiveVariableMap> = IdxSetBuf<V::LiveVar>; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
is this giving a warning? If so, change V::LiveVar
to <V as LiveVariableMap>::LiveVar
and remove the bound (for better or worse, this compiles)
src/librustc_mir/util/liveness.rs
Outdated
@@ -80,18 +103,18 @@ pub struct LivenessMode { | |||
} | |||
|
|||
/// A combination of liveness results, used in NLL. | |||
pub struct LivenessResults { | |||
pub struct LivenessResults<V: LiveVariableMap> { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think I intended this to be just <V>
...
src/librustc_mir/util/liveness.rs
Outdated
} | ||
|
||
impl LivenessResults { | ||
pub fn compute<'tcx>(mir: &Mir<'tcx>) -> LivenessResults { | ||
impl<V: LiveVariableMap> LivenessResults<V> { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
...and here we would have impl<V, M: LiveVariableMap<LiveVar = V>
...
src/librustc_mir/util/liveness.rs
Outdated
impl LivenessResults { | ||
pub fn compute<'tcx>(mir: &Mir<'tcx>) -> LivenessResults { | ||
impl<V: LiveVariableMap> LivenessResults<V> { | ||
pub fn compute<'tcx>(mir: &Mir<'tcx>, map: &dyn LiveVariableMap<LiveVar = V>) -> LivenessResults<V::LiveVar> { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
and here
pub fn compute<'tcx>(mir: &Mir<'tcx>, map: &M) -> LivenessResults<V> {
src/librustc_mir/util/liveness.rs
Outdated
@@ -115,7 +138,7 @@ impl LivenessResults { | |||
/// Compute which local variables are live within the given function | |||
/// `mir`. The liveness mode `mode` determines what sorts of uses are | |||
/// considered to make a variable live (e.g., do drops count?). | |||
pub fn liveness_of_locals<'tcx>(mir: &Mir<'tcx>, mode: LivenessMode) -> LivenessResult { | |||
pub fn liveness_of_locals<'tcx, V: LiveVariableMap>(mir: &Mir<'tcx>, mode: LivenessMode) -> LivenessResult<V::LiveVar> { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this can just be V
then, I think
The job Click to expand the log.
I'm a bot! I can only do what humans tell me to, so if this was not helpful or you have suggestions for improvements, please ping or otherwise contact |
☔ The latest upstream changes (presumably #51987) made this pull request unmergeable. Please resolve the merge conflicts. |
src/librustc_mir/util/liveness.rs
Outdated
impl<V: LiveVariableMap> LivenessResults<V> { | ||
pub fn compute<'tcx>(mir: &Mir<'tcx>, map: &dyn LiveVariableMap<LiveVar = V>) -> LivenessResults<V::LiveVar> { | ||
impl<V, M: LiveVariableMap<LiveVar = V>> LivenessResults<V> { | ||
pub fn compute<'tcx>(mir: &Mir<'tcx>, map: &M) -> LivenessResults<V> { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would probably make this map: &impl LiveVariableMap<LiveVar = V>
and remove the explicit M
parameter altogether
src/librustc_mir/util/liveness.rs
Outdated
@@ -138,7 +138,7 @@ impl<V: LiveVariableMap> LivenessResults<V> { | |||
/// Compute which local variables are live within the given function | |||
/// `mir`. The liveness mode `mode` determines what sorts of uses are | |||
/// considered to make a variable live (e.g., do drops count?). | |||
pub fn liveness_of_locals<'tcx, V: LiveVariableMap>(mir: &Mir<'tcx>, mode: LivenessMode) -> LivenessResult<V::LiveVar> { | |||
pub fn liveness_of_locals<'tcx, V>(mir: &Mir<'tcx>, mode: LivenessMode) -> LivenessResult<V> { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this will presumably need the map
to be given to it as well
src/librustc_mir/util/liveness.rs
Outdated
@@ -138,7 +138,7 @@ impl<V: LiveVariableMap> LivenessResults<V> { | |||
/// Compute which local variables are live within the given function | |||
/// `mir`. The liveness mode `mode` determines what sorts of uses are | |||
/// considered to make a variable live (e.g., do drops count?). | |||
pub fn liveness_of_locals<'tcx, V: LiveVariableMap>(mir: &Mir<'tcx>, mode: LivenessMode) -> LivenessResult<V::LiveVar> { | |||
pub fn liveness_of_locals<'tcx, V>(mir: &Mir<'tcx>, mode: LivenessMode) -> LivenessResult<V> { | |||
let locals = mir.local_decls.len(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this variable represents the total number of variables we are computing liveness for. We may need to extend the LiveVariableMap
trait to include a num_variables(mir: &Mir<'tcx>)
method -- for the identity case, it would return mir.local_decls.len()
.
9ae372e
to
8ac931d
Compare
src/librustc/mir/mod.rs
Outdated
@@ -53,7 +53,7 @@ pub mod traversal; | |||
pub mod visit; | |||
|
|||
/// Types for locals | |||
type LocalDecls<'tcx> = IndexVec<Local, LocalDecl<'tcx>>; | |||
type LocalDecls<'tcx> = IndexVec<LocalWithRegion, LocalDecl<'tcx>>; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This should remain Local
! This is the full set of local declarations -- LocalWithRegion
is meant to be a subset of the full set of locals.
flow_inits: &'gen mut FlowAtLocation<MaybeInitializedPlaces<'flow, 'gcx, 'tcx>>, | ||
move_data: &'gen MoveData<'tcx>, | ||
drop_data: FxHashMap<Ty<'tcx>, DropData<'tcx>>, | ||
map: &'gen IdentityMap<'gen, 'tcx>, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah, I suspect this is the problem -- this should not be IdentityMap
, right? But rather LocalWithRegionMap
or whatever that type is called
We used to hardcode that we wanted the liveness of *all* variables. This can now be configured by selecting an alternative index type V and providing a (partial) map from locals to that new type V.
7147292
to
2255786
Compare
The job Click to expand the log.
I'm a bot! I can only do what humans tell me to, so if this was not helpful or you have suggestions for improvements, please ping or otherwise contact |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks great! Tidy errors though mean that we can't see the travis results.
src/librustc/mir/mod.rs
Outdated
@@ -2932,3 +2932,5 @@ impl<'tcx> TypeFoldable<'tcx> for Literal<'tcx> { | |||
} | |||
} | |||
} | |||
|
|||
newtype_index!(LocalWithRegion); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would expect this to live in the borrow_check
somewhere -- probably nll/liveness_map.rs
(See below)
src/librustc_mir/util/liveness.rs
Outdated
@@ -455,3 +544,42 @@ pub fn write_mir_fn<'a, 'tcx>( | |||
writeln!(w, "}}")?; | |||
Ok(()) | |||
} | |||
|
|||
crate struct NllLivenessMap { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would expect this to live in the nll code -- I'd probably put it in a new module nll/liveness_map.rs
along with the LocalWithRegion
index declaration.
Lots of interesting failures: https://travis-ci.org/rust-lang/rust/jobs/405945256#L1943 =) |
src/librustc_mir/util/liveness.rs
Outdated
|
||
pub type LocalSet = IdxSetBuf<Local>; | ||
pub type LocalSet<V> = IdxSetBuf<V>; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
oh, let's rename this to LiveVarSet<V>
-- it'd be nice to distinguish locals (all variables) from live variables (the set of variables we are computing liveness on). Maybe not the best name, but it works (and fits with e.g. LiveVariableMap
etc)
@bors try |
☀️ Test successful - status-travis |
The job Click to expand the log.
I'm a bot! I can only do what humans tell me to, so if this was not helpful or you have suggestions for improvements, please ping or otherwise contact |
The job Click to expand the log.
I'm a bot! I can only do what humans tell me to, so if this was not helpful or you have suggestions for improvements, please ping or otherwise contact |
@rust-timer build e5906f3e09c74cf6bd6fe86851a3bacd75fc1a42 |
Success: Queued e5906f3e09c74cf6bd6fe86851a3bacd75fc1a42 with parent c7cba3d, comparison URL. |
@Dylan-DPC those travis errors are basically a case of "working as expected". TBH, I suspect we could just remove those tests. They were early "bootstrap" tests of the liveness code but I think that the full set of ui/compile-fail tests are more interesting. The tests are failing though because the variables used in them do not have any regions in their types, and hence they no longer appear in the liveness results. Still, I'd suggest just removing |
The job Click to expand the log.
I'm a bot! I can only do what humans tell me to, so if this was not helpful or you have suggestions for improvements, please ping or otherwise contact |
Looks like a win, perf wise =) -80% for tuple-stress :) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks good, left a few nits (comments)
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your | ||
// option. This file may not be copied, modified, or distributed | ||
// except according to those terms. | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We should add a module doc comment here explaining what is going on. Something like this:
For the NLL computation, we need to compute liveness, but only for those local variables whose types contain regions. The others are not of interest to us. This file defines a new index type (LocalWithRegion
) that indexes into a list of "variables whose type contain regions". It also defines a map from Local
to LocalWithRegion
and vice versa -- this map can be given to the liveness code so that it only operates over variables with regions in their types, instead of all variables.
use rustc_data_structures::indexed_vec::Idx; | ||
use rustc::ty::TypeFoldable; | ||
|
||
crate struct NllLivenessMap { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Add comment:
--
Map between Local
and LocalWithRegion
indices: this map is supplied to the liveness code so that it will only analyze those variables whose types contain regions.
use rustc::ty::TypeFoldable; | ||
|
||
crate struct NllLivenessMap { | ||
pub from_local: IndexVec<Local, Option<LocalWithRegion>>, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Comment:
For each local variable, contains either None
(if the type has no regions) or Some(i)
with a suitable index.
|
||
crate struct NllLivenessMap { | ||
pub from_local: IndexVec<Local, Option<LocalWithRegion>>, | ||
pub to_local: IndexVec<LocalWithRegion, Local>, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Comment:
For each LocalWithRegion
, maps back to the original Local
index.
} | ||
|
||
impl NllLivenessMap { | ||
pub fn compute(mir: &Mir) -> Self { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Comment:
Iterates over the variables in Mir
and assigns each Local
whose type contains regions a LocalWithRegion
index. Returns a map for converting back and forth.
} | ||
} | ||
|
||
newtype_index!(LocalWithRegion); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Newline at end of file, probably, and a comment:
Index given to each local variable whose type contains a region.
The job Click to expand the log.
I'm a bot! I can only do what humans tell me to, so if this was not helpful or you have suggestions for improvements, please ping or otherwise contact |
@bors r+ p=1 High-priority NLL fix |
📌 Commit 0770ff0 has been approved by |
@bors p=20 |
…matsakis only compute liveness for variables whose types include regions Closes #52034 r? @nikomatsakis
☀️ Test successful - status-appveyor, status-travis |
[NLL] Remove `LiveVar` The `LiveVar` type (and related) made it harder to reason about the code. It seemed as an abstraction that didn't bring any useful concept to the reader (when transitioning from the RFC theory to the actual implementation code). It achieved a compactness in the vectors storing the def/use/drop information that was related only to the `LocalUseMap`. This PR went in the other direction and favored time over memory (but this decision can be easily reverted to the other side without reintroducing `LiveVar`). What this PR aims at is to clarify that there's no significant transformation between the MIR `Local` and the `LiveVar` (now refactored as `live_locals: Vec<Local>`): we're just filtering (not mapping) the entire group of `Local`s into a meaningful subset that we should perform the liveness analysis on. As a side note, there is no guarantee that the liveness analysis is performed only on (what the code calls) "live" variables, if the NLL facts are requested it will be performed on *any* variable so there can't be any assumptions on that regard. (Still, this PR didn't change the general naming convention to reduce the number of changes here and streamline the review process). **Acceptance criteria:** This PR attempts to do only a minor refactoring and not to change the logic so it can't have any performance impact, particularly, it can't lose any of the significant performance improvement achieved in the great work done in #52115. r? @nikomatsakis
…sper [NLL] Remove `LiveVar` The `LiveVar` type (and related) made it harder to reason about the code. It seemed as an abstraction that didn't bring any useful concept to the reader (when transitioning from the RFC theory to the actual implementation code). It achieved a compactness in the vectors storing the def/use/drop information that was related only to the `LocalUseMap`. This PR went in the other direction and favored time over memory (but this decision can be easily reverted to the other side without reintroducing `LiveVar`). What this PR aims at is to clarify that there's no significant transformation between the MIR `Local` and the `LiveVar` (now refactored as `live_locals: Vec<Local>`): we're just filtering (not mapping) the entire group of `Local`s into a meaningful subset that we should perform the liveness analysis on. As a side note, there is no guarantee that the liveness analysis is performed only on (what the code calls) "live" variables, if the NLL facts are requested it will be performed on *any* variable so there can't be any assumptions on that regard. (Still, this PR didn't change the general naming convention to reduce the number of changes here and streamline the review process). **Acceptance criteria:** This PR attempts to do only a minor refactoring and not to change the logic so it can't have any performance impact, particularly, it can't lose any of the significant performance improvement achieved in the great work done in #52115. r? @nikomatsakis
Closes #52034
r? @nikomatsakis