Skip to content
This repository was archived by the owner on May 28, 2025. It is now read-only.

Commit 7ef555d

Browse files
committed
Support non-trivial scalars in ConstProp.
1 parent 09ce0f6 commit 7ef555d

File tree

2 files changed

+30
-46
lines changed

2 files changed

+30
-46
lines changed

compiler/rustc_mir_dataflow/src/value_analysis.rs

Lines changed: 29 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -626,45 +626,36 @@ pub struct Map {
626626
}
627627

628628
impl Map {
629-
fn new() -> Self {
630-
Self {
629+
/// Returns a map that only tracks places whose type has scalar layout.
630+
///
631+
/// This is currently the only way to create a [`Map`]. The way in which the tracked places are
632+
/// chosen is an implementation detail and may not be relied upon (other than that their type
633+
/// are scalars).
634+
pub fn new<'tcx>(tcx: TyCtxt<'tcx>, body: &Body<'tcx>, value_limit: Option<usize>) -> Self {
635+
let mut map = Self {
631636
locals: IndexVec::new(),
632637
projections: FxHashMap::default(),
633638
places: IndexVec::new(),
634639
value_count: 0,
635640
inner_values: IndexVec::new(),
636641
inner_values_buffer: Vec::new(),
637-
}
638-
}
639-
640-
/// Returns a map that only tracks places whose type passes the filter.
641-
///
642-
/// This is currently the only way to create a [`Map`]. The way in which the tracked places are
643-
/// chosen is an implementation detail and may not be relied upon (other than that their type
644-
/// passes the filter).
645-
pub fn from_filter<'tcx>(
646-
tcx: TyCtxt<'tcx>,
647-
body: &Body<'tcx>,
648-
filter: impl Fn(Ty<'tcx>) -> bool,
649-
value_limit: Option<usize>,
650-
) -> Self {
651-
let mut map = Self::new();
642+
};
652643
let exclude = excluded_locals(body);
653-
map.register_with_filter(tcx, body, filter, exclude, value_limit);
644+
map.register(tcx, body, exclude, value_limit);
654645
debug!("registered {} places ({} nodes in total)", map.value_count, map.places.len());
655646
map
656647
}
657648

658-
/// Register all non-excluded places that pass the filter.
659-
fn register_with_filter<'tcx>(
649+
/// Register all non-excluded places that have scalar layout.
650+
fn register<'tcx>(
660651
&mut self,
661652
tcx: TyCtxt<'tcx>,
662653
body: &Body<'tcx>,
663-
filter: impl Fn(Ty<'tcx>) -> bool,
664654
exclude: BitSet<Local>,
665655
value_limit: Option<usize>,
666656
) {
667657
let mut worklist = VecDeque::with_capacity(value_limit.unwrap_or(body.local_decls.len()));
658+
let param_env = tcx.param_env_reveal_all_normalized(body.source.def_id());
668659

669660
// Start by constructing the places for each bare local.
670661
self.locals = IndexVec::from_elem(None, &body.local_decls);
@@ -679,7 +670,7 @@ impl Map {
679670
self.locals[local] = Some(place);
680671

681672
// And push the eventual children places to the worklist.
682-
self.register_children(tcx, place, decl.ty, &filter, &mut worklist);
673+
self.register_children(tcx, param_env, place, decl.ty, &mut worklist);
683674
}
684675

685676
// `place.elem1.elem2` with type `ty`.
@@ -702,7 +693,7 @@ impl Map {
702693
}
703694

704695
// And push the eventual children places to the worklist.
705-
self.register_children(tcx, place, ty, &filter, &mut worklist);
696+
self.register_children(tcx, param_env, place, ty, &mut worklist);
706697
}
707698

708699
// Pre-compute the tree of ValueIndex nested in each PlaceIndex.
@@ -732,42 +723,35 @@ impl Map {
732723
fn register_children<'tcx>(
733724
&mut self,
734725
tcx: TyCtxt<'tcx>,
726+
param_env: ty::ParamEnv<'tcx>,
735727
place: PlaceIndex,
736728
ty: Ty<'tcx>,
737-
filter: &impl Fn(Ty<'tcx>) -> bool,
738729
worklist: &mut VecDeque<(PlaceIndex, Option<TrackElem>, TrackElem, Ty<'tcx>)>,
739730
) {
740731
// Allocate a value slot if it doesn't have one, and the user requested one.
741-
if self.places[place].value_index.is_none() && filter(ty) {
732+
assert!(self.places[place].value_index.is_none());
733+
if tcx.layout_of(param_env.and(ty)).map_or(false, |layout| layout.abi.is_scalar()) {
742734
self.places[place].value_index = Some(self.value_count.into());
743735
self.value_count += 1;
744736
}
745737

746738
// For enums, directly create the `Discriminant`, as that's their main use.
747739
if ty.is_enum() {
748-
let discr_ty = ty.discriminant_ty(tcx);
749-
if filter(discr_ty) {
750-
let discr = *self
751-
.projections
752-
.entry((place, TrackElem::Discriminant))
753-
.or_insert_with(|| {
754-
// Prepend new child to the linked list.
755-
let next = self.places.push(PlaceInfo::new(Some(TrackElem::Discriminant)));
756-
self.places[next].next_sibling = self.places[place].first_child;
757-
self.places[place].first_child = Some(next);
758-
next
759-
});
760-
761-
// Allocate a value slot if it doesn't have one.
762-
if self.places[discr].value_index.is_none() {
763-
self.places[discr].value_index = Some(self.value_count.into());
764-
self.value_count += 1;
765-
}
766-
}
740+
// Prepend new child to the linked list.
741+
let discr = self.places.push(PlaceInfo::new(Some(TrackElem::Discriminant)));
742+
self.places[discr].next_sibling = self.places[place].first_child;
743+
self.places[place].first_child = Some(discr);
744+
let old = self.projections.insert((place, TrackElem::Discriminant), discr);
745+
assert!(old.is_none());
746+
747+
// Allocate a value slot if it doesn't have one.
748+
assert!(self.places[discr].value_index.is_none());
749+
self.places[discr].value_index = Some(self.value_count.into());
750+
self.value_count += 1;
767751
}
768752

769753
// Recurse with all fields of this place.
770-
iter_fields(ty, tcx, ty::ParamEnv::reveal_all(), |variant, field, ty| {
754+
iter_fields(ty, tcx, param_env, |variant, field, ty| {
771755
worklist.push_back((
772756
place,
773757
variant.map(TrackElem::Variant),

compiler/rustc_mir_transform/src/dataflow_const_prop.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ impl<'tcx> MirPass<'tcx> for DataflowConstProp {
5050
let place_limit = if tcx.sess.mir_opt_level() < 4 { Some(PLACE_LIMIT) } else { None };
5151

5252
// Decide which places to track during the analysis.
53-
let map = Map::from_filter(tcx, body, Ty::is_scalar, place_limit);
53+
let map = Map::new(tcx, body, place_limit);
5454

5555
// Perform the actual dataflow analysis.
5656
let analysis = ConstAnalysis::new(tcx, body, map);

0 commit comments

Comments
 (0)