Make LocalAnalizer visitor iterate instead of recurse
This commit is contained in:
parent
2bdaccbbcf
commit
0cfaa28bc5
@ -154,51 +154,62 @@ impl<'mir, 'a: 'mir, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>> Visitor<'tcx>
|
||||
context: PlaceContext,
|
||||
location: Location) {
|
||||
debug!("visit_place(place={:?}, context={:?})", place, context);
|
||||
let mut context = context;
|
||||
let cx = self.fx.cx;
|
||||
|
||||
if let mir::Place::Projection(ref proj) = *place {
|
||||
// Allow uses of projections that are ZSTs or from scalar fields.
|
||||
let is_consume = match context {
|
||||
PlaceContext::NonMutatingUse(NonMutatingUseContext::Copy) |
|
||||
PlaceContext::NonMutatingUse(NonMutatingUseContext::Move) => true,
|
||||
_ => false
|
||||
};
|
||||
if is_consume {
|
||||
let base_ty = proj.base.ty(self.fx.mir, cx.tcx());
|
||||
let base_ty = self.fx.monomorphize(&base_ty);
|
||||
place.iterate(|place_base, place_projections| {
|
||||
for proj in place_projections {
|
||||
// Allow uses of projections that are ZSTs or from scalar fields.
|
||||
let is_consume = match context {
|
||||
PlaceContext::NonMutatingUse(NonMutatingUseContext::Copy) |
|
||||
PlaceContext::NonMutatingUse(NonMutatingUseContext::Move) => true,
|
||||
_ => false
|
||||
};
|
||||
if is_consume {
|
||||
let base_ty = proj.base.ty(self.fx.mir, cx.tcx());
|
||||
let base_ty = self.fx.monomorphize(&base_ty);
|
||||
|
||||
// ZSTs don't require any actual memory access.
|
||||
let elem_ty = base_ty
|
||||
.projection_ty(cx.tcx(), &proj.elem)
|
||||
.ty;
|
||||
let elem_ty = self.fx.monomorphize(&elem_ty);
|
||||
if cx.layout_of(elem_ty).is_zst() {
|
||||
return;
|
||||
}
|
||||
|
||||
if let mir::ProjectionElem::Field(..) = proj.elem {
|
||||
let layout = cx.layout_of(base_ty.ty);
|
||||
if cx.is_backend_immediate(layout) || cx.is_backend_scalar_pair(layout) {
|
||||
// Recurse with the same context, instead of `Projection`,
|
||||
// potentially stopping at non-operand projections,
|
||||
// which would trigger `not_ssa` on locals.
|
||||
self.visit_place(&proj.base, context, location);
|
||||
// ZSTs don't require any actual memory access.
|
||||
let elem_ty = base_ty
|
||||
.projection_ty(cx.tcx(), &proj.elem)
|
||||
.ty;
|
||||
let elem_ty = self.fx.monomorphize(&elem_ty);
|
||||
if cx.layout_of(elem_ty).is_zst() {
|
||||
return;
|
||||
}
|
||||
|
||||
if let mir::ProjectionElem::Field(..) = proj.elem {
|
||||
let layout = cx.layout_of(base_ty.ty);
|
||||
if cx.is_backend_immediate(layout) || cx.is_backend_scalar_pair(layout) {
|
||||
// Recurse with the same context, instead of `Projection`,
|
||||
// potentially stopping at non-operand projections,
|
||||
// which would trigger `not_ssa` on locals.
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// A deref projection only reads the pointer, never needs the place.
|
||||
if let mir::ProjectionElem::Deref = proj.elem {
|
||||
return self.visit_place(
|
||||
&proj.base,
|
||||
PlaceContext::NonMutatingUse(NonMutatingUseContext::Copy),
|
||||
location
|
||||
);
|
||||
}
|
||||
|
||||
context = if context.is_mutating_use() {
|
||||
PlaceContext::MutatingUse(MutatingUseContext::Projection)
|
||||
} else {
|
||||
PlaceContext::NonMutatingUse(NonMutatingUseContext::Projection)
|
||||
};
|
||||
}
|
||||
|
||||
// A deref projection only reads the pointer, never needs the place.
|
||||
if let mir::ProjectionElem::Deref = proj.elem {
|
||||
return self.visit_place(
|
||||
&proj.base,
|
||||
PlaceContext::NonMutatingUse(NonMutatingUseContext::Copy),
|
||||
location
|
||||
);
|
||||
// Default base visit behavior
|
||||
if let mir::PlaceBase::Local(local) = place_base {
|
||||
self.visit_local(local, context, location);
|
||||
}
|
||||
}
|
||||
|
||||
self.super_place(place, context, location);
|
||||
});
|
||||
}
|
||||
|
||||
fn visit_local(&mut self,
|
||||
|
Loading…
x
Reference in New Issue
Block a user