Skip to content

Allow more MIR SROA #144543

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Jul 28, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 8 additions & 28 deletions compiler/rustc_mir_transform/src/sroa.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use rustc_abi::{FIRST_VARIANT, FieldIdx};
use rustc_abi::FieldIdx;
use rustc_data_structures::flat_map_in_place::FlatMapInPlace;
use rustc_hir::LangItem;
use rustc_index::IndexVec;
Expand Down Expand Up @@ -32,7 +32,7 @@ impl<'tcx> crate::MirPass<'tcx> for ScalarReplacementOfAggregates {
let typing_env = body.typing_env(tcx);
loop {
debug!(?excluded);
let escaping = escaping_locals(tcx, typing_env, &excluded, body);
let escaping = escaping_locals(tcx, &excluded, body);
debug!(?escaping);
let replacements = compute_flattening(tcx, typing_env, body, escaping);
debug!(?replacements);
Expand Down Expand Up @@ -64,39 +64,19 @@ impl<'tcx> crate::MirPass<'tcx> for ScalarReplacementOfAggregates {
/// client code.
fn escaping_locals<'tcx>(
tcx: TyCtxt<'tcx>,
typing_env: ty::TypingEnv<'tcx>,
excluded: &DenseBitSet<Local>,
body: &Body<'tcx>,
) -> DenseBitSet<Local> {
let is_excluded_ty = |ty: Ty<'tcx>| {
if ty.is_union() || ty.is_enum() {
return true;
}
if let ty::Adt(def, _args) = ty.kind() {
if def.repr().simd() {
// Exclude #[repr(simd)] types so that they are not de-optimized into an array
return true;
}
if tcx.is_lang_item(def.did(), LangItem::DynMetadata) {
// codegen wants to see the `DynMetadata<T>`,
// not the inner reference-to-opaque-type.
return true;
}
// We already excluded unions and enums, so this ADT must have one variant
let variant = def.variant(FIRST_VARIANT);
if variant.fields.len() > 1 {
// If this has more than one field, it cannot be a wrapper that only provides a
// niche, so we do not want to automatically exclude it.
return false;
}
let Ok(layout) = tcx.layout_of(typing_env.as_query_input(ty)) else {
// We can't get the layout
return true;
};
if layout.layout.largest_niche().is_some() {
// This type has a niche
return true;
}
if let ty::Adt(def, _args) = ty.kind()
&& tcx.is_lang_item(def.did(), LangItem::DynMetadata)
{
// codegen wants to see the `DynMetadata<T>`,
// not the inner reference-to-opaque-type.
return true;
}
// Default for non-ADTs
false
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -64,9 +64,8 @@
+ let mut _45: &mut std::future::Ready<()>;
+ let mut _46: &mut std::pin::Pin<&mut std::future::Ready<()>>;
+ scope 14 (inlined <Pin<&mut std::future::Ready<()>> as DerefMut>::deref_mut) {
+ let mut _47: std::pin::Pin<&mut std::future::Ready<()>>;
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

annot: See how this Pin wrapper is now removed, when it previously couldn't be.

+ scope 15 (inlined Pin::<&mut std::future::Ready<()>>::as_mut) {
+ let mut _48: &mut &mut std::future::Ready<()>;
+ let mut _47: &mut &mut std::future::Ready<()>;
+ scope 16 (inlined Pin::<&mut std::future::Ready<()>>::new_unchecked) {
+ }
+ scope 18 (inlined <&mut std::future::Ready<()> as DerefMut>::deref_mut) {
Expand All @@ -76,15 +75,15 @@
+ }
+ }
+ scope 19 (inlined Option::<()>::take) {
+ let mut _49: std::option::Option<()>;
+ let mut _48: std::option::Option<()>;
+ scope 20 (inlined std::mem::replace::<Option<()>>) {
+ scope 21 {
+ }
+ }
+ }
+ scope 22 (inlined #[track_caller] Option::<()>::expect) {
+ let mut _50: isize;
+ let mut _51: !;
+ let mut _49: isize;
+ let mut _50: !;
+ scope 23 {
+ }
+ }
Expand Down Expand Up @@ -229,28 +228,25 @@
+ StorageDead(_24);
+ StorageLive(_45);
+ StorageLive(_46);
+ StorageLive(_51);
+ StorageLive(_50);
+ StorageLive(_42);
+ StorageLive(_43);
+ StorageLive(_44);
+ _46 = &mut _19;
+ StorageLive(_47);
+ StorageLive(_48);
+ _48 = &mut (_19.0: &mut std::future::Ready<()>);
+ _47 = &mut (_19.0: &mut std::future::Ready<()>);
+ _45 = copy (_19.0: &mut std::future::Ready<()>);
+ StorageDead(_48);
+ _47 = Pin::<&mut std::future::Ready<()>> { pointer: copy _45 };
+ StorageDead(_47);
+ _44 = &mut ((*_45).0: std::option::Option<()>);
+ StorageLive(_49);
+ _49 = Option::<()>::None;
+ StorageLive(_48);
+ _48 = Option::<()>::None;
+ _43 = copy ((*_45).0: std::option::Option<()>);
+ ((*_45).0: std::option::Option<()>) = copy _49;
+ StorageDead(_49);
+ ((*_45).0: std::option::Option<()>) = copy _48;
+ StorageDead(_48);
+ StorageDead(_44);
+ StorageLive(_50);
+ _50 = discriminant(_43);
+ switchInt(move _50) -> [0: bb11, 1: bb12, otherwise: bb5];
+ StorageLive(_49);
+ _49 = discriminant(_43);
+ switchInt(move _49) -> [0: bb11, 1: bb12, otherwise: bb5];
}
+
+ bb5: {
Expand Down Expand Up @@ -313,16 +309,16 @@
+ }
+
+ bb11: {
+ _51 = option::expect_failed(const "`Ready` polled after completion") -> unwind unreachable;
+ _50 = option::expect_failed(const "`Ready` polled after completion") -> unwind unreachable;
+ }
+
+ bb12: {
+ _42 = move ((_43 as Some).0: ());
+ StorageDead(_50);
+ StorageDead(_49);
+ StorageDead(_43);
+ _18 = Poll::<()>::Ready(move _42);
+ StorageDead(_42);
+ StorageDead(_51);
+ StorageDead(_50);
+ StorageDead(_46);
+ StorageDead(_45);
+ StorageDead(_22);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -66,9 +66,8 @@
+ let mut _47: &mut std::future::Ready<()>;
+ let mut _48: &mut std::pin::Pin<&mut std::future::Ready<()>>;
+ scope 14 (inlined <Pin<&mut std::future::Ready<()>> as DerefMut>::deref_mut) {
+ let mut _49: std::pin::Pin<&mut std::future::Ready<()>>;
+ scope 15 (inlined Pin::<&mut std::future::Ready<()>>::as_mut) {
+ let mut _50: &mut &mut std::future::Ready<()>;
+ let mut _49: &mut &mut std::future::Ready<()>;
+ scope 16 (inlined Pin::<&mut std::future::Ready<()>>::new_unchecked) {
+ }
+ scope 18 (inlined <&mut std::future::Ready<()> as DerefMut>::deref_mut) {
Expand All @@ -78,15 +77,15 @@
+ }
+ }
+ scope 19 (inlined Option::<()>::take) {
+ let mut _51: std::option::Option<()>;
+ let mut _50: std::option::Option<()>;
+ scope 20 (inlined std::mem::replace::<Option<()>>) {
+ scope 21 {
+ }
+ }
+ }
+ scope 22 (inlined #[track_caller] Option::<()>::expect) {
+ let mut _52: isize;
+ let mut _53: !;
+ let mut _51: isize;
+ let mut _52: !;
+ scope 23 {
+ }
+ }
Expand Down Expand Up @@ -246,28 +245,25 @@
+ StorageDead(_24);
+ StorageLive(_47);
+ StorageLive(_48);
+ StorageLive(_53);
+ StorageLive(_52);
+ StorageLive(_44);
+ StorageLive(_45);
+ StorageLive(_46);
+ _48 = &mut _19;
+ StorageLive(_49);
+ StorageLive(_50);
+ _50 = &mut (_19.0: &mut std::future::Ready<()>);
+ _49 = &mut (_19.0: &mut std::future::Ready<()>);
+ _47 = copy (_19.0: &mut std::future::Ready<()>);
+ StorageDead(_50);
+ _49 = Pin::<&mut std::future::Ready<()>> { pointer: copy _47 };
+ StorageDead(_49);
+ _46 = &mut ((*_47).0: std::option::Option<()>);
+ StorageLive(_51);
+ _51 = Option::<()>::None;
+ StorageLive(_50);
+ _50 = Option::<()>::None;
+ _45 = copy ((*_47).0: std::option::Option<()>);
+ ((*_47).0: std::option::Option<()>) = copy _51;
+ StorageDead(_51);
+ ((*_47).0: std::option::Option<()>) = copy _50;
+ StorageDead(_50);
+ StorageDead(_46);
+ StorageLive(_52);
+ _52 = discriminant(_45);
+ switchInt(move _52) -> [0: bb16, 1: bb17, otherwise: bb7];
+ StorageLive(_51);
+ _51 = discriminant(_45);
+ switchInt(move _51) -> [0: bb16, 1: bb17, otherwise: bb7];
}

- bb6 (cleanup): {
Expand Down Expand Up @@ -354,16 +350,16 @@
+ }
+
+ bb16: {
+ _53 = option::expect_failed(const "`Ready` polled after completion") -> bb11;
+ _52 = option::expect_failed(const "`Ready` polled after completion") -> bb11;
+ }
+
+ bb17: {
+ _44 = move ((_45 as Some).0: ());
+ StorageDead(_52);
+ StorageDead(_51);
+ StorageDead(_45);
+ _18 = Poll::<()>::Ready(move _44);
+ StorageDead(_44);
+ StorageDead(_53);
+ StorageDead(_52);
+ StorageDead(_48);
+ StorageDead(_47);
+ StorageDead(_22);
Expand Down
Loading