Skip to content

Commit 3fa44ea

Browse files
committed
Split Map::register.
1 parent cea2e2e commit 3fa44ea

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
@@ -372,21 +372,20 @@ impl<'tcx> Map<'tcx> {
372372
inner_values: IndexVec::new(),
373373
inner_values_buffer: Vec::new(),
374374
};
375-
let exclude = excluded_locals(body);
376-
map.register(tcx, body, exclude, value_limit);
375+
map.register_locals(tcx, body);
376+
map.collect_places(tcx, body);
377+
map.propagate_assignments(tcx, body);
378+
map.create_values(tcx, body, value_limit);
379+
map.trim_useless_places();
377380
debug!("registered {} places ({} nodes in total)", map.value_count, map.places.len());
378381
map
379382
}
380383

381384
/// Register all non-excluded places that have scalar layout.
382385
#[tracing::instrument(level = "trace", skip(self, tcx, body))]
383-
fn register(
384-
&mut self,
385-
tcx: TyCtxt<'tcx>,
386-
body: &Body<'tcx>,
387-
exclude: DenseBitSet<Local>,
388-
value_limit: Option<usize>,
389-
) {
386+
fn register_locals(&mut self, tcx: TyCtxt<'tcx>, body: &Body<'tcx>) {
387+
let exclude = excluded_locals(body);
388+
390389
// Start by constructing the places for each bare local.
391390
for (local, decl) in body.local_decls.iter_enumerated() {
392391
if exclude.contains(local) {
@@ -401,23 +400,79 @@ impl<'tcx> Map<'tcx> {
401400
let place = self.places.push(PlaceInfo::new(decl.ty, None));
402401
self.locals[local] = Some(place);
403402
}
403+
}
404404

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

452-
// Create values for places whose type have scalar layout.
513+
/// Create values for places whose type have scalar layout.
514+
#[tracing::instrument(level = "trace", skip(self, tcx, body))]
515+
fn create_values(&mut self, tcx: TyCtxt<'tcx>, body: &Body<'tcx>, value_limit: Option<usize>) {
453516
let typing_env = body.typing_env(tcx);
454517
for place_info in self.places.iter_mut() {
455518
// The user requires a bound on the number of created values.
@@ -483,8 +546,11 @@ impl<'tcx> Map<'tcx> {
483546
self.cache_preorder_invoke(place);
484547
}
485548
}
549+
}
486550

487-
// Trim useless places.
551+
/// Trim useless places.
552+
#[tracing::instrument(level = "trace", skip(self))]
553+
fn trim_useless_places(&mut self) {
488554
for opt_place in self.locals.iter_mut() {
489555
if let Some(place) = *opt_place
490556
&& self.inner_values[place].is_empty()
@@ -497,7 +563,12 @@ impl<'tcx> Map<'tcx> {
497563
}
498564

499565
#[tracing::instrument(level = "trace", skip(self), ret)]
500-
fn register_place(&mut self, ty: Ty<'tcx>, base: PlaceIndex, elem: TrackElem) -> PlaceIndex {
566+
fn register_place_index(
567+
&mut self,
568+
ty: Ty<'tcx>,
569+
base: PlaceIndex,
570+
elem: TrackElem,
571+
) -> PlaceIndex {
501572
*self.projections.entry((base, elem)).or_insert_with(|| {
502573
let next = self.places.push(PlaceInfo::new(ty, Some(elem)));
503574
self.places[next].next_sibling = self.places[base].first_child;
@@ -506,6 +577,46 @@ impl<'tcx> Map<'tcx> {
506577
})
507578
}
508579

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

573646
impl<'tcx> Visitor<'tcx> for PlaceCollector<'_, 'tcx> {
@@ -577,51 +650,7 @@ impl<'tcx> Visitor<'tcx> for PlaceCollector<'_, 'tcx> {
577650
return;
578651
}
579652

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

0 commit comments

Comments
 (0)