Skip to content

Commit 0cfaa28

Browse files
committed
Make LocalAnalizer visitor iterate instead of recurse
1 parent 2bdaccb commit 0cfaa28

File tree

1 file changed

+48
-37
lines changed

1 file changed

+48
-37
lines changed

src/librustc_codegen_ssa/mir/analyze.rs

+48-37
Original file line numberDiff line numberDiff line change
@@ -154,51 +154,62 @@ impl<'mir, 'a: 'mir, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>> Visitor<'tcx>
154154
context: PlaceContext,
155155
location: Location) {
156156
debug!("visit_place(place={:?}, context={:?})", place, context);
157+
let mut context = context;
157158
let cx = self.fx.cx;
158159

159-
if let mir::Place::Projection(ref proj) = *place {
160-
// Allow uses of projections that are ZSTs or from scalar fields.
161-
let is_consume = match context {
162-
PlaceContext::NonMutatingUse(NonMutatingUseContext::Copy) |
163-
PlaceContext::NonMutatingUse(NonMutatingUseContext::Move) => true,
164-
_ => false
165-
};
166-
if is_consume {
167-
let base_ty = proj.base.ty(self.fx.mir, cx.tcx());
168-
let base_ty = self.fx.monomorphize(&base_ty);
169-
170-
// ZSTs don't require any actual memory access.
171-
let elem_ty = base_ty
172-
.projection_ty(cx.tcx(), &proj.elem)
173-
.ty;
174-
let elem_ty = self.fx.monomorphize(&elem_ty);
175-
if cx.layout_of(elem_ty).is_zst() {
176-
return;
177-
}
178-
179-
if let mir::ProjectionElem::Field(..) = proj.elem {
180-
let layout = cx.layout_of(base_ty.ty);
181-
if cx.is_backend_immediate(layout) || cx.is_backend_scalar_pair(layout) {
182-
// Recurse with the same context, instead of `Projection`,
183-
// potentially stopping at non-operand projections,
184-
// which would trigger `not_ssa` on locals.
185-
self.visit_place(&proj.base, context, location);
160+
place.iterate(|place_base, place_projections| {
161+
for proj in place_projections {
162+
// Allow uses of projections that are ZSTs or from scalar fields.
163+
let is_consume = match context {
164+
PlaceContext::NonMutatingUse(NonMutatingUseContext::Copy) |
165+
PlaceContext::NonMutatingUse(NonMutatingUseContext::Move) => true,
166+
_ => false
167+
};
168+
if is_consume {
169+
let base_ty = proj.base.ty(self.fx.mir, cx.tcx());
170+
let base_ty = self.fx.monomorphize(&base_ty);
171+
172+
// ZSTs don't require any actual memory access.
173+
let elem_ty = base_ty
174+
.projection_ty(cx.tcx(), &proj.elem)
175+
.ty;
176+
let elem_ty = self.fx.monomorphize(&elem_ty);
177+
if cx.layout_of(elem_ty).is_zst() {
186178
return;
187179
}
180+
181+
if let mir::ProjectionElem::Field(..) = proj.elem {
182+
let layout = cx.layout_of(base_ty.ty);
183+
if cx.is_backend_immediate(layout) || cx.is_backend_scalar_pair(layout) {
184+
// Recurse with the same context, instead of `Projection`,
185+
// potentially stopping at non-operand projections,
186+
// which would trigger `not_ssa` on locals.
187+
continue;
188+
}
189+
}
188190
}
189-
}
190191

191-
// A deref projection only reads the pointer, never needs the place.
192-
if let mir::ProjectionElem::Deref = proj.elem {
193-
return self.visit_place(
194-
&proj.base,
195-
PlaceContext::NonMutatingUse(NonMutatingUseContext::Copy),
196-
location
197-
);
192+
// A deref projection only reads the pointer, never needs the place.
193+
if let mir::ProjectionElem::Deref = proj.elem {
194+
return self.visit_place(
195+
&proj.base,
196+
PlaceContext::NonMutatingUse(NonMutatingUseContext::Copy),
197+
location
198+
);
199+
}
200+
201+
context = if context.is_mutating_use() {
202+
PlaceContext::MutatingUse(MutatingUseContext::Projection)
203+
} else {
204+
PlaceContext::NonMutatingUse(NonMutatingUseContext::Projection)
205+
};
198206
}
199-
}
200207

201-
self.super_place(place, context, location);
208+
// Default base visit behavior
209+
if let mir::PlaceBase::Local(local) = place_base {
210+
self.visit_local(local, context, location);
211+
}
212+
});
202213
}
203214

204215
fn visit_local(&mut self,

0 commit comments

Comments
 (0)