Auto merge of #144543 - scottmcm:more-sroa, r=cjgillot

Allow more MIR SROA

This removes some guards on SROA that are no longer needed:
- With https://github.com/rust-lang/compiler-team/issues/838 it no longer needs to check for SIMD
- With https://github.com/rust-lang/compiler-team/issues/807 it no longer needs to check for niches
  - This means that `Wrapper(char)` and `Pin<&mut T>` can get SRoA'd now, where previously they weren't because the check was banning SRaA for anything with a niche -- not just things with `#[rustc_layout_scalar_valid_range_*]`.
  - Technically rust-lang/rust#133652 isn't complete yet, but `NonZero` and `NonNull` have already moved over, so this is fine.  At worst this will mean that LLVM gets less `!range` metadata on something that wasn't already fixed by rust-lang/rust#133651 or rust-lang/rust#135236, but that's still sound, and unblocking general SRoA is worth that tradeoff.
This commit is contained in:
bors
2025-07-28 11:53:15 +00:00
3 changed files with 40 additions and 68 deletions

View File

@@ -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;
@@ -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);
@@ -64,7 +64,6 @@ 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> {
@@ -72,31 +71,12 @@ fn escaping_locals<'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