Skip to content

Commit 1f44202

Browse files
committed
Split Map::register.
1 parent a4736f3 commit 1f44202

File tree

1 file changed

+144
-115
lines changed

1 file changed

+144
-115
lines changed

compiler/rustc_mir_dataflow/src/value_analysis.rs

Lines changed: 144 additions & 115 deletions
Original file line numberDiff line numberDiff line change
@@ -370,21 +370,20 @@ impl<'tcx> Map<'tcx> {
370370
inner_values: IndexVec::new(),
371371
inner_values_buffer: Vec::new(),
372372
};
373-
let exclude = excluded_locals(body);
374-
map.register(tcx, body, exclude, value_limit);
373+
map.register_locals(tcx, body);
374+
map.collect_places(tcx, body);
375+
map.propagate_assignments(tcx, body);
376+
map.create_values(tcx, body, value_limit);
377+
map.trim_useless_places();
375378
debug!("registered {} places ({} nodes in total)", map.value_count, map.places.len());
376379
map
377380
}
378381

379382
/// Register all non-excluded places that have scalar layout.
380383
#[tracing::instrument(level = "trace", skip(self, tcx, body))]
381-
fn register(
382-
&mut self,
383-
tcx: TyCtxt<'tcx>,
384-
body: &Body<'tcx>,
385-
exclude: DenseBitSet<Local>,
386-
value_limit: Option<usize>,
387-
) {
384+
fn register_locals(&mut self, tcx: TyCtxt<'tcx>, body: &Body<'tcx>) {
385+
let exclude = excluded_locals(body);
386+
388387
// Start by constructing the places for each bare local.
389388
for (local, decl) in body.local_decls.iter_enumerated() {
390389
if exclude.contains(local) {
@@ -399,23 +398,79 @@ impl<'tcx> Map<'tcx> {
399398
let place = self.places.push(PlaceInfo::new(decl.ty, None));
400399
self.locals[local] = Some(place);
401400
}
401+
}
402402

403-
// Collect syntactic places and assignments between them.
404-
let mut collector =
405-
PlaceCollector { tcx, body, map: self, assignments: Default::default() };
403+
/// Collect syntactic places from body, and create `PlaceIndex` for them.
404+
#[tracing::instrument(level = "trace", skip(self, tcx, body))]
405+
fn collect_places(&mut self, tcx: TyCtxt<'tcx>, body: &Body<'tcx>) {
406+
let mut collector = PlaceCollector { tcx, body, map: self };
406407
collector.visit_body(body);
407-
let PlaceCollector { mut assignments, .. } = collector;
408-
409-
// Just collecting syntactic places is not enough. We may need to propagate this pattern:
410-
// _1 = (const 5u32, const 13i64);
411-
// _2 = _1;
412-
// _3 = (_2.0 as u32);
413-
//
414-
// `_1.0` does not appear, but we still need to track it. This is achieved by propagating
415-
// projections from assignments. We recorded an assignment between `_2` and `_1`, so we
416-
// want `_1` and `_2` to have the same sub-places.
417-
//
418-
// This is what this fixpoint loop does. While we are still creating places, run through
408+
}
409+
410+
/// Just collecting syntactic places is not enough. We may need to propagate this pattern:
411+
/// _1 = (const 5u32, const 13i64);
412+
/// _2 = _1;
413+
/// _3 = (_2.0 as u32);
414+
///
415+
/// `_1.0` does not appear, but we still need to track it. This is achieved by propagating
416+
/// projections from assignments. We recorded an assignment between `_2` and `_1`, so we
417+
/// want `_1` and `_2` to have the same sub-places.
418+
#[tracing::instrument(level = "trace", skip(self, tcx, body))]
419+
fn propagate_assignments(&mut self, tcx: TyCtxt<'tcx>, body: &Body<'tcx>) {
420+
// Collect syntactic places and assignments between them.
421+
let mut assignments = FxIndexSet::default();
422+
423+
for bbdata in body.basic_blocks.iter() {
424+
for stmt in bbdata.statements.iter() {
425+
let Some((lhs, rhs)) = stmt.kind.as_assign() else { continue };
426+
match rhs {
427+
Rvalue::Use(Operand::Move(rhs) | Operand::Copy(rhs))
428+
| Rvalue::CopyForDeref(rhs) => {
429+
let Some(lhs) = self.register_place(tcx, body, *lhs) else { continue };
430+
let Some(rhs) = self.register_place(tcx, body, *rhs) else { continue };
431+
assignments.insert((lhs, rhs));
432+
}
433+
Rvalue::Aggregate(kind, fields) => {
434+
let Some(mut lhs) = self.register_place(tcx, body, *lhs) else { continue };
435+
match **kind {
436+
// Do not propagate unions.
437+
AggregateKind::Adt(_, _, _, _, Some(_)) => continue,
438+
AggregateKind::Adt(_, variant, _, _, None) => {
439+
let ty = self.places[lhs].ty;
440+
if ty.is_enum() {
441+
lhs = self.register_place_index(
442+
ty,
443+
lhs,
444+
TrackElem::Variant(variant),
445+
);
446+
}
447+
}
448+
AggregateKind::RawPtr(..)
449+
| AggregateKind::Array(_)
450+
| AggregateKind::Tuple
451+
| AggregateKind::Closure(..)
452+
| AggregateKind::Coroutine(..)
453+
| AggregateKind::CoroutineClosure(..) => {}
454+
}
455+
for (index, field) in fields.iter_enumerated() {
456+
if let Some(rhs) = field.place()
457+
&& let Some(rhs) = self.register_place(tcx, body, rhs)
458+
{
459+
let lhs = self.register_place_index(
460+
self.places[rhs].ty,
461+
lhs,
462+
TrackElem::Field(index),
463+
);
464+
assignments.insert((lhs, rhs));
465+
}
466+
}
467+
}
468+
_ => {}
469+
}
470+
}
471+
}
472+
473+
// This is a fixpoint loop does. While we are still creating places, run through
419474
// all the assignments, and register places for children.
420475
let mut num_places = 0;
421476
while num_places < self.places.len() {
@@ -428,8 +483,11 @@ impl<'tcx> Map<'tcx> {
428483
let mut child = self.places[lhs].first_child;
429484
while let Some(lhs_child) = child {
430485
let PlaceInfo { ty, proj_elem, next_sibling, .. } = self.places[lhs_child];
431-
let rhs_child =
432-
self.register_place(ty, rhs, proj_elem.expect("child is not a projection"));
486+
let rhs_child = self.register_place_index(
487+
ty,
488+
rhs,
489+
proj_elem.expect("child is not a projection"),
490+
);
433491
assignments.insert((lhs_child, rhs_child));
434492
child = next_sibling;
435493
}
@@ -438,16 +496,21 @@ impl<'tcx> Map<'tcx> {
438496
let mut child = self.places[rhs].first_child;
439497
while let Some(rhs_child) = child {
440498
let PlaceInfo { ty, proj_elem, next_sibling, .. } = self.places[rhs_child];
441-
let lhs_child =
442-
self.register_place(ty, lhs, proj_elem.expect("child is not a projection"));
499+
let lhs_child = self.register_place_index(
500+
ty,
501+
lhs,
502+
proj_elem.expect("child is not a projection"),
503+
);
443504
assignments.insert((lhs_child, rhs_child));
444505
child = next_sibling;
445506
}
446507
}
447508
}
448-
drop(assignments);
509+
}
449510

450-
// Create values for places whose type have scalar layout.
511+
/// Create values for places whose type have scalar layout.
512+
#[tracing::instrument(level = "trace", skip(self, tcx, body))]
513+
fn create_values(&mut self, tcx: TyCtxt<'tcx>, body: &Body<'tcx>, value_limit: Option<usize>) {
451514
let typing_env = body.typing_env(tcx);
452515
for place_info in self.places.iter_mut() {
453516
// The user requires a bound on the number of created values.
@@ -481,8 +544,11 @@ impl<'tcx> Map<'tcx> {
481544
self.cache_preorder_invoke(place);
482545
}
483546
}
547+
}
484548

485-
// Trim useless places.
549+
/// Trim useless places.
550+
#[tracing::instrument(level = "trace", skip(self))]
551+
fn trim_useless_places(&mut self) {
486552
for opt_place in self.locals.iter_mut() {
487553
if let Some(place) = *opt_place
488554
&& self.inner_values[place].is_empty()
@@ -495,7 +561,12 @@ impl<'tcx> Map<'tcx> {
495561
}
496562

497563
#[tracing::instrument(level = "trace", skip(self), ret)]
498-
fn register_place(&mut self, ty: Ty<'tcx>, base: PlaceIndex, elem: TrackElem) -> PlaceIndex {
564+
fn register_place_index(
565+
&mut self,
566+
ty: Ty<'tcx>,
567+
base: PlaceIndex,
568+
elem: TrackElem,
569+
) -> PlaceIndex {
499570
*self.projections.entry((base, elem)).or_insert_with(|| {
500571
let next = self.places.push(PlaceInfo::new(ty, Some(elem)));
501572
self.places[next].next_sibling = self.places[base].first_child;
@@ -504,6 +575,46 @@ impl<'tcx> Map<'tcx> {
504575
})
505576
}
506577

578+
#[tracing::instrument(level = "trace", skip(self, tcx, body))]
579+
fn register_place(
580+
&mut self,
581+
tcx: TyCtxt<'tcx>,
582+
body: &Body<'tcx>,
583+
place: Place<'tcx>,
584+
) -> Option<PlaceIndex> {
585+
// Create a place for this projection.
586+
let mut place_index = self.locals[place.local]?;
587+
let mut ty = PlaceTy::from_ty(body.local_decls[place.local].ty);
588+
tracing::trace!(?place_index, ?ty);
589+
590+
if let ty::Ref(_, ref_ty, _) | ty::RawPtr(ref_ty, _) = ty.ty.kind()
591+
&& let ty::Slice(..) = ref_ty.kind()
592+
{
593+
self.register_place_index(tcx.types.usize, place_index, TrackElem::DerefLen);
594+
} else if ty.ty.is_enum() {
595+
let discriminant_ty = ty.ty.discriminant_ty(tcx);
596+
self.register_place_index(discriminant_ty, place_index, TrackElem::Discriminant);
597+
}
598+
599+
for proj in place.projection {
600+
let track_elem = proj.try_into().ok()?;
601+
ty = ty.projection_ty(tcx, proj);
602+
place_index = self.register_place_index(ty.ty, place_index, track_elem);
603+
tracing::trace!(?proj, ?place_index, ?ty);
604+
605+
if let ty::Ref(_, ref_ty, _) | ty::RawPtr(ref_ty, _) = ty.ty.kind()
606+
&& let ty::Slice(..) = ref_ty.kind()
607+
{
608+
self.register_place_index(tcx.types.usize, place_index, TrackElem::DerefLen);
609+
} else if ty.ty.is_enum() {
610+
let discriminant_ty = ty.ty.discriminant_ty(tcx);
611+
self.register_place_index(discriminant_ty, place_index, TrackElem::Discriminant);
612+
}
613+
}
614+
615+
Some(place_index)
616+
}
617+
507618
/// Precompute the list of values inside `root` and store it inside
508619
/// as a slice within `inner_values_buffer`.
509620
fn cache_preorder_invoke(&mut self, root: PlaceIndex) {
@@ -528,44 +639,6 @@ struct PlaceCollector<'a, 'tcx> {
528639
tcx: TyCtxt<'tcx>,
529640
body: &'a Body<'tcx>,
530641
map: &'a mut Map<'tcx>,
531-
assignments: FxIndexSet<(PlaceIndex, PlaceIndex)>,
532-
}
533-
534-
impl<'tcx> PlaceCollector<'_, 'tcx> {
535-
#[tracing::instrument(level = "trace", skip(self))]
536-
fn register_place(&mut self, place: Place<'tcx>) -> Option<PlaceIndex> {
537-
// Create a place for this projection.
538-
let mut place_index = self.map.locals[place.local]?;
539-
let mut ty = PlaceTy::from_ty(self.body.local_decls[place.local].ty);
540-
tracing::trace!(?place_index, ?ty);
541-
542-
if let ty::Ref(_, ref_ty, _) | ty::RawPtr(ref_ty, _) = ty.ty.kind()
543-
&& let ty::Slice(..) = ref_ty.kind()
544-
{
545-
self.map.register_place(self.tcx.types.usize, place_index, TrackElem::DerefLen);
546-
} else if ty.ty.is_enum() {
547-
let discriminant_ty = ty.ty.discriminant_ty(self.tcx);
548-
self.map.register_place(discriminant_ty, place_index, TrackElem::Discriminant);
549-
}
550-
551-
for proj in place.projection {
552-
let track_elem = proj.try_into().ok()?;
553-
ty = ty.projection_ty(self.tcx, proj);
554-
place_index = self.map.register_place(ty.ty, place_index, track_elem);
555-
tracing::trace!(?proj, ?place_index, ?ty);
556-
557-
if let ty::Ref(_, ref_ty, _) | ty::RawPtr(ref_ty, _) = ty.ty.kind()
558-
&& let ty::Slice(..) = ref_ty.kind()
559-
{
560-
self.map.register_place(self.tcx.types.usize, place_index, TrackElem::DerefLen);
561-
} else if ty.ty.is_enum() {
562-
let discriminant_ty = ty.ty.discriminant_ty(self.tcx);
563-
self.map.register_place(discriminant_ty, place_index, TrackElem::Discriminant);
564-
}
565-
}
566-
567-
Some(place_index)
568-
}
569642
}
570643

571644
impl<'tcx> Visitor<'tcx> for PlaceCollector<'_, 'tcx> {
@@ -575,51 +648,7 @@ impl<'tcx> Visitor<'tcx> for PlaceCollector<'_, 'tcx> {
575648
return;
576649
}
577650

578-
self.register_place(*place);
579-
}
580-
581-
fn visit_assign(&mut self, lhs: &Place<'tcx>, rhs: &Rvalue<'tcx>, location: Location) {
582-
self.super_assign(lhs, rhs, location);
583-
584-
match rhs {
585-
Rvalue::Use(Operand::Move(rhs) | Operand::Copy(rhs)) | Rvalue::CopyForDeref(rhs) => {
586-
let Some(lhs) = self.register_place(*lhs) else { return };
587-
let Some(rhs) = self.register_place(*rhs) else { return };
588-
self.assignments.insert((lhs, rhs));
589-
}
590-
Rvalue::Aggregate(kind, fields) => {
591-
let Some(mut lhs) = self.register_place(*lhs) else { return };
592-
match **kind {
593-
// Do not propagate unions.
594-
AggregateKind::Adt(_, _, _, _, Some(_)) => return,
595-
AggregateKind::Adt(_, variant, _, _, None) => {
596-
let ty = self.map.places[lhs].ty;
597-
if ty.is_enum() {
598-
lhs = self.map.register_place(ty, lhs, TrackElem::Variant(variant));
599-
}
600-
}
601-
AggregateKind::RawPtr(..)
602-
| AggregateKind::Array(_)
603-
| AggregateKind::Tuple
604-
| AggregateKind::Closure(..)
605-
| AggregateKind::Coroutine(..)
606-
| AggregateKind::CoroutineClosure(..) => {}
607-
}
608-
for (index, field) in fields.iter_enumerated() {
609-
if let Some(rhs) = field.place()
610-
&& let Some(rhs) = self.register_place(rhs)
611-
{
612-
let lhs = self.map.register_place(
613-
self.map.places[rhs].ty,
614-
lhs,
615-
TrackElem::Field(index),
616-
);
617-
self.assignments.insert((lhs, rhs));
618-
}
619-
}
620-
}
621-
_ => {}
622-
}
651+
self.map.register_place(self.tcx, self.body, *place);
623652
}
624653
}
625654

0 commit comments

Comments
 (0)