diff --git a/compiler/rustc_mir_transform/src/sroa.rs b/compiler/rustc_mir_transform/src/sroa.rs index 80c4b58a57444..38769885f368b 100644 --- a/compiler/rustc_mir_transform/src/sroa.rs +++ b/compiler/rustc_mir_transform/src/sroa.rs @@ -72,8 +72,12 @@ fn escaping_locals<'tcx>( return true; } if let ty::Adt(def, _args) = ty.kind() - && tcx.is_lang_item(def.did(), LangItem::DynMetadata) + && (def.repr().simd() || tcx.is_lang_item(def.did(), LangItem::DynMetadata)) { + // Exclude #[repr(simd)] types so that they are not de-optimized into an array + // (MCP#838 banned projections into SIMD types, but if the value is unused + // this pass sees "all the uses are of the fields" and expands it.) + // codegen wants to see the `DynMetadata`, // not the inner reference-to-opaque-type. return true; diff --git a/tests/mir-opt/sroa/simd_sroa.foo.ScalarReplacementOfAggregates.diff b/tests/mir-opt/sroa/simd_sroa.foo.ScalarReplacementOfAggregates.diff new file mode 100644 index 0000000000000..744032471089d --- /dev/null +++ b/tests/mir-opt/sroa/simd_sroa.foo.ScalarReplacementOfAggregates.diff @@ -0,0 +1,32 @@ +- // MIR for `foo` before ScalarReplacementOfAggregates ++ // MIR for `foo` after ScalarReplacementOfAggregates + + fn foo(_1: &[Simd], _2: Simd) -> () { + debug simds => _1; + debug _unused => _2; + let mut _0: (); + let _3: std::simd::Simd; + let _4: usize; + let mut _5: usize; + let mut _6: bool; + scope 1 { + debug a => _3; + } + + bb0: { + StorageLive(_3); + StorageLive(_4); + _4 = const 0_usize; + _5 = PtrMetadata(copy _1); + _6 = Lt(copy _4, copy _5); + assert(move _6, "index out of bounds: the length is {} but the index is {}", move _5, copy _4) -> [success: bb1, unwind continue]; + } + + bb1: { + _3 = copy (*_1)[_4]; + StorageDead(_4); + StorageDead(_3); + return; + } + } + diff --git a/tests/mir-opt/sroa/simd_sroa.rs b/tests/mir-opt/sroa/simd_sroa.rs new file mode 100644 index 0000000000000..1ae84d3f975bd --- /dev/null +++ b/tests/mir-opt/sroa/simd_sroa.rs @@ -0,0 +1,18 @@ +//@ needs-unwind +#![feature(portable_simd)] + +// SRoA expands things even if they're unused +// + +use std::simd::Simd; + +// EMIT_MIR simd_sroa.foo.ScalarReplacementOfAggregates.diff +pub(crate) fn foo(simds: &[Simd], _unused: Simd) { + // CHECK-LABEL: fn foo + // CHECK-NOT: [u8; 16] + // CHECK: let [[SIMD:_.+]]: std::simd::Simd; + // CHECK-NOT: [u8; 16] + // CHECK: [[SIMD]] = copy (*_1)[0 of 1]; + // CHECK-NOT: [u8; 16] + let a = simds[0]; +}