Skip to content
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

[nll] optimize tuple-stress benchmark by skipping visit of types that do not have regions #52027

Closed
nikomatsakis opened this issue Jul 3, 2018 · 1 comment
Assignees
Labels
E-mentor Call for participation: This issue has a mentor. Use #t-compiler/help on Zulip for discussion. NLL-performant Working towards the "performance is good" goal

Comments

@nikomatsakis
Copy link
Contributor

The tuple-stress benchmark appears to be ridiculously slow with NLL. Profiling suggests that the majority of costs come from the liveness constraint generation code:

pub(super) fn generate<'gcx, 'tcx>(
cx: &mut TypeChecker<'_, 'gcx, 'tcx>,
mir: &Mir<'tcx>,
liveness: &LivenessResults,
flow_inits: &mut FlowAtLocation<MaybeInitializedPlaces<'_, 'gcx, 'tcx>>,
move_data: &MoveData<'tcx>,
) {

Specifically, the vast majority of samples (50%) occur in the push_type_live_constraint function:

fn push_type_live_constraint<T>(
cx: &mut TypeChecker<'_, 'gcx, 'tcx>,
value: T,
location: Location,
) where
T: TypeFoldable<'tcx>,

This function primarily consists of a walk over all the free regions within a type:

cx.tcx().for_each_free_region(&value, |live_region| {
cx.constraints.liveness_set.push((live_region, location));
});

However, the types in question don't really involve regions (they are things like (u32, f64, u32) etc). It turns out that we have a "flags" mechanism that tracks the content of types, designed for just such a purpose. This should allow us to quickly skip. The flags are defined here, using the bitflags! macro:

rust/src/librustc/ty/mod.rs

Lines 418 to 419 in 860d169

bitflags! {
pub struct TypeFlags: u32 {

The flag we are interested in HAS_FREE_REGIONS:

rust/src/librustc/ty/mod.rs

Lines 432 to 434 in 860d169

/// Does this have any region that "appears free" in the type?
/// Basically anything but `ReLateBound` and `ReErased`.
const HAS_FREE_REGIONS = 1 << 6;

We should be able to optimize the for_each_free_region to consult this flag and quickly skip past types that do not contain any regions. for_each_free_region is defined here:

pub fn for_each_free_region<T,F>(self,
value: &T,
callback: F)
where F: FnMut(ty::Region<'tcx>),
T: TypeFoldable<'tcx>,

It uses a "type visitor" to do its work:

impl<'tcx, F> TypeVisitor<'tcx> for RegionVisitor<F>
where F : FnMut(ty::Region<'tcx>)

we want to add callback for the case of visiting types which will check this flag. Something like the following ought to do it:

fn visit_ty(&mut self, ty: Ty<'tcx>) -> bool {
  if ty.flags.intersects(HAS_FREE_REGIONS) {
    self.super_ty(ty)
  } else {
    false // keep visiting
  }
}
@nikomatsakis nikomatsakis added I-nominated E-mentor Call for participation: This issue has a mentor. Use #t-compiler/help on Zulip for discussion. NLL-performant Working towards the "performance is good" goal labels Jul 3, 2018
@nikomatsakis nikomatsakis changed the title [nll] optimize tuple-stress benchmark [nll] optimize tuple-stress benchmark by skipping visit of types that do not have regions Jul 3, 2018
@nikomatsakis nikomatsakis added this to the Rust 2018 Preview 2 milestone Jul 3, 2018
@lqd lqd self-assigned this Jul 3, 2018
@nnethercote
Copy link
Contributor

FWIW, I think the first code snippet in the above description should be this:

self.liveness
.regular
.simulate_block(self.mir, bb, |location, live_locals| {
for live_local in live_locals.iter() {
let live_local_ty = self.mir.local_decls[live_local].ty;
Self::push_type_live_constraint(&mut self.cx, live_local_ty, location);
}
});

bors added a commit that referenced this issue Jul 7, 2018
NLL Liveness: Skip regionless types when visiting free regions

The tuple-stress benchmark exercises the liveness constraint generation code for types which do not have regions

Closes #52027
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
E-mentor Call for participation: This issue has a mentor. Use #t-compiler/help on Zulip for discussion. NLL-performant Working towards the "performance is good" goal
Projects
None yet
Development

No branches or pull requests

3 participants