about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2023-03-06 08:31:28 +0000
committerbors <bors@rust-lang.org>2023-03-06 08:31:28 +0000
commitac4379fea9e83465d814bb05005689f49bd2141e (patch)
tree202064ac3cbfeee67f8a71bbd251d3ab500f5d94
parent8c0f83d773370150a6ea1b40b36b55566e40a73c (diff)
parent708536bb470721e582c85e800f8ccca568cdfc7c (diff)
downloadrust-ac4379fea9e83465d814bb05005689f49bd2141e.tar.gz
rust-ac4379fea9e83465d814bb05005689f49bd2141e.zip
Auto merge of #108787 - cjgillot:sroa-lifetime, r=compiler-errors
Erase regions even when failing to normalize type in MIR opts

The first commit just moves the tests around.

Fixes https://github.com/rust-lang/rust/issues/108720

cc `@saethlin`
-rw-r--r--compiler/rustc_mir_dataflow/src/value_analysis.rs9
-rw-r--r--compiler/rustc_mir_transform/src/sroa.rs8
-rw-r--r--tests/mir-opt/sroa.constant.ScalarReplacementOfAggregates.diff46
-rw-r--r--tests/mir-opt/sroa.copies.ScalarReplacementOfAggregates.diff91
-rw-r--r--tests/mir-opt/sroa.dropping.ScalarReplacementOfAggregates.diff44
-rw-r--r--tests/mir-opt/sroa.enums.ScalarReplacementOfAggregates.diff43
-rw-r--r--tests/mir-opt/sroa.escaping.ScalarReplacementOfAggregates.diff44
-rw-r--r--tests/mir-opt/sroa.flat.ScalarReplacementOfAggregates.diff80
-rw-r--r--tests/mir-opt/sroa.ref_copies.ScalarReplacementOfAggregates.diff56
-rw-r--r--tests/mir-opt/sroa.structs.ScalarReplacementOfAggregates.diff33
-rw-r--r--tests/mir-opt/sroa.unions.ScalarReplacementOfAggregates.diff23
-rw-r--r--tests/mir-opt/sroa/lifetimes.foo.ScalarReplacementOfAggregates.diff214
-rw-r--r--tests/mir-opt/sroa/lifetimes.rs37
-rw-r--r--tests/mir-opt/sroa/structs.constant.ScalarReplacementOfAggregates.diff46
-rw-r--r--tests/mir-opt/sroa/structs.copies.ScalarReplacementOfAggregates.diff91
-rw-r--r--tests/mir-opt/sroa/structs.dropping.ScalarReplacementOfAggregates.diff44
-rw-r--r--tests/mir-opt/sroa/structs.enums.ScalarReplacementOfAggregates.diff43
-rw-r--r--tests/mir-opt/sroa/structs.escaping.ScalarReplacementOfAggregates.diff44
-rw-r--r--tests/mir-opt/sroa/structs.flat.ScalarReplacementOfAggregates.diff80
-rw-r--r--tests/mir-opt/sroa/structs.ref_copies.ScalarReplacementOfAggregates.diff56
-rw-r--r--tests/mir-opt/sroa/structs.rs (renamed from tests/mir-opt/sroa.rs)18
-rw-r--r--tests/mir-opt/sroa/structs.structs.ScalarReplacementOfAggregates.diff33
-rw-r--r--tests/mir-opt/sroa/structs.unions.ScalarReplacementOfAggregates.diff23
23 files changed, 730 insertions, 476 deletions
diff --git a/compiler/rustc_mir_dataflow/src/value_analysis.rs b/compiler/rustc_mir_dataflow/src/value_analysis.rs
index 401db890a98..34c60b5ff3c 100644
--- a/compiler/rustc_mir_dataflow/src/value_analysis.rs
+++ b/compiler/rustc_mir_dataflow/src/value_analysis.rs
@@ -690,7 +690,7 @@ impl Map {
         }
 
         // Recurse with all fields of this place.
-        iter_fields(ty, tcx, |variant, field, ty| {
+        iter_fields(ty, tcx, ty::ParamEnv::reveal_all(), |variant, field, ty| {
             if let Some(variant) = variant {
                 projection.push(PlaceElem::Downcast(None, variant));
                 let _ = self.make_place(local, projection);
@@ -939,6 +939,7 @@ impl<V, T> TryFrom<ProjectionElem<V, T>> for TrackElem {
 pub fn iter_fields<'tcx>(
     ty: Ty<'tcx>,
     tcx: TyCtxt<'tcx>,
+    param_env: ty::ParamEnv<'tcx>,
     mut f: impl FnMut(Option<VariantIdx>, Field, Ty<'tcx>),
 ) {
     match ty.kind() {
@@ -956,14 +957,14 @@ pub fn iter_fields<'tcx>(
                 for (f_index, f_def) in v_def.fields.iter().enumerate() {
                     let field_ty = f_def.ty(tcx, substs);
                     let field_ty = tcx
-                        .try_normalize_erasing_regions(ty::ParamEnv::reveal_all(), field_ty)
-                        .unwrap_or(field_ty);
+                        .try_normalize_erasing_regions(param_env, field_ty)
+                        .unwrap_or_else(|_| tcx.erase_regions(field_ty));
                     f(variant, f_index.into(), field_ty);
                 }
             }
         }
         ty::Closure(_, substs) => {
-            iter_fields(substs.as_closure().tupled_upvars_ty(), tcx, f);
+            iter_fields(substs.as_closure().tupled_upvars_ty(), tcx, param_env, f);
         }
         _ => (),
     }
diff --git a/compiler/rustc_mir_transform/src/sroa.rs b/compiler/rustc_mir_transform/src/sroa.rs
index 13168e9a268..ca2221520c8 100644
--- a/compiler/rustc_mir_transform/src/sroa.rs
+++ b/compiler/rustc_mir_transform/src/sroa.rs
@@ -4,7 +4,7 @@ use rustc_index::vec::IndexVec;
 use rustc_middle::mir::patch::MirPatch;
 use rustc_middle::mir::visit::*;
 use rustc_middle::mir::*;
-use rustc_middle::ty::{Ty, TyCtxt};
+use rustc_middle::ty::{self, Ty, TyCtxt};
 use rustc_mir_dataflow::value_analysis::{excluded_locals, iter_fields};
 
 pub struct ScalarReplacementOfAggregates;
@@ -18,11 +18,12 @@ impl<'tcx> MirPass<'tcx> for ScalarReplacementOfAggregates {
     fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
         debug!(def_id = ?body.source.def_id());
         let mut excluded = excluded_locals(body);
+        let param_env = tcx.param_env_reveal_all_normalized(body.source.def_id());
         loop {
             debug!(?excluded);
             let escaping = escaping_locals(&excluded, body);
             debug!(?escaping);
-            let replacements = compute_flattening(tcx, body, escaping);
+            let replacements = compute_flattening(tcx, param_env, body, escaping);
             debug!(?replacements);
             let all_dead_locals = replace_flattened_locals(tcx, body, replacements);
             if !all_dead_locals.is_empty() {
@@ -144,6 +145,7 @@ impl<'tcx> ReplacementMap<'tcx> {
 /// The replacement will be done later in `ReplacementVisitor`.
 fn compute_flattening<'tcx>(
     tcx: TyCtxt<'tcx>,
+    param_env: ty::ParamEnv<'tcx>,
     body: &mut Body<'tcx>,
     escaping: BitSet<Local>,
 ) -> ReplacementMap<'tcx> {
@@ -155,7 +157,7 @@ fn compute_flattening<'tcx>(
         }
         let decl = body.local_decls[local].clone();
         let ty = decl.ty;
-        iter_fields(ty, tcx, |variant, field, field_ty| {
+        iter_fields(ty, tcx, param_env, |variant, field, field_ty| {
             if variant.is_some() {
                 // Downcasts are currently not supported.
                 return;
diff --git a/tests/mir-opt/sroa.constant.ScalarReplacementOfAggregates.diff b/tests/mir-opt/sroa.constant.ScalarReplacementOfAggregates.diff
deleted file mode 100644
index 9e33215f2b5..00000000000
--- a/tests/mir-opt/sroa.constant.ScalarReplacementOfAggregates.diff
+++ /dev/null
@@ -1,46 +0,0 @@
-- // MIR for `constant` before ScalarReplacementOfAggregates
-+ // MIR for `constant` after ScalarReplacementOfAggregates
-  
-  fn constant() -> () {
-      let mut _0: ();                      // return place in scope 0 at $DIR/sroa.rs:+0:15: +0:15
-      let _1: (usize, u8);                 // in scope 0 at $DIR/sroa.rs:+2:9: +2:10
-+     let _4: usize;                       // in scope 0 at $DIR/sroa.rs:+2:9: +2:10
-+     let _5: u8;                          // in scope 0 at $DIR/sroa.rs:+2:9: +2:10
-      scope 1 {
--         debug y => _1;                   // in scope 1 at $DIR/sroa.rs:+2:9: +2:10
-+         debug y => (usize, u8){ .0 => _4, .1 => _5, }; // in scope 1 at $DIR/sroa.rs:+2:9: +2:10
-          let _2: usize;                   // in scope 1 at $DIR/sroa.rs:+3:9: +3:10
-          scope 2 {
-              debug t => _2;               // in scope 2 at $DIR/sroa.rs:+3:9: +3:10
-              let _3: u8;                  // in scope 2 at $DIR/sroa.rs:+4:9: +4:10
-              scope 3 {
-                  debug u => _3;           // in scope 3 at $DIR/sroa.rs:+4:9: +4:10
-              }
-          }
-      }
-  
-      bb0: {
--         StorageLive(_1);                 // scope 0 at $DIR/sroa.rs:+2:9: +2:10
-+         StorageLive(_4);                 // scope 0 at $DIR/sroa.rs:+2:9: +2:10
-+         StorageLive(_5);                 // scope 0 at $DIR/sroa.rs:+2:9: +2:10
-+         nop;                             // scope 0 at $DIR/sroa.rs:+2:9: +2:10
-          _1 = const _;                    // scope 0 at $DIR/sroa.rs:+2:13: +2:14
-+         _4 = move (_1.0: usize);         // scope 1 at $DIR/sroa.rs:+3:9: +3:10
-+         _5 = move (_1.1: u8);            // scope 1 at $DIR/sroa.rs:+3:9: +3:10
-          StorageLive(_2);                 // scope 1 at $DIR/sroa.rs:+3:9: +3:10
--         _2 = (_1.0: usize);              // scope 1 at $DIR/sroa.rs:+3:13: +3:16
-+         _2 = _4;                         // scope 1 at $DIR/sroa.rs:+3:13: +3:16
-          StorageLive(_3);                 // scope 2 at $DIR/sroa.rs:+4:9: +4:10
--         _3 = (_1.1: u8);                 // scope 2 at $DIR/sroa.rs:+4:13: +4:16
-+         _3 = _5;                         // scope 2 at $DIR/sroa.rs:+4:13: +4:16
-          _0 = const ();                   // scope 0 at $DIR/sroa.rs:+0:15: +5:2
-          StorageDead(_3);                 // scope 2 at $DIR/sroa.rs:+5:1: +5:2
-          StorageDead(_2);                 // scope 1 at $DIR/sroa.rs:+5:1: +5:2
--         StorageDead(_1);                 // scope 0 at $DIR/sroa.rs:+5:1: +5:2
-+         StorageDead(_4);                 // scope 0 at $DIR/sroa.rs:+5:1: +5:2
-+         StorageDead(_5);                 // scope 0 at $DIR/sroa.rs:+5:1: +5:2
-+         nop;                             // scope 0 at $DIR/sroa.rs:+5:1: +5:2
-          return;                          // scope 0 at $DIR/sroa.rs:+5:2: +5:2
-      }
-  }
-  
diff --git a/tests/mir-opt/sroa.copies.ScalarReplacementOfAggregates.diff b/tests/mir-opt/sroa.copies.ScalarReplacementOfAggregates.diff
deleted file mode 100644
index 976f6d44b75..00000000000
--- a/tests/mir-opt/sroa.copies.ScalarReplacementOfAggregates.diff
+++ /dev/null
@@ -1,91 +0,0 @@
-- // MIR for `copies` before ScalarReplacementOfAggregates
-+ // MIR for `copies` after ScalarReplacementOfAggregates
-  
-  fn copies(_1: Foo) -> () {
-      debug x => _1;                       // in scope 0 at $DIR/sroa.rs:+0:11: +0:12
-      let mut _0: ();                      // return place in scope 0 at $DIR/sroa.rs:+0:19: +0:19
-      let _2: Foo;                         // in scope 0 at $DIR/sroa.rs:+1:9: +1:10
-+     let _11: u8;                         // in scope 0 at $DIR/sroa.rs:+1:9: +1:10
-+     let _12: ();                         // in scope 0 at $DIR/sroa.rs:+1:9: +1:10
-+     let _13: &str;                       // in scope 0 at $DIR/sroa.rs:+1:9: +1:10
-+     let _14: std::option::Option<isize>; // in scope 0 at $DIR/sroa.rs:+1:9: +1:10
-      scope 1 {
--         debug y => _2;                   // in scope 1 at $DIR/sroa.rs:+1:9: +1:10
-+         debug y => Foo{ .0 => _11, .1 => _12, .2 => _13, .3 => _14, }; // in scope 1 at $DIR/sroa.rs:+1:9: +1:10
-          let _3: u8;                      // in scope 1 at $DIR/sroa.rs:+2:9: +2:10
-          scope 2 {
-              debug t => _3;               // in scope 2 at $DIR/sroa.rs:+2:9: +2:10
-              let _4: &str;                // in scope 2 at $DIR/sroa.rs:+3:9: +3:10
-              scope 3 {
-                  debug u => _4;           // in scope 3 at $DIR/sroa.rs:+3:9: +3:10
-                  let _5: Foo;             // in scope 3 at $DIR/sroa.rs:+4:9: +4:10
-+                 let _7: u8;              // in scope 3 at $DIR/sroa.rs:+4:9: +4:10
-+                 let _8: ();              // in scope 3 at $DIR/sroa.rs:+4:9: +4:10
-+                 let _9: &str;            // in scope 3 at $DIR/sroa.rs:+4:9: +4:10
-+                 let _10: std::option::Option<isize>; // in scope 3 at $DIR/sroa.rs:+4:9: +4:10
-                  scope 4 {
--                     debug z => _5;       // in scope 4 at $DIR/sroa.rs:+4:9: +4:10
-+                     debug z => Foo{ .0 => _7, .1 => _8, .2 => _9, .3 => _10, }; // in scope 4 at $DIR/sroa.rs:+4:9: +4:10
-                      let _6: ();          // in scope 4 at $DIR/sroa.rs:+5:9: +5:10
-                      scope 5 {
-                          debug a => _6;   // in scope 5 at $DIR/sroa.rs:+5:9: +5:10
-                      }
-                  }
-              }
-          }
-      }
-  
-      bb0: {
--         StorageLive(_2);                 // scope 0 at $DIR/sroa.rs:+1:9: +1:10
--         _2 = _1;                         // scope 0 at $DIR/sroa.rs:+1:13: +1:14
-+         StorageLive(_11);                // scope 0 at $DIR/sroa.rs:+1:9: +1:10
-+         StorageLive(_12);                // scope 0 at $DIR/sroa.rs:+1:9: +1:10
-+         StorageLive(_13);                // scope 0 at $DIR/sroa.rs:+1:9: +1:10
-+         StorageLive(_14);                // scope 0 at $DIR/sroa.rs:+1:9: +1:10
-+         nop;                             // scope 0 at $DIR/sroa.rs:+1:9: +1:10
-+         _11 = (_1.0: u8);                // scope 0 at $DIR/sroa.rs:+1:13: +1:14
-+         _12 = (_1.1: ());                // scope 0 at $DIR/sroa.rs:+1:13: +1:14
-+         _13 = (_1.2: &str);              // scope 0 at $DIR/sroa.rs:+1:13: +1:14
-+         _14 = (_1.3: std::option::Option<isize>); // scope 0 at $DIR/sroa.rs:+1:13: +1:14
-+         nop;                             // scope 0 at $DIR/sroa.rs:+1:13: +1:14
-          StorageLive(_3);                 // scope 1 at $DIR/sroa.rs:+2:9: +2:10
--         _3 = (_2.0: u8);                 // scope 1 at $DIR/sroa.rs:+2:13: +2:16
-+         _3 = _11;                        // scope 1 at $DIR/sroa.rs:+2:13: +2:16
-          StorageLive(_4);                 // scope 2 at $DIR/sroa.rs:+3:9: +3:10
--         _4 = (_2.2: &str);               // scope 2 at $DIR/sroa.rs:+3:13: +3:16
--         StorageLive(_5);                 // scope 3 at $DIR/sroa.rs:+4:9: +4:10
--         _5 = _2;                         // scope 3 at $DIR/sroa.rs:+4:13: +4:14
-+         _4 = _13;                        // scope 2 at $DIR/sroa.rs:+3:13: +3:16
-+         StorageLive(_7);                 // scope 3 at $DIR/sroa.rs:+4:9: +4:10
-+         StorageLive(_8);                 // scope 3 at $DIR/sroa.rs:+4:9: +4:10
-+         StorageLive(_9);                 // scope 3 at $DIR/sroa.rs:+4:9: +4:10
-+         StorageLive(_10);                // scope 3 at $DIR/sroa.rs:+4:9: +4:10
-+         nop;                             // scope 3 at $DIR/sroa.rs:+4:9: +4:10
-+         _7 = _11;                        // scope 3 at $DIR/sroa.rs:+4:13: +4:14
-+         _8 = _12;                        // scope 3 at $DIR/sroa.rs:+4:13: +4:14
-+         _9 = _13;                        // scope 3 at $DIR/sroa.rs:+4:13: +4:14
-+         _10 = _14;                       // scope 3 at $DIR/sroa.rs:+4:13: +4:14
-+         nop;                             // scope 3 at $DIR/sroa.rs:+4:13: +4:14
-          StorageLive(_6);                 // scope 4 at $DIR/sroa.rs:+5:9: +5:10
--         _6 = (_5.1: ());                 // scope 4 at $DIR/sroa.rs:+5:13: +5:16
-+         _6 = _8;                         // scope 4 at $DIR/sroa.rs:+5:13: +5:16
-          _0 = const ();                   // scope 0 at $DIR/sroa.rs:+0:19: +6:2
-          StorageDead(_6);                 // scope 4 at $DIR/sroa.rs:+6:1: +6:2
--         StorageDead(_5);                 // scope 3 at $DIR/sroa.rs:+6:1: +6:2
-+         StorageDead(_7);                 // scope 3 at $DIR/sroa.rs:+6:1: +6:2
-+         StorageDead(_8);                 // scope 3 at $DIR/sroa.rs:+6:1: +6:2
-+         StorageDead(_9);                 // scope 3 at $DIR/sroa.rs:+6:1: +6:2
-+         StorageDead(_10);                // scope 3 at $DIR/sroa.rs:+6:1: +6:2
-+         nop;                             // scope 3 at $DIR/sroa.rs:+6:1: +6:2
-          StorageDead(_4);                 // scope 2 at $DIR/sroa.rs:+6:1: +6:2
-          StorageDead(_3);                 // scope 1 at $DIR/sroa.rs:+6:1: +6:2
--         StorageDead(_2);                 // scope 0 at $DIR/sroa.rs:+6:1: +6:2
-+         StorageDead(_11);                // scope 0 at $DIR/sroa.rs:+6:1: +6:2
-+         StorageDead(_12);                // scope 0 at $DIR/sroa.rs:+6:1: +6:2
-+         StorageDead(_13);                // scope 0 at $DIR/sroa.rs:+6:1: +6:2
-+         StorageDead(_14);                // scope 0 at $DIR/sroa.rs:+6:1: +6:2
-+         nop;                             // scope 0 at $DIR/sroa.rs:+6:1: +6:2
-          return;                          // scope 0 at $DIR/sroa.rs:+6:2: +6:2
-      }
-  }
-  
diff --git a/tests/mir-opt/sroa.dropping.ScalarReplacementOfAggregates.diff b/tests/mir-opt/sroa.dropping.ScalarReplacementOfAggregates.diff
deleted file mode 100644
index 17a89e7d8eb..00000000000
--- a/tests/mir-opt/sroa.dropping.ScalarReplacementOfAggregates.diff
+++ /dev/null
@@ -1,44 +0,0 @@
-- // MIR for `dropping` before ScalarReplacementOfAggregates
-+ // MIR for `dropping` after ScalarReplacementOfAggregates
-  
-  fn dropping() -> () {
-      let mut _0: ();                      // return place in scope 0 at $DIR/sroa.rs:+0:19: +0:19
-      let _1: Tag;                         // in scope 0 at $DIR/sroa.rs:+1:5: +1:32
-      let mut _2: S;                       // in scope 0 at $DIR/sroa.rs:+1:5: +1:30
-      let mut _3: Tag;                     // in scope 0 at $DIR/sroa.rs:+1:7: +1:13
-      let mut _4: Tag;                     // in scope 0 at $DIR/sroa.rs:+1:15: +1:21
-      let mut _5: Tag;                     // in scope 0 at $DIR/sroa.rs:+1:23: +1:29
-  
-      bb0: {
-          StorageLive(_1);                 // scope 0 at $DIR/sroa.rs:+1:5: +1:32
-          StorageLive(_2);                 // scope 0 at $DIR/sroa.rs:+1:5: +1:30
-          StorageLive(_3);                 // scope 0 at $DIR/sroa.rs:+1:7: +1:13
-          _3 = Tag(const 0_usize);         // scope 0 at $DIR/sroa.rs:+1:7: +1:13
-          StorageLive(_4);                 // scope 0 at $DIR/sroa.rs:+1:15: +1:21
-          _4 = Tag(const 1_usize);         // scope 0 at $DIR/sroa.rs:+1:15: +1:21
-          StorageLive(_5);                 // scope 0 at $DIR/sroa.rs:+1:23: +1:29
-          _5 = Tag(const 2_usize);         // scope 0 at $DIR/sroa.rs:+1:23: +1:29
-          _2 = S(move _3, move _4, move _5); // scope 0 at $DIR/sroa.rs:+1:5: +1:30
-          StorageDead(_5);                 // scope 0 at $DIR/sroa.rs:+1:29: +1:30
-          StorageDead(_4);                 // scope 0 at $DIR/sroa.rs:+1:29: +1:30
-          StorageDead(_3);                 // scope 0 at $DIR/sroa.rs:+1:29: +1:30
-          _1 = move (_2.1: Tag);           // scope 0 at $DIR/sroa.rs:+1:5: +1:32
-          drop(_1) -> bb1;                 // scope 0 at $DIR/sroa.rs:+1:32: +1:33
-      }
-  
-      bb1: {
-          drop((_2.0: Tag)) -> bb3;        // scope 0 at $DIR/sroa.rs:+1:32: +1:33
-      }
-  
-      bb2: {
-          StorageDead(_2);                 // scope 0 at $DIR/sroa.rs:+1:32: +1:33
-          StorageDead(_1);                 // scope 0 at $DIR/sroa.rs:+1:32: +1:33
-          _0 = const ();                   // scope 0 at $DIR/sroa.rs:+0:19: +2:2
-          return;                          // scope 0 at $DIR/sroa.rs:+2:2: +2:2
-      }
-  
-      bb3: {
-          drop((_2.2: Tag)) -> bb2;        // scope 0 at $DIR/sroa.rs:+1:32: +1:33
-      }
-  }
-  
diff --git a/tests/mir-opt/sroa.enums.ScalarReplacementOfAggregates.diff b/tests/mir-opt/sroa.enums.ScalarReplacementOfAggregates.diff
deleted file mode 100644
index 04d26162aad..00000000000
--- a/tests/mir-opt/sroa.enums.ScalarReplacementOfAggregates.diff
+++ /dev/null
@@ -1,43 +0,0 @@
-- // MIR for `enums` before ScalarReplacementOfAggregates
-+ // MIR for `enums` after ScalarReplacementOfAggregates
-  
-  fn enums(_1: usize) -> usize {
-      debug a => _1;                       // in scope 0 at $DIR/sroa.rs:+0:14: +0:15
-      let mut _0: usize;                   // return place in scope 0 at $DIR/sroa.rs:+0:27: +0:32
-      let mut _2: std::option::Option<usize>; // in scope 0 at $DIR/sroa.rs:+1:22: +1:29
-      let mut _3: usize;                   // in scope 0 at $DIR/sroa.rs:+1:27: +1:28
-      let mut _4: isize;                   // in scope 0 at $DIR/sroa.rs:+1:12: +1:19
-      scope 1 {
-          debug a => _5;                   // in scope 1 at $DIR/sroa.rs:+1:17: +1:18
-          let _5: usize;                   // in scope 1 at $DIR/sroa.rs:+1:17: +1:18
-      }
-  
-      bb0: {
-          StorageLive(_2);                 // scope 1 at $DIR/sroa.rs:+1:22: +1:29
-          StorageLive(_3);                 // scope 1 at $DIR/sroa.rs:+1:27: +1:28
-          _3 = _1;                         // scope 1 at $DIR/sroa.rs:+1:27: +1:28
-          _2 = Option::<usize>::Some(move _3); // scope 1 at $DIR/sroa.rs:+1:22: +1:29
-          StorageDead(_3);                 // scope 1 at $DIR/sroa.rs:+1:28: +1:29
-          _4 = discriminant(_2);           // scope 1 at $DIR/sroa.rs:+1:12: +1:19
-          switchInt(move _4) -> [1: bb1, otherwise: bb2]; // scope 1 at $DIR/sroa.rs:+1:12: +1:19
-      }
-  
-      bb1: {
-          StorageLive(_5);                 // scope 1 at $DIR/sroa.rs:+1:17: +1:18
-          _5 = ((_2 as Some).0: usize);    // scope 1 at $DIR/sroa.rs:+1:17: +1:18
-          _0 = _5;                         // scope 1 at $DIR/sroa.rs:+1:32: +1:33
-          StorageDead(_5);                 // scope 0 at $DIR/sroa.rs:+1:34: +1:35
-          goto -> bb3;                     // scope 0 at $DIR/sroa.rs:+1:5: +1:46
-      }
-  
-      bb2: {
-          _0 = const 0_usize;              // scope 0 at $DIR/sroa.rs:+1:43: +1:44
-          goto -> bb3;                     // scope 0 at $DIR/sroa.rs:+1:5: +1:46
-      }
-  
-      bb3: {
-          StorageDead(_2);                 // scope 0 at $DIR/sroa.rs:+2:1: +2:2
-          return;                          // scope 0 at $DIR/sroa.rs:+2:2: +2:2
-      }
-  }
-  
diff --git a/tests/mir-opt/sroa.escaping.ScalarReplacementOfAggregates.diff b/tests/mir-opt/sroa.escaping.ScalarReplacementOfAggregates.diff
deleted file mode 100644
index fd691fdd153..00000000000
--- a/tests/mir-opt/sroa.escaping.ScalarReplacementOfAggregates.diff
+++ /dev/null
@@ -1,44 +0,0 @@
-- // MIR for `escaping` before ScalarReplacementOfAggregates
-+ // MIR for `escaping` after ScalarReplacementOfAggregates
-  
-  fn escaping() -> () {
-      let mut _0: ();                      // return place in scope 0 at $DIR/sroa.rs:+0:19: +0:19
-      let _1: ();                          // in scope 0 at $DIR/sroa.rs:+1:5: +1:42
-      let mut _2: *const u32;              // in scope 0 at $DIR/sroa.rs:+1:7: +1:41
-      let _3: &u32;                        // in scope 0 at $DIR/sroa.rs:+1:7: +1:41
-      let _4: Escaping;                    // in scope 0 at $DIR/sroa.rs:+1:8: +1:39
-      let mut _5: u32;                     // in scope 0 at $DIR/sroa.rs:+1:34: +1:37
-  
-      bb0: {
-          StorageLive(_1);                 // scope 0 at $DIR/sroa.rs:+1:5: +1:42
-          StorageLive(_2);                 // scope 0 at $DIR/sroa.rs:+1:7: +1:41
-          StorageLive(_3);                 // scope 0 at $DIR/sroa.rs:+1:7: +1:41
-          StorageLive(_4);                 // scope 0 at $DIR/sroa.rs:+1:8: +1:39
-          StorageLive(_5);                 // scope 0 at $DIR/sroa.rs:+1:34: +1:37
-          _5 = g() -> bb1;                 // scope 0 at $DIR/sroa.rs:+1:34: +1:37
-                                           // mir::Constant
-                                           // + span: $DIR/sroa.rs:78:34: 78:35
-                                           // + literal: Const { ty: fn() -> u32 {g}, val: Value(<ZST>) }
-      }
-  
-      bb1: {
-          _4 = Escaping { a: const 1_u32, b: const 2_u32, c: move _5 }; // scope 0 at $DIR/sroa.rs:+1:8: +1:39
-          StorageDead(_5);                 // scope 0 at $DIR/sroa.rs:+1:38: +1:39
-          _3 = &(_4.0: u32);               // scope 0 at $DIR/sroa.rs:+1:7: +1:41
-          _2 = &raw const (*_3);           // scope 0 at $DIR/sroa.rs:+1:7: +1:41
-          _1 = f(move _2) -> bb2;          // scope 0 at $DIR/sroa.rs:+1:5: +1:42
-                                           // mir::Constant
-                                           // + span: $DIR/sroa.rs:78:5: 78:6
-                                           // + literal: Const { ty: fn(*const u32) {f}, val: Value(<ZST>) }
-      }
-  
-      bb2: {
-          StorageDead(_2);                 // scope 0 at $DIR/sroa.rs:+1:41: +1:42
-          StorageDead(_4);                 // scope 0 at $DIR/sroa.rs:+1:42: +1:43
-          StorageDead(_3);                 // scope 0 at $DIR/sroa.rs:+1:42: +1:43
-          StorageDead(_1);                 // scope 0 at $DIR/sroa.rs:+1:42: +1:43
-          _0 = const ();                   // scope 0 at $DIR/sroa.rs:+0:19: +2:2
-          return;                          // scope 0 at $DIR/sroa.rs:+2:2: +2:2
-      }
-  }
-  
diff --git a/tests/mir-opt/sroa.flat.ScalarReplacementOfAggregates.diff b/tests/mir-opt/sroa.flat.ScalarReplacementOfAggregates.diff
deleted file mode 100644
index 69631fc0213..00000000000
--- a/tests/mir-opt/sroa.flat.ScalarReplacementOfAggregates.diff
+++ /dev/null
@@ -1,80 +0,0 @@
-- // MIR for `flat` before ScalarReplacementOfAggregates
-+ // MIR for `flat` after ScalarReplacementOfAggregates
-  
-  fn flat() -> () {
-      let mut _0: ();                      // return place in scope 0 at $DIR/sroa.rs:+0:15: +0:15
-      let _1: u8;                          // in scope 0 at $DIR/sroa.rs:+1:15: +1:16
-      let _2: ();                          // in scope 0 at $DIR/sroa.rs:+1:18: +1:19
-      let _3: &str;                        // in scope 0 at $DIR/sroa.rs:+1:21: +1:22
-      let _4: std::option::Option<isize>;  // in scope 0 at $DIR/sroa.rs:+1:24: +1:25
-      let mut _5: Foo;                     // in scope 0 at $DIR/sroa.rs:+1:30: +1:70
-      let mut _6: ();                      // in scope 0 at $DIR/sroa.rs:+1:45: +1:47
-      let mut _7: std::option::Option<isize>; // in scope 0 at $DIR/sroa.rs:+1:60: +1:68
-+     let mut _8: u8;                      // in scope 0 at $DIR/sroa.rs:+1:30: +1:70
-+     let mut _9: ();                      // in scope 0 at $DIR/sroa.rs:+1:30: +1:70
-+     let mut _10: &str;                   // in scope 0 at $DIR/sroa.rs:+1:30: +1:70
-+     let mut _11: std::option::Option<isize>; // in scope 0 at $DIR/sroa.rs:+1:30: +1:70
-      scope 1 {
-          debug a => _1;                   // in scope 1 at $DIR/sroa.rs:+1:15: +1:16
-          debug b => _2;                   // in scope 1 at $DIR/sroa.rs:+1:18: +1:19
-          debug c => _3;                   // in scope 1 at $DIR/sroa.rs:+1:21: +1:22
-          debug d => _4;                   // in scope 1 at $DIR/sroa.rs:+1:24: +1:25
-          scope 2 {
-              scope 3 {
-                  scope 4 {
-                      scope 5 {
-                      }
-                  }
-              }
-          }
-      }
-  
-      bb0: {
--         StorageLive(_5);                 // scope 0 at $DIR/sroa.rs:+1:30: +1:70
-+         StorageLive(_8);                 // scope 0 at $DIR/sroa.rs:+1:30: +1:70
-+         StorageLive(_9);                 // scope 0 at $DIR/sroa.rs:+1:30: +1:70
-+         StorageLive(_10);                // scope 0 at $DIR/sroa.rs:+1:30: +1:70
-+         StorageLive(_11);                // scope 0 at $DIR/sroa.rs:+1:30: +1:70
-+         nop;                             // scope 0 at $DIR/sroa.rs:+1:30: +1:70
-          StorageLive(_6);                 // scope 0 at $DIR/sroa.rs:+1:45: +1:47
-          _6 = ();                         // scope 0 at $DIR/sroa.rs:+1:45: +1:47
-          StorageLive(_7);                 // scope 0 at $DIR/sroa.rs:+1:60: +1:68
-          _7 = Option::<isize>::Some(const -4_isize); // scope 0 at $DIR/sroa.rs:+1:60: +1:68
--         _5 = Foo { a: const 5_u8, b: move _6, c: const "a", d: move _7 }; // scope 0 at $DIR/sroa.rs:+1:30: +1:70
-+         _8 = const 5_u8;                 // scope 0 at $DIR/sroa.rs:+1:30: +1:70
-+         _9 = move _6;                    // scope 0 at $DIR/sroa.rs:+1:30: +1:70
-+         _10 = const "a";                 // scope 0 at $DIR/sroa.rs:+1:30: +1:70
-                                           // mir::Constant
-                                           // + span: $DIR/sroa.rs:53:52: 53:55
-                                           // + literal: Const { ty: &str, val: Value(Slice(..)) }
-+         _11 = move _7;                   // scope 0 at $DIR/sroa.rs:+1:30: +1:70
-+         nop;                             // scope 0 at $DIR/sroa.rs:+1:30: +1:70
-          StorageDead(_7);                 // scope 0 at $DIR/sroa.rs:+1:69: +1:70
-          StorageDead(_6);                 // scope 0 at $DIR/sroa.rs:+1:69: +1:70
-          StorageLive(_1);                 // scope 0 at $DIR/sroa.rs:+1:15: +1:16
--         _1 = (_5.0: u8);                 // scope 0 at $DIR/sroa.rs:+1:15: +1:16
-+         _1 = _8;                         // scope 0 at $DIR/sroa.rs:+1:15: +1:16
-          StorageLive(_2);                 // scope 0 at $DIR/sroa.rs:+1:18: +1:19
--         _2 = (_5.1: ());                 // scope 0 at $DIR/sroa.rs:+1:18: +1:19
-+         _2 = _9;                         // scope 0 at $DIR/sroa.rs:+1:18: +1:19
-          StorageLive(_3);                 // scope 0 at $DIR/sroa.rs:+1:21: +1:22
--         _3 = (_5.2: &str);               // scope 0 at $DIR/sroa.rs:+1:21: +1:22
-+         _3 = _10;                        // scope 0 at $DIR/sroa.rs:+1:21: +1:22
-          StorageLive(_4);                 // scope 0 at $DIR/sroa.rs:+1:24: +1:25
--         _4 = (_5.3: std::option::Option<isize>); // scope 0 at $DIR/sroa.rs:+1:24: +1:25
--         StorageDead(_5);                 // scope 0 at $DIR/sroa.rs:+1:70: +1:71
-+         _4 = _11;                        // scope 0 at $DIR/sroa.rs:+1:24: +1:25
-+         StorageDead(_8);                 // scope 0 at $DIR/sroa.rs:+1:70: +1:71
-+         StorageDead(_9);                 // scope 0 at $DIR/sroa.rs:+1:70: +1:71
-+         StorageDead(_10);                // scope 0 at $DIR/sroa.rs:+1:70: +1:71
-+         StorageDead(_11);                // scope 0 at $DIR/sroa.rs:+1:70: +1:71
-+         nop;                             // scope 0 at $DIR/sroa.rs:+1:70: +1:71
-          _0 = const ();                   // scope 0 at $DIR/sroa.rs:+0:15: +6:2
-          StorageDead(_4);                 // scope 0 at $DIR/sroa.rs:+6:1: +6:2
-          StorageDead(_3);                 // scope 0 at $DIR/sroa.rs:+6:1: +6:2
-          StorageDead(_2);                 // scope 0 at $DIR/sroa.rs:+6:1: +6:2
-          StorageDead(_1);                 // scope 0 at $DIR/sroa.rs:+6:1: +6:2
-          return;                          // scope 0 at $DIR/sroa.rs:+6:2: +6:2
-      }
-  }
-  
diff --git a/tests/mir-opt/sroa.ref_copies.ScalarReplacementOfAggregates.diff b/tests/mir-opt/sroa.ref_copies.ScalarReplacementOfAggregates.diff
deleted file mode 100644
index f0d62220dd6..00000000000
--- a/tests/mir-opt/sroa.ref_copies.ScalarReplacementOfAggregates.diff
+++ /dev/null
@@ -1,56 +0,0 @@
-- // MIR for `ref_copies` before ScalarReplacementOfAggregates
-+ // MIR for `ref_copies` after ScalarReplacementOfAggregates
-  
-  fn ref_copies(_1: &Foo) -> () {
-      debug x => _1;                       // in scope 0 at $DIR/sroa.rs:+0:15: +0:16
-      let mut _0: ();                      // return place in scope 0 at $DIR/sroa.rs:+0:24: +0:24
-      let _2: Foo;                         // in scope 0 at $DIR/sroa.rs:+1:9: +1:10
-+     let _5: u8;                          // in scope 0 at $DIR/sroa.rs:+1:9: +1:10
-+     let _6: ();                          // in scope 0 at $DIR/sroa.rs:+1:9: +1:10
-+     let _7: &str;                        // in scope 0 at $DIR/sroa.rs:+1:9: +1:10
-+     let _8: std::option::Option<isize>;  // in scope 0 at $DIR/sroa.rs:+1:9: +1:10
-      scope 1 {
--         debug y => _2;                   // in scope 1 at $DIR/sroa.rs:+1:9: +1:10
-+         debug y => Foo{ .0 => _5, .1 => _6, .2 => _7, .3 => _8, }; // in scope 1 at $DIR/sroa.rs:+1:9: +1:10
-          let _3: u8;                      // in scope 1 at $DIR/sroa.rs:+2:9: +2:10
-          scope 2 {
-              debug t => _3;               // in scope 2 at $DIR/sroa.rs:+2:9: +2:10
-              let _4: &str;                // in scope 2 at $DIR/sroa.rs:+3:9: +3:10
-              scope 3 {
-                  debug u => _4;           // in scope 3 at $DIR/sroa.rs:+3:9: +3:10
-              }
-          }
-      }
-  
-      bb0: {
--         StorageLive(_2);                 // scope 0 at $DIR/sroa.rs:+1:9: +1:10
--         _2 = (*_1);                      // scope 0 at $DIR/sroa.rs:+1:13: +1:15
-+         StorageLive(_5);                 // scope 0 at $DIR/sroa.rs:+1:9: +1:10
-+         StorageLive(_6);                 // scope 0 at $DIR/sroa.rs:+1:9: +1:10
-+         StorageLive(_7);                 // scope 0 at $DIR/sroa.rs:+1:9: +1:10
-+         StorageLive(_8);                 // scope 0 at $DIR/sroa.rs:+1:9: +1:10
-+         nop;                             // scope 0 at $DIR/sroa.rs:+1:9: +1:10
-+         _5 = ((*_1).0: u8);              // scope 0 at $DIR/sroa.rs:+1:13: +1:15
-+         _6 = ((*_1).1: ());              // scope 0 at $DIR/sroa.rs:+1:13: +1:15
-+         _7 = ((*_1).2: &str);            // scope 0 at $DIR/sroa.rs:+1:13: +1:15
-+         _8 = ((*_1).3: std::option::Option<isize>); // scope 0 at $DIR/sroa.rs:+1:13: +1:15
-+         nop;                             // scope 0 at $DIR/sroa.rs:+1:13: +1:15
-          StorageLive(_3);                 // scope 1 at $DIR/sroa.rs:+2:9: +2:10
--         _3 = (_2.0: u8);                 // scope 1 at $DIR/sroa.rs:+2:13: +2:16
-+         _3 = _5;                         // scope 1 at $DIR/sroa.rs:+2:13: +2:16
-          StorageLive(_4);                 // scope 2 at $DIR/sroa.rs:+3:9: +3:10
--         _4 = (_2.2: &str);               // scope 2 at $DIR/sroa.rs:+3:13: +3:16
-+         _4 = _7;                         // scope 2 at $DIR/sroa.rs:+3:13: +3:16
-          _0 = const ();                   // scope 0 at $DIR/sroa.rs:+0:24: +4:2
-          StorageDead(_4);                 // scope 2 at $DIR/sroa.rs:+4:1: +4:2
-          StorageDead(_3);                 // scope 1 at $DIR/sroa.rs:+4:1: +4:2
--         StorageDead(_2);                 // scope 0 at $DIR/sroa.rs:+4:1: +4:2
-+         StorageDead(_5);                 // scope 0 at $DIR/sroa.rs:+4:1: +4:2
-+         StorageDead(_6);                 // scope 0 at $DIR/sroa.rs:+4:1: +4:2
-+         StorageDead(_7);                 // scope 0 at $DIR/sroa.rs:+4:1: +4:2
-+         StorageDead(_8);                 // scope 0 at $DIR/sroa.rs:+4:1: +4:2
-+         nop;                             // scope 0 at $DIR/sroa.rs:+4:1: +4:2
-          return;                          // scope 0 at $DIR/sroa.rs:+4:2: +4:2
-      }
-  }
-  
diff --git a/tests/mir-opt/sroa.structs.ScalarReplacementOfAggregates.diff b/tests/mir-opt/sroa.structs.ScalarReplacementOfAggregates.diff
deleted file mode 100644
index 2c63d8b266d..00000000000
--- a/tests/mir-opt/sroa.structs.ScalarReplacementOfAggregates.diff
+++ /dev/null
@@ -1,33 +0,0 @@
-- // MIR for `structs` before ScalarReplacementOfAggregates
-+ // MIR for `structs` after ScalarReplacementOfAggregates
-  
-  fn structs(_1: f32) -> f32 {
-      debug a => _1;                       // in scope 0 at $DIR/sroa.rs:+0:16: +0:17
-      let mut _0: f32;                     // return place in scope 0 at $DIR/sroa.rs:+0:27: +0:30
-      let mut _2: structs::U;              // in scope 0 at $DIR/sroa.rs:+6:5: +6:21
-      let mut _3: f32;                     // in scope 0 at $DIR/sroa.rs:+6:18: +6:19
-+     let mut _4: usize;                   // in scope 0 at $DIR/sroa.rs:+6:5: +6:21
-+     let mut _5: f32;                     // in scope 0 at $DIR/sroa.rs:+6:5: +6:21
-  
-      bb0: {
--         StorageLive(_2);                 // scope 0 at $DIR/sroa.rs:+6:5: +6:21
-+         StorageLive(_4);                 // scope 0 at $DIR/sroa.rs:+6:5: +6:21
-+         StorageLive(_5);                 // scope 0 at $DIR/sroa.rs:+6:5: +6:21
-+         nop;                             // scope 0 at $DIR/sroa.rs:+6:5: +6:21
-          StorageLive(_3);                 // scope 0 at $DIR/sroa.rs:+6:18: +6:19
-          _3 = _1;                         // scope 0 at $DIR/sroa.rs:+6:18: +6:19
--         _2 = U { _foo: const 0_usize, a: move _3 }; // scope 0 at $DIR/sroa.rs:+6:5: +6:21
-+         _4 = const 0_usize;              // scope 0 at $DIR/sroa.rs:+6:5: +6:21
-+         _5 = move _3;                    // scope 0 at $DIR/sroa.rs:+6:5: +6:21
-+         nop;                             // scope 0 at $DIR/sroa.rs:+6:5: +6:21
-          StorageDead(_3);                 // scope 0 at $DIR/sroa.rs:+6:20: +6:21
--         _0 = (_2.1: f32);                // scope 0 at $DIR/sroa.rs:+6:5: +6:23
--         StorageDead(_2);                 // scope 0 at $DIR/sroa.rs:+7:1: +7:2
-+         _0 = _5;                         // scope 0 at $DIR/sroa.rs:+6:5: +6:23
-+         StorageDead(_4);                 // scope 0 at $DIR/sroa.rs:+7:1: +7:2
-+         StorageDead(_5);                 // scope 0 at $DIR/sroa.rs:+7:1: +7:2
-+         nop;                             // scope 0 at $DIR/sroa.rs:+7:1: +7:2
-          return;                          // scope 0 at $DIR/sroa.rs:+7:2: +7:2
-      }
-  }
-  
diff --git a/tests/mir-opt/sroa.unions.ScalarReplacementOfAggregates.diff b/tests/mir-opt/sroa.unions.ScalarReplacementOfAggregates.diff
deleted file mode 100644
index adfb01385d4..00000000000
--- a/tests/mir-opt/sroa.unions.ScalarReplacementOfAggregates.diff
+++ /dev/null
@@ -1,23 +0,0 @@
-- // MIR for `unions` before ScalarReplacementOfAggregates
-+ // MIR for `unions` after ScalarReplacementOfAggregates
-  
-  fn unions(_1: f32) -> u32 {
-      debug a => _1;                       // in scope 0 at $DIR/sroa.rs:+0:15: +0:16
-      let mut _0: u32;                     // return place in scope 0 at $DIR/sroa.rs:+0:26: +0:29
-      let mut _2: unions::Repr;            // in scope 0 at $DIR/sroa.rs:+5:14: +5:27
-      let mut _3: f32;                     // in scope 0 at $DIR/sroa.rs:+5:24: +5:25
-      scope 1 {
-      }
-  
-      bb0: {
-          StorageLive(_2);                 // scope 1 at $DIR/sroa.rs:+5:14: +5:27
-          StorageLive(_3);                 // scope 1 at $DIR/sroa.rs:+5:24: +5:25
-          _3 = _1;                         // scope 1 at $DIR/sroa.rs:+5:24: +5:25
-          _2 = Repr { f: move _3 };        // scope 1 at $DIR/sroa.rs:+5:14: +5:27
-          StorageDead(_3);                 // scope 1 at $DIR/sroa.rs:+5:26: +5:27
-          _0 = (_2.1: u32);                // scope 1 at $DIR/sroa.rs:+5:14: +5:29
-          StorageDead(_2);                 // scope 0 at $DIR/sroa.rs:+6:1: +6:2
-          return;                          // scope 0 at $DIR/sroa.rs:+6:2: +6:2
-      }
-  }
-  
diff --git a/tests/mir-opt/sroa/lifetimes.foo.ScalarReplacementOfAggregates.diff b/tests/mir-opt/sroa/lifetimes.foo.ScalarReplacementOfAggregates.diff
new file mode 100644
index 00000000000..225f80ed41b
--- /dev/null
+++ b/tests/mir-opt/sroa/lifetimes.foo.ScalarReplacementOfAggregates.diff
@@ -0,0 +1,214 @@
+- // MIR for `foo` before ScalarReplacementOfAggregates
++ // MIR for `foo` after ScalarReplacementOfAggregates
+  
+  fn foo() -> () {
+      let mut _0: ();                      // return place in scope 0 at $DIR/lifetimes.rs:+0:18: +0:18
+      let _1: Foo<T>;                      // in scope 0 at $DIR/lifetimes.rs:+1:9: +1:12
+      let mut _2: std::result::Result<std::boxed::Box<dyn std::fmt::Display>, <T as Err>::Err>; // in scope 0 at $DIR/lifetimes.rs:+2:12: +2:31
+      let mut _3: std::boxed::Box<dyn std::fmt::Display>; // in scope 0 at $DIR/lifetimes.rs:+2:15: +2:30
+      let mut _4: std::boxed::Box<u32>;    // in scope 0 at $DIR/lifetimes.rs:+2:15: +2:30
+      let mut _7: isize;                   // in scope 0 at $DIR/lifetimes.rs:+9:12: +9:17
+      let _9: ();                          // in scope 0 at $SRC_DIR/std/src/macros.rs:LL:COL
+      let _10: ();                         // in scope 0 at $SRC_DIR/std/src/macros.rs:LL:COL
+      let mut _11: std::fmt::Arguments<'_>; // in scope 0 at $SRC_DIR/std/src/macros.rs:LL:COL
+      let mut _12: &[&str];                // in scope 0 at $DIR/lifetimes.rs:+10:19: +10:28
+      let mut _13: &[&str; 3];             // in scope 0 at $DIR/lifetimes.rs:+10:19: +10:28
+      let _14: &[&str; 3];                 // in scope 0 at $DIR/lifetimes.rs:+10:19: +10:28
+      let _15: [&str; 3];                  // in scope 0 at $DIR/lifetimes.rs:+10:19: +10:28
+      let mut _16: &[core::fmt::ArgumentV1<'_>]; // in scope 0 at $SRC_DIR/std/src/macros.rs:LL:COL
+      let mut _17: &[core::fmt::ArgumentV1<'_>; 2]; // in scope 0 at $SRC_DIR/std/src/macros.rs:LL:COL
+      let _18: &[core::fmt::ArgumentV1<'_>; 2]; // in scope 0 at $SRC_DIR/std/src/macros.rs:LL:COL
+      let _19: [core::fmt::ArgumentV1<'_>; 2]; // in scope 0 at $SRC_DIR/std/src/macros.rs:LL:COL
+      let mut _20: core::fmt::ArgumentV1<'_>; // in scope 0 at $DIR/lifetimes.rs:+10:21: +10:22
+      let mut _21: &std::boxed::Box<dyn std::fmt::Display>; // in scope 0 at $DIR/lifetimes.rs:+10:21: +10:22
+      let _22: &std::boxed::Box<dyn std::fmt::Display>; // in scope 0 at $DIR/lifetimes.rs:+10:21: +10:22
+      let mut _23: core::fmt::ArgumentV1<'_>; // in scope 0 at $DIR/lifetimes.rs:+10:25: +10:26
+      let mut _24: &u32;                   // in scope 0 at $DIR/lifetimes.rs:+10:25: +10:26
+      let _25: &u32;                       // in scope 0 at $DIR/lifetimes.rs:+10:25: +10:26
+      let mut _27: bool;                   // in scope 0 at $DIR/lifetimes.rs:+12:1: +12:2
+      let mut _28: isize;                  // in scope 0 at $DIR/lifetimes.rs:+12:1: +12:2
+      let mut _29: isize;                  // in scope 0 at $DIR/lifetimes.rs:+12:1: +12:2
+      let mut _30: isize;                  // in scope 0 at $DIR/lifetimes.rs:+12:1: +12:2
++     let _31: std::result::Result<std::boxed::Box<dyn std::fmt::Display>, <T as Err>::Err>; // in scope 0 at $DIR/lifetimes.rs:+1:9: +1:12
++     let _32: u32;                        // in scope 0 at $DIR/lifetimes.rs:+1:9: +1:12
+      scope 1 {
+-         debug foo => _1;                 // in scope 1 at $DIR/lifetimes.rs:+1:9: +1:12
++         debug foo => Foo<T>{ .0 => _31, .1 => _32, }; // in scope 1 at $DIR/lifetimes.rs:+1:9: +1:12
+          let _5: std::result::Result<std::boxed::Box<dyn std::fmt::Display>, <T as Err>::Err>; // in scope 1 at $DIR/lifetimes.rs:+6:9: +6:10
+          scope 2 {
+              debug x => _5;               // in scope 2 at $DIR/lifetimes.rs:+6:9: +6:10
+              let _6: u32;                 // in scope 2 at $DIR/lifetimes.rs:+7:9: +7:10
+              scope 3 {
+                  debug y => _6;           // in scope 3 at $DIR/lifetimes.rs:+7:9: +7:10
+                  scope 4 {
+                      debug x => _8;       // in scope 4 at $DIR/lifetimes.rs:+9:15: +9:16
+                      let _8: std::boxed::Box<dyn std::fmt::Display>; // in scope 4 at $DIR/lifetimes.rs:+9:15: +9:16
+                      let mut _26: &[&str; 3]; // in scope 4 at $DIR/lifetimes.rs:+10:19: +10:28
+                  }
+              }
+          }
+      }
+  
+      bb0: {
+          _27 = const false;               // scope 0 at $DIR/lifetimes.rs:+1:9: +1:12
+-         StorageLive(_1);                 // scope 0 at $DIR/lifetimes.rs:+1:9: +1:12
++         StorageLive(_31);                // scope 0 at $DIR/lifetimes.rs:+1:9: +1:12
++         StorageLive(_32);                // scope 0 at $DIR/lifetimes.rs:+1:9: +1:12
++         nop;                             // scope 0 at $DIR/lifetimes.rs:+1:9: +1:12
+          StorageLive(_2);                 // scope 0 at $DIR/lifetimes.rs:+2:12: +2:31
+          StorageLive(_3);                 // scope 0 at $DIR/lifetimes.rs:+2:15: +2:30
+          StorageLive(_4);                 // scope 0 at $DIR/lifetimes.rs:+2:15: +2:30
+          _4 = Box::<u32>::new(const 5_u32) -> bb1; // scope 0 at $DIR/lifetimes.rs:+2:15: +2:30
+                                           // mir::Constant
+                                           // + span: $DIR/lifetimes.rs:19:15: 19:23
+                                           // + user_ty: UserType(1)
+                                           // + literal: Const { ty: fn(u32) -> Box<u32> {Box::<u32>::new}, val: Value(<ZST>) }
+      }
+  
+      bb1: {
+          _3 = move _4 as std::boxed::Box<dyn std::fmt::Display> (Pointer(Unsize)); // scope 0 at $DIR/lifetimes.rs:+2:15: +2:30
+          StorageDead(_4);                 // scope 0 at $DIR/lifetimes.rs:+2:29: +2:30
+          _2 = Result::<Box<dyn std::fmt::Display>, <T as Err>::Err>::Ok(move _3); // scope 0 at $DIR/lifetimes.rs:+2:12: +2:31
+          StorageDead(_3);                 // scope 0 at $DIR/lifetimes.rs:+2:30: +2:31
+-         _1 = Foo::<T> { x: move _2, y: const 7_u32 }; // scope 0 at $DIR/lifetimes.rs:+1:23: +4:6
++         _31 = move _2;                   // scope 0 at $DIR/lifetimes.rs:+1:23: +4:6
++         _32 = const 7_u32;               // scope 0 at $DIR/lifetimes.rs:+1:23: +4:6
++         nop;                             // scope 0 at $DIR/lifetimes.rs:+1:23: +4:6
+          StorageDead(_2);                 // scope 0 at $DIR/lifetimes.rs:+4:5: +4:6
+          StorageLive(_5);                 // scope 1 at $DIR/lifetimes.rs:+6:9: +6:10
+          _27 = const true;                // scope 1 at $DIR/lifetimes.rs:+6:13: +6:18
+-         _5 = move (_1.0: std::result::Result<std::boxed::Box<dyn std::fmt::Display>, <T as Err>::Err>); // scope 1 at $DIR/lifetimes.rs:+6:13: +6:18
++         _5 = move _31;                   // scope 1 at $DIR/lifetimes.rs:+6:13: +6:18
+          StorageLive(_6);                 // scope 2 at $DIR/lifetimes.rs:+7:9: +7:10
+-         _6 = (_1.1: u32);                // scope 2 at $DIR/lifetimes.rs:+7:13: +7:18
++         _6 = _32;                        // scope 2 at $DIR/lifetimes.rs:+7:13: +7:18
+          _7 = discriminant(_5);           // scope 4 at $DIR/lifetimes.rs:+9:12: +9:17
+          switchInt(move _7) -> [0: bb2, otherwise: bb7]; // scope 4 at $DIR/lifetimes.rs:+9:12: +9:17
+      }
+  
+      bb2: {
+          StorageLive(_8);                 // scope 4 at $DIR/lifetimes.rs:+9:15: +9:16
+          _27 = const false;               // scope 4 at $DIR/lifetimes.rs:+9:15: +9:16
+          _8 = move ((_5 as Ok).0: std::boxed::Box<dyn std::fmt::Display>); // scope 4 at $DIR/lifetimes.rs:+9:15: +9:16
+          StorageLive(_9);                 // scope 4 at $SRC_DIR/std/src/macros.rs:LL:COL
+          StorageLive(_10);                // scope 4 at $SRC_DIR/std/src/macros.rs:LL:COL
+          StorageLive(_11);                // scope 4 at $SRC_DIR/std/src/macros.rs:LL:COL
+          StorageLive(_12);                // scope 4 at $DIR/lifetimes.rs:+10:19: +10:28
+          StorageLive(_13);                // scope 4 at $DIR/lifetimes.rs:+10:19: +10:28
+          StorageLive(_14);                // scope 4 at $DIR/lifetimes.rs:+10:19: +10:28
+          _26 = const _;                   // scope 4 at $DIR/lifetimes.rs:+10:19: +10:28
+                                           // mir::Constant
+                                           // + span: $DIR/lifetimes.rs:27:19: 27:28
+                                           // + literal: Const { ty: &[&str; 3], val: Unevaluated(foo, [T], Some(promoted[0])) }
+          _14 = &(*_26);                   // scope 4 at $DIR/lifetimes.rs:+10:19: +10:28
+          _13 = &(*_14);                   // scope 4 at $DIR/lifetimes.rs:+10:19: +10:28
+          _12 = move _13 as &[&str] (Pointer(Unsize)); // scope 4 at $DIR/lifetimes.rs:+10:19: +10:28
+          StorageDead(_13);                // scope 4 at $DIR/lifetimes.rs:+10:27: +10:28
+          StorageLive(_16);                // scope 4 at $SRC_DIR/std/src/macros.rs:LL:COL
+          StorageLive(_17);                // scope 4 at $SRC_DIR/std/src/macros.rs:LL:COL
+          StorageLive(_18);                // scope 4 at $SRC_DIR/std/src/macros.rs:LL:COL
+          StorageLive(_19);                // scope 4 at $SRC_DIR/std/src/macros.rs:LL:COL
+          StorageLive(_20);                // scope 4 at $DIR/lifetimes.rs:+10:21: +10:22
+          StorageLive(_21);                // scope 4 at $DIR/lifetimes.rs:+10:21: +10:22
+          StorageLive(_22);                // scope 4 at $DIR/lifetimes.rs:+10:21: +10:22
+          _22 = &_8;                       // scope 4 at $DIR/lifetimes.rs:+10:21: +10:22
+          _21 = &(*_22);                   // scope 4 at $DIR/lifetimes.rs:+10:21: +10:22
+          _20 = core::fmt::ArgumentV1::<'_>::new_display::<Box<dyn std::fmt::Display>>(move _21) -> bb3; // scope 4 at $DIR/lifetimes.rs:+10:21: +10:22
+                                           // mir::Constant
+                                           // + span: $DIR/lifetimes.rs:27:21: 27:22
+                                           // + user_ty: UserType(4)
+                                           // + literal: Const { ty: for<'b> fn(&'b Box<dyn std::fmt::Display>) -> core::fmt::ArgumentV1<'b> {core::fmt::ArgumentV1::<'_>::new_display::<Box<dyn std::fmt::Display>>}, val: Value(<ZST>) }
+      }
+  
+      bb3: {
+          StorageDead(_21);                // scope 4 at $DIR/lifetimes.rs:+10:21: +10:22
+          StorageLive(_23);                // scope 4 at $DIR/lifetimes.rs:+10:25: +10:26
+          StorageLive(_24);                // scope 4 at $DIR/lifetimes.rs:+10:25: +10:26
+          StorageLive(_25);                // scope 4 at $DIR/lifetimes.rs:+10:25: +10:26
+          _25 = &_6;                       // scope 4 at $DIR/lifetimes.rs:+10:25: +10:26
+          _24 = &(*_25);                   // scope 4 at $DIR/lifetimes.rs:+10:25: +10:26
+          _23 = core::fmt::ArgumentV1::<'_>::new_display::<u32>(move _24) -> bb4; // scope 4 at $DIR/lifetimes.rs:+10:25: +10:26
+                                           // mir::Constant
+                                           // + span: $DIR/lifetimes.rs:27:25: 27:26
+                                           // + user_ty: UserType(5)
+                                           // + literal: Const { ty: for<'b> fn(&'b u32) -> core::fmt::ArgumentV1<'b> {core::fmt::ArgumentV1::<'_>::new_display::<u32>}, val: Value(<ZST>) }
+      }
+  
+      bb4: {
+          StorageDead(_24);                // scope 4 at $DIR/lifetimes.rs:+10:25: +10:26
+          _19 = [move _20, move _23];      // scope 4 at $SRC_DIR/std/src/macros.rs:LL:COL
+          StorageDead(_23);                // scope 4 at $SRC_DIR/std/src/macros.rs:LL:COL
+          StorageDead(_20);                // scope 4 at $SRC_DIR/std/src/macros.rs:LL:COL
+          _18 = &_19;                      // scope 4 at $SRC_DIR/std/src/macros.rs:LL:COL
+          _17 = &(*_18);                   // scope 4 at $SRC_DIR/std/src/macros.rs:LL:COL
+          _16 = move _17 as &[core::fmt::ArgumentV1<'_>] (Pointer(Unsize)); // scope 4 at $SRC_DIR/std/src/macros.rs:LL:COL
+          StorageDead(_17);                // scope 4 at $SRC_DIR/std/src/macros.rs:LL:COL
+          _11 = Arguments::<'_>::new_v1(move _12, move _16) -> bb5; // scope 4 at $SRC_DIR/std/src/macros.rs:LL:COL
+                                           // mir::Constant
+                                           // + span: $SRC_DIR/std/src/macros.rs:LL:COL
+                                           // + user_ty: UserType(3)
+                                           // + literal: Const { ty: fn(&[&'static str], &[core::fmt::ArgumentV1<'_>]) -> Arguments<'_> {Arguments::<'_>::new_v1}, val: Value(<ZST>) }
+      }
+  
+      bb5: {
+          StorageDead(_16);                // scope 4 at $SRC_DIR/std/src/macros.rs:LL:COL
+          StorageDead(_12);                // scope 4 at $SRC_DIR/std/src/macros.rs:LL:COL
+          _10 = _eprint(move _11) -> bb6;  // scope 4 at $SRC_DIR/std/src/macros.rs:LL:COL
+                                           // mir::Constant
+                                           // + span: $SRC_DIR/std/src/macros.rs:LL:COL
+                                           // + literal: Const { ty: for<'a> fn(Arguments<'a>) {_eprint}, val: Value(<ZST>) }
+      }
+  
+      bb6: {
+          StorageDead(_11);                // scope 4 at $SRC_DIR/std/src/macros.rs:LL:COL
+          StorageDead(_25);                // scope 4 at $SRC_DIR/std/src/macros.rs:LL:COL
+          StorageDead(_22);                // scope 4 at $SRC_DIR/std/src/macros.rs:LL:COL
+          StorageDead(_19);                // scope 4 at $SRC_DIR/std/src/macros.rs:LL:COL
+          StorageDead(_18);                // scope 4 at $SRC_DIR/std/src/macros.rs:LL:COL
+          StorageDead(_14);                // scope 4 at $SRC_DIR/std/src/macros.rs:LL:COL
+          StorageDead(_10);                // scope 4 at $SRC_DIR/std/src/macros.rs:LL:COL
+          _9 = const ();                   // scope 4 at $SRC_DIR/std/src/macros.rs:LL:COL
+          StorageDead(_9);                 // scope 4 at $SRC_DIR/std/src/macros.rs:LL:COL
+          _0 = const ();                   // scope 4 at $DIR/lifetimes.rs:+9:22: +11:6
+          drop(_8) -> bb8;                 // scope 3 at $DIR/lifetimes.rs:+11:5: +11:6
+      }
+  
+      bb7: {
+          _0 = const ();                   // scope 3 at $DIR/lifetimes.rs:+11:6: +11:6
+          goto -> bb9;                     // scope 3 at $DIR/lifetimes.rs:+9:5: +11:6
+      }
+  
+      bb8: {
+          StorageDead(_8);                 // scope 3 at $DIR/lifetimes.rs:+11:5: +11:6
+          goto -> bb9;                     // scope 3 at $DIR/lifetimes.rs:+9:5: +11:6
+      }
+  
+      bb9: {
+          StorageDead(_6);                 // scope 2 at $DIR/lifetimes.rs:+12:1: +12:2
+          _28 = discriminant(_5);          // scope 1 at $DIR/lifetimes.rs:+12:1: +12:2
+          switchInt(move _28) -> [0: bb11, otherwise: bb13]; // scope 1 at $DIR/lifetimes.rs:+12:1: +12:2
+      }
+  
+      bb10: {
+          _27 = const false;               // scope 1 at $DIR/lifetimes.rs:+12:1: +12:2
+          StorageDead(_5);                 // scope 1 at $DIR/lifetimes.rs:+12:1: +12:2
+-         StorageDead(_1);                 // scope 0 at $DIR/lifetimes.rs:+12:1: +12:2
++         StorageDead(_31);                // scope 0 at $DIR/lifetimes.rs:+12:1: +12:2
++         StorageDead(_32);                // scope 0 at $DIR/lifetimes.rs:+12:1: +12:2
++         nop;                             // scope 0 at $DIR/lifetimes.rs:+12:1: +12:2
+          return;                          // scope 0 at $DIR/lifetimes.rs:+12:2: +12:2
+      }
+  
+      bb11: {
+          switchInt(_27) -> [0: bb10, otherwise: bb12]; // scope 1 at $DIR/lifetimes.rs:+12:1: +12:2
+      }
+  
+      bb12: {
+          drop(((_5 as Ok).0: std::boxed::Box<dyn std::fmt::Display>)) -> bb10; // scope 1 at $DIR/lifetimes.rs:+12:1: +12:2
+      }
+  
+      bb13: {
+          drop(_5) -> bb10;                // scope 1 at $DIR/lifetimes.rs:+12:1: +12:2
+      }
+  }
+  
diff --git a/tests/mir-opt/sroa/lifetimes.rs b/tests/mir-opt/sroa/lifetimes.rs
new file mode 100644
index 00000000000..2356d212f3f
--- /dev/null
+++ b/tests/mir-opt/sroa/lifetimes.rs
@@ -0,0 +1,37 @@
+// unit-test: ScalarReplacementOfAggregates
+// compile-flags: -Cpanic=abort
+// no-prefer-dynamic
+
+trait Err {
+    type Err;
+}
+
+struct Foo<T: Err> {
+    // Check that the `'static` lifetime is erased when creating the local for `x`,
+    // even if we fail to normalize the type.
+    x: Result<Box<dyn std::fmt::Display + 'static>, <T as Err>::Err>,
+    y: u32,
+}
+
+// EMIT_MIR lifetimes.foo.ScalarReplacementOfAggregates.diff
+fn foo<T: Err>() {
+    let foo: Foo<T> = Foo {
+        x: Ok(Box::new(5_u32)),
+        y: 7_u32,
+    };
+
+    let x = foo.x;
+    let y = foo.y;
+
+    if let Ok(x) = x {
+        eprintln!("{x} {y}");
+    }
+}
+
+impl Err for () {
+    type Err = ();
+}
+
+fn main() {
+    foo::<()>()
+}
diff --git a/tests/mir-opt/sroa/structs.constant.ScalarReplacementOfAggregates.diff b/tests/mir-opt/sroa/structs.constant.ScalarReplacementOfAggregates.diff
new file mode 100644
index 00000000000..647681f0e7a
--- /dev/null
+++ b/tests/mir-opt/sroa/structs.constant.ScalarReplacementOfAggregates.diff
@@ -0,0 +1,46 @@
+- // MIR for `constant` before ScalarReplacementOfAggregates
++ // MIR for `constant` after ScalarReplacementOfAggregates
+  
+  fn constant() -> () {
+      let mut _0: ();                      // return place in scope 0 at $DIR/structs.rs:+0:15: +0:15
+      let _1: (usize, u8);                 // in scope 0 at $DIR/structs.rs:+2:9: +2:10
++     let _4: usize;                       // in scope 0 at $DIR/structs.rs:+2:9: +2:10
++     let _5: u8;                          // in scope 0 at $DIR/structs.rs:+2:9: +2:10
+      scope 1 {
+-         debug y => _1;                   // in scope 1 at $DIR/structs.rs:+2:9: +2:10
++         debug y => (usize, u8){ .0 => _4, .1 => _5, }; // in scope 1 at $DIR/structs.rs:+2:9: +2:10
+          let _2: usize;                   // in scope 1 at $DIR/structs.rs:+3:9: +3:10
+          scope 2 {
+              debug t => _2;               // in scope 2 at $DIR/structs.rs:+3:9: +3:10
+              let _3: u8;                  // in scope 2 at $DIR/structs.rs:+4:9: +4:10
+              scope 3 {
+                  debug u => _3;           // in scope 3 at $DIR/structs.rs:+4:9: +4:10
+              }
+          }
+      }
+  
+      bb0: {
+-         StorageLive(_1);                 // scope 0 at $DIR/structs.rs:+2:9: +2:10
++         StorageLive(_4);                 // scope 0 at $DIR/structs.rs:+2:9: +2:10
++         StorageLive(_5);                 // scope 0 at $DIR/structs.rs:+2:9: +2:10
++         nop;                             // scope 0 at $DIR/structs.rs:+2:9: +2:10
+          _1 = const _;                    // scope 0 at $DIR/structs.rs:+2:13: +2:14
++         _4 = move (_1.0: usize);         // scope 1 at $DIR/structs.rs:+3:9: +3:10
++         _5 = move (_1.1: u8);            // scope 1 at $DIR/structs.rs:+3:9: +3:10
+          StorageLive(_2);                 // scope 1 at $DIR/structs.rs:+3:9: +3:10
+-         _2 = (_1.0: usize);              // scope 1 at $DIR/structs.rs:+3:13: +3:16
++         _2 = _4;                         // scope 1 at $DIR/structs.rs:+3:13: +3:16
+          StorageLive(_3);                 // scope 2 at $DIR/structs.rs:+4:9: +4:10
+-         _3 = (_1.1: u8);                 // scope 2 at $DIR/structs.rs:+4:13: +4:16
++         _3 = _5;                         // scope 2 at $DIR/structs.rs:+4:13: +4:16
+          _0 = const ();                   // scope 0 at $DIR/structs.rs:+0:15: +5:2
+          StorageDead(_3);                 // scope 2 at $DIR/structs.rs:+5:1: +5:2
+          StorageDead(_2);                 // scope 1 at $DIR/structs.rs:+5:1: +5:2
+-         StorageDead(_1);                 // scope 0 at $DIR/structs.rs:+5:1: +5:2
++         StorageDead(_4);                 // scope 0 at $DIR/structs.rs:+5:1: +5:2
++         StorageDead(_5);                 // scope 0 at $DIR/structs.rs:+5:1: +5:2
++         nop;                             // scope 0 at $DIR/structs.rs:+5:1: +5:2
+          return;                          // scope 0 at $DIR/structs.rs:+5:2: +5:2
+      }
+  }
+  
diff --git a/tests/mir-opt/sroa/structs.copies.ScalarReplacementOfAggregates.diff b/tests/mir-opt/sroa/structs.copies.ScalarReplacementOfAggregates.diff
new file mode 100644
index 00000000000..b0b0da8861f
--- /dev/null
+++ b/tests/mir-opt/sroa/structs.copies.ScalarReplacementOfAggregates.diff
@@ -0,0 +1,91 @@
+- // MIR for `copies` before ScalarReplacementOfAggregates
++ // MIR for `copies` after ScalarReplacementOfAggregates
+  
+  fn copies(_1: Foo) -> () {
+      debug x => _1;                       // in scope 0 at $DIR/structs.rs:+0:11: +0:12
+      let mut _0: ();                      // return place in scope 0 at $DIR/structs.rs:+0:19: +0:19
+      let _2: Foo;                         // in scope 0 at $DIR/structs.rs:+1:9: +1:10
++     let _11: u8;                         // in scope 0 at $DIR/structs.rs:+1:9: +1:10
++     let _12: ();                         // in scope 0 at $DIR/structs.rs:+1:9: +1:10
++     let _13: &str;                       // in scope 0 at $DIR/structs.rs:+1:9: +1:10
++     let _14: std::option::Option<isize>; // in scope 0 at $DIR/structs.rs:+1:9: +1:10
+      scope 1 {
+-         debug y => _2;                   // in scope 1 at $DIR/structs.rs:+1:9: +1:10
++         debug y => Foo{ .0 => _11, .1 => _12, .2 => _13, .3 => _14, }; // in scope 1 at $DIR/structs.rs:+1:9: +1:10
+          let _3: u8;                      // in scope 1 at $DIR/structs.rs:+2:9: +2:10
+          scope 2 {
+              debug t => _3;               // in scope 2 at $DIR/structs.rs:+2:9: +2:10
+              let _4: &str;                // in scope 2 at $DIR/structs.rs:+3:9: +3:10
+              scope 3 {
+                  debug u => _4;           // in scope 3 at $DIR/structs.rs:+3:9: +3:10
+                  let _5: Foo;             // in scope 3 at $DIR/structs.rs:+4:9: +4:10
++                 let _7: u8;              // in scope 3 at $DIR/structs.rs:+4:9: +4:10
++                 let _8: ();              // in scope 3 at $DIR/structs.rs:+4:9: +4:10
++                 let _9: &str;            // in scope 3 at $DIR/structs.rs:+4:9: +4:10
++                 let _10: std::option::Option<isize>; // in scope 3 at $DIR/structs.rs:+4:9: +4:10
+                  scope 4 {
+-                     debug z => _5;       // in scope 4 at $DIR/structs.rs:+4:9: +4:10
++                     debug z => Foo{ .0 => _7, .1 => _8, .2 => _9, .3 => _10, }; // in scope 4 at $DIR/structs.rs:+4:9: +4:10
+                      let _6: ();          // in scope 4 at $DIR/structs.rs:+5:9: +5:10
+                      scope 5 {
+                          debug a => _6;   // in scope 5 at $DIR/structs.rs:+5:9: +5:10
+                      }
+                  }
+              }
+          }
+      }
+  
+      bb0: {
+-         StorageLive(_2);                 // scope 0 at $DIR/structs.rs:+1:9: +1:10
+-         _2 = _1;                         // scope 0 at $DIR/structs.rs:+1:13: +1:14
++         StorageLive(_11);                // scope 0 at $DIR/structs.rs:+1:9: +1:10
++         StorageLive(_12);                // scope 0 at $DIR/structs.rs:+1:9: +1:10
++         StorageLive(_13);                // scope 0 at $DIR/structs.rs:+1:9: +1:10
++         StorageLive(_14);                // scope 0 at $DIR/structs.rs:+1:9: +1:10
++         nop;                             // scope 0 at $DIR/structs.rs:+1:9: +1:10
++         _11 = (_1.0: u8);                // scope 0 at $DIR/structs.rs:+1:13: +1:14
++         _12 = (_1.1: ());                // scope 0 at $DIR/structs.rs:+1:13: +1:14
++         _13 = (_1.2: &str);              // scope 0 at $DIR/structs.rs:+1:13: +1:14
++         _14 = (_1.3: std::option::Option<isize>); // scope 0 at $DIR/structs.rs:+1:13: +1:14
++         nop;                             // scope 0 at $DIR/structs.rs:+1:13: +1:14
+          StorageLive(_3);                 // scope 1 at $DIR/structs.rs:+2:9: +2:10
+-         _3 = (_2.0: u8);                 // scope 1 at $DIR/structs.rs:+2:13: +2:16
++         _3 = _11;                        // scope 1 at $DIR/structs.rs:+2:13: +2:16
+          StorageLive(_4);                 // scope 2 at $DIR/structs.rs:+3:9: +3:10
+-         _4 = (_2.2: &str);               // scope 2 at $DIR/structs.rs:+3:13: +3:16
+-         StorageLive(_5);                 // scope 3 at $DIR/structs.rs:+4:9: +4:10
+-         _5 = _2;                         // scope 3 at $DIR/structs.rs:+4:13: +4:14
++         _4 = _13;                        // scope 2 at $DIR/structs.rs:+3:13: +3:16
++         StorageLive(_7);                 // scope 3 at $DIR/structs.rs:+4:9: +4:10
++         StorageLive(_8);                 // scope 3 at $DIR/structs.rs:+4:9: +4:10
++         StorageLive(_9);                 // scope 3 at $DIR/structs.rs:+4:9: +4:10
++         StorageLive(_10);                // scope 3 at $DIR/structs.rs:+4:9: +4:10
++         nop;                             // scope 3 at $DIR/structs.rs:+4:9: +4:10
++         _7 = _11;                        // scope 3 at $DIR/structs.rs:+4:13: +4:14
++         _8 = _12;                        // scope 3 at $DIR/structs.rs:+4:13: +4:14
++         _9 = _13;                        // scope 3 at $DIR/structs.rs:+4:13: +4:14
++         _10 = _14;                       // scope 3 at $DIR/structs.rs:+4:13: +4:14
++         nop;                             // scope 3 at $DIR/structs.rs:+4:13: +4:14
+          StorageLive(_6);                 // scope 4 at $DIR/structs.rs:+5:9: +5:10
+-         _6 = (_5.1: ());                 // scope 4 at $DIR/structs.rs:+5:13: +5:16
++         _6 = _8;                         // scope 4 at $DIR/structs.rs:+5:13: +5:16
+          _0 = const ();                   // scope 0 at $DIR/structs.rs:+0:19: +6:2
+          StorageDead(_6);                 // scope 4 at $DIR/structs.rs:+6:1: +6:2
+-         StorageDead(_5);                 // scope 3 at $DIR/structs.rs:+6:1: +6:2
++         StorageDead(_7);                 // scope 3 at $DIR/structs.rs:+6:1: +6:2
++         StorageDead(_8);                 // scope 3 at $DIR/structs.rs:+6:1: +6:2
++         StorageDead(_9);                 // scope 3 at $DIR/structs.rs:+6:1: +6:2
++         StorageDead(_10);                // scope 3 at $DIR/structs.rs:+6:1: +6:2
++         nop;                             // scope 3 at $DIR/structs.rs:+6:1: +6:2
+          StorageDead(_4);                 // scope 2 at $DIR/structs.rs:+6:1: +6:2
+          StorageDead(_3);                 // scope 1 at $DIR/structs.rs:+6:1: +6:2
+-         StorageDead(_2);                 // scope 0 at $DIR/structs.rs:+6:1: +6:2
++         StorageDead(_11);                // scope 0 at $DIR/structs.rs:+6:1: +6:2
++         StorageDead(_12);                // scope 0 at $DIR/structs.rs:+6:1: +6:2
++         StorageDead(_13);                // scope 0 at $DIR/structs.rs:+6:1: +6:2
++         StorageDead(_14);                // scope 0 at $DIR/structs.rs:+6:1: +6:2
++         nop;                             // scope 0 at $DIR/structs.rs:+6:1: +6:2
+          return;                          // scope 0 at $DIR/structs.rs:+6:2: +6:2
+      }
+  }
+  
diff --git a/tests/mir-opt/sroa/structs.dropping.ScalarReplacementOfAggregates.diff b/tests/mir-opt/sroa/structs.dropping.ScalarReplacementOfAggregates.diff
new file mode 100644
index 00000000000..b6439c00a00
--- /dev/null
+++ b/tests/mir-opt/sroa/structs.dropping.ScalarReplacementOfAggregates.diff
@@ -0,0 +1,44 @@
+- // MIR for `dropping` before ScalarReplacementOfAggregates
++ // MIR for `dropping` after ScalarReplacementOfAggregates
+  
+  fn dropping() -> () {
+      let mut _0: ();                      // return place in scope 0 at $DIR/structs.rs:+0:19: +0:19
+      let _1: Tag;                         // in scope 0 at $DIR/structs.rs:+1:5: +1:32
+      let mut _2: S;                       // in scope 0 at $DIR/structs.rs:+1:5: +1:30
+      let mut _3: Tag;                     // in scope 0 at $DIR/structs.rs:+1:7: +1:13
+      let mut _4: Tag;                     // in scope 0 at $DIR/structs.rs:+1:15: +1:21
+      let mut _5: Tag;                     // in scope 0 at $DIR/structs.rs:+1:23: +1:29
+  
+      bb0: {
+          StorageLive(_1);                 // scope 0 at $DIR/structs.rs:+1:5: +1:32
+          StorageLive(_2);                 // scope 0 at $DIR/structs.rs:+1:5: +1:30
+          StorageLive(_3);                 // scope 0 at $DIR/structs.rs:+1:7: +1:13
+          _3 = Tag(const 0_usize);         // scope 0 at $DIR/structs.rs:+1:7: +1:13
+          StorageLive(_4);                 // scope 0 at $DIR/structs.rs:+1:15: +1:21
+          _4 = Tag(const 1_usize);         // scope 0 at $DIR/structs.rs:+1:15: +1:21
+          StorageLive(_5);                 // scope 0 at $DIR/structs.rs:+1:23: +1:29
+          _5 = Tag(const 2_usize);         // scope 0 at $DIR/structs.rs:+1:23: +1:29
+          _2 = S(move _3, move _4, move _5); // scope 0 at $DIR/structs.rs:+1:5: +1:30
+          StorageDead(_5);                 // scope 0 at $DIR/structs.rs:+1:29: +1:30
+          StorageDead(_4);                 // scope 0 at $DIR/structs.rs:+1:29: +1:30
+          StorageDead(_3);                 // scope 0 at $DIR/structs.rs:+1:29: +1:30
+          _1 = move (_2.1: Tag);           // scope 0 at $DIR/structs.rs:+1:5: +1:32
+          drop(_1) -> bb1;                 // scope 0 at $DIR/structs.rs:+1:32: +1:33
+      }
+  
+      bb1: {
+          drop((_2.0: Tag)) -> bb3;        // scope 0 at $DIR/structs.rs:+1:32: +1:33
+      }
+  
+      bb2: {
+          StorageDead(_2);                 // scope 0 at $DIR/structs.rs:+1:32: +1:33
+          StorageDead(_1);                 // scope 0 at $DIR/structs.rs:+1:32: +1:33
+          _0 = const ();                   // scope 0 at $DIR/structs.rs:+0:19: +2:2
+          return;                          // scope 0 at $DIR/structs.rs:+2:2: +2:2
+      }
+  
+      bb3: {
+          drop((_2.2: Tag)) -> bb2;        // scope 0 at $DIR/structs.rs:+1:32: +1:33
+      }
+  }
+  
diff --git a/tests/mir-opt/sroa/structs.enums.ScalarReplacementOfAggregates.diff b/tests/mir-opt/sroa/structs.enums.ScalarReplacementOfAggregates.diff
new file mode 100644
index 00000000000..ff1e30c2d8f
--- /dev/null
+++ b/tests/mir-opt/sroa/structs.enums.ScalarReplacementOfAggregates.diff
@@ -0,0 +1,43 @@
+- // MIR for `enums` before ScalarReplacementOfAggregates
++ // MIR for `enums` after ScalarReplacementOfAggregates
+  
+  fn enums(_1: usize) -> usize {
+      debug a => _1;                       // in scope 0 at $DIR/structs.rs:+0:14: +0:15
+      let mut _0: usize;                   // return place in scope 0 at $DIR/structs.rs:+0:27: +0:32
+      let mut _2: std::option::Option<usize>; // in scope 0 at $DIR/structs.rs:+1:22: +1:29
+      let mut _3: usize;                   // in scope 0 at $DIR/structs.rs:+1:27: +1:28
+      let mut _4: isize;                   // in scope 0 at $DIR/structs.rs:+1:12: +1:19
+      scope 1 {
+          debug a => _5;                   // in scope 1 at $DIR/structs.rs:+1:17: +1:18
+          let _5: usize;                   // in scope 1 at $DIR/structs.rs:+1:17: +1:18
+      }
+  
+      bb0: {
+          StorageLive(_2);                 // scope 1 at $DIR/structs.rs:+1:22: +1:29
+          StorageLive(_3);                 // scope 1 at $DIR/structs.rs:+1:27: +1:28
+          _3 = _1;                         // scope 1 at $DIR/structs.rs:+1:27: +1:28
+          _2 = Option::<usize>::Some(move _3); // scope 1 at $DIR/structs.rs:+1:22: +1:29
+          StorageDead(_3);                 // scope 1 at $DIR/structs.rs:+1:28: +1:29
+          _4 = discriminant(_2);           // scope 1 at $DIR/structs.rs:+1:12: +1:19
+          switchInt(move _4) -> [1: bb1, otherwise: bb2]; // scope 1 at $DIR/structs.rs:+1:12: +1:19
+      }
+  
+      bb1: {
+          StorageLive(_5);                 // scope 1 at $DIR/structs.rs:+1:17: +1:18
+          _5 = ((_2 as Some).0: usize);    // scope 1 at $DIR/structs.rs:+1:17: +1:18
+          _0 = _5;                         // scope 1 at $DIR/structs.rs:+1:32: +1:33
+          StorageDead(_5);                 // scope 0 at $DIR/structs.rs:+1:34: +1:35
+          goto -> bb3;                     // scope 0 at $DIR/structs.rs:+1:5: +1:46
+      }
+  
+      bb2: {
+          _0 = const 0_usize;              // scope 0 at $DIR/structs.rs:+1:43: +1:44
+          goto -> bb3;                     // scope 0 at $DIR/structs.rs:+1:5: +1:46
+      }
+  
+      bb3: {
+          StorageDead(_2);                 // scope 0 at $DIR/structs.rs:+2:1: +2:2
+          return;                          // scope 0 at $DIR/structs.rs:+2:2: +2:2
+      }
+  }
+  
diff --git a/tests/mir-opt/sroa/structs.escaping.ScalarReplacementOfAggregates.diff b/tests/mir-opt/sroa/structs.escaping.ScalarReplacementOfAggregates.diff
new file mode 100644
index 00000000000..d45823d4bac
--- /dev/null
+++ b/tests/mir-opt/sroa/structs.escaping.ScalarReplacementOfAggregates.diff
@@ -0,0 +1,44 @@
+- // MIR for `escaping` before ScalarReplacementOfAggregates
++ // MIR for `escaping` after ScalarReplacementOfAggregates
+  
+  fn escaping() -> () {
+      let mut _0: ();                      // return place in scope 0 at $DIR/structs.rs:+0:19: +0:19
+      let _1: ();                          // in scope 0 at $DIR/structs.rs:+1:5: +1:42
+      let mut _2: *const u32;              // in scope 0 at $DIR/structs.rs:+1:7: +1:41
+      let _3: &u32;                        // in scope 0 at $DIR/structs.rs:+1:7: +1:41
+      let _4: Escaping;                    // in scope 0 at $DIR/structs.rs:+1:8: +1:39
+      let mut _5: u32;                     // in scope 0 at $DIR/structs.rs:+1:34: +1:37
+  
+      bb0: {
+          StorageLive(_1);                 // scope 0 at $DIR/structs.rs:+1:5: +1:42
+          StorageLive(_2);                 // scope 0 at $DIR/structs.rs:+1:7: +1:41
+          StorageLive(_3);                 // scope 0 at $DIR/structs.rs:+1:7: +1:41
+          StorageLive(_4);                 // scope 0 at $DIR/structs.rs:+1:8: +1:39
+          StorageLive(_5);                 // scope 0 at $DIR/structs.rs:+1:34: +1:37
+          _5 = g() -> bb1;                 // scope 0 at $DIR/structs.rs:+1:34: +1:37
+                                           // mir::Constant
+                                           // + span: $DIR/structs.rs:78:34: 78:35
+                                           // + literal: Const { ty: fn() -> u32 {g}, val: Value(<ZST>) }
+      }
+  
+      bb1: {
+          _4 = Escaping { a: const 1_u32, b: const 2_u32, c: move _5 }; // scope 0 at $DIR/structs.rs:+1:8: +1:39
+          StorageDead(_5);                 // scope 0 at $DIR/structs.rs:+1:38: +1:39
+          _3 = &(_4.0: u32);               // scope 0 at $DIR/structs.rs:+1:7: +1:41
+          _2 = &raw const (*_3);           // scope 0 at $DIR/structs.rs:+1:7: +1:41
+          _1 = f(move _2) -> bb2;          // scope 0 at $DIR/structs.rs:+1:5: +1:42
+                                           // mir::Constant
+                                           // + span: $DIR/structs.rs:78:5: 78:6
+                                           // + literal: Const { ty: fn(*const u32) {f}, val: Value(<ZST>) }
+      }
+  
+      bb2: {
+          StorageDead(_2);                 // scope 0 at $DIR/structs.rs:+1:41: +1:42
+          StorageDead(_4);                 // scope 0 at $DIR/structs.rs:+1:42: +1:43
+          StorageDead(_3);                 // scope 0 at $DIR/structs.rs:+1:42: +1:43
+          StorageDead(_1);                 // scope 0 at $DIR/structs.rs:+1:42: +1:43
+          _0 = const ();                   // scope 0 at $DIR/structs.rs:+0:19: +2:2
+          return;                          // scope 0 at $DIR/structs.rs:+2:2: +2:2
+      }
+  }
+  
diff --git a/tests/mir-opt/sroa/structs.flat.ScalarReplacementOfAggregates.diff b/tests/mir-opt/sroa/structs.flat.ScalarReplacementOfAggregates.diff
new file mode 100644
index 00000000000..1aa11d17b67
--- /dev/null
+++ b/tests/mir-opt/sroa/structs.flat.ScalarReplacementOfAggregates.diff
@@ -0,0 +1,80 @@
+- // MIR for `flat` before ScalarReplacementOfAggregates
++ // MIR for `flat` after ScalarReplacementOfAggregates
+  
+  fn flat() -> () {
+      let mut _0: ();                      // return place in scope 0 at $DIR/structs.rs:+0:15: +0:15
+      let _1: u8;                          // in scope 0 at $DIR/structs.rs:+1:15: +1:16
+      let _2: ();                          // in scope 0 at $DIR/structs.rs:+1:18: +1:19
+      let _3: &str;                        // in scope 0 at $DIR/structs.rs:+1:21: +1:22
+      let _4: std::option::Option<isize>;  // in scope 0 at $DIR/structs.rs:+1:24: +1:25
+      let mut _5: Foo;                     // in scope 0 at $DIR/structs.rs:+1:30: +1:70
+      let mut _6: ();                      // in scope 0 at $DIR/structs.rs:+1:45: +1:47
+      let mut _7: std::option::Option<isize>; // in scope 0 at $DIR/structs.rs:+1:60: +1:68
++     let mut _8: u8;                      // in scope 0 at $DIR/structs.rs:+1:30: +1:70
++     let mut _9: ();                      // in scope 0 at $DIR/structs.rs:+1:30: +1:70
++     let mut _10: &str;                   // in scope 0 at $DIR/structs.rs:+1:30: +1:70
++     let mut _11: std::option::Option<isize>; // in scope 0 at $DIR/structs.rs:+1:30: +1:70
+      scope 1 {
+          debug a => _1;                   // in scope 1 at $DIR/structs.rs:+1:15: +1:16
+          debug b => _2;                   // in scope 1 at $DIR/structs.rs:+1:18: +1:19
+          debug c => _3;                   // in scope 1 at $DIR/structs.rs:+1:21: +1:22
+          debug d => _4;                   // in scope 1 at $DIR/structs.rs:+1:24: +1:25
+          scope 2 {
+              scope 3 {
+                  scope 4 {
+                      scope 5 {
+                      }
+                  }
+              }
+          }
+      }
+  
+      bb0: {
+-         StorageLive(_5);                 // scope 0 at $DIR/structs.rs:+1:30: +1:70
++         StorageLive(_8);                 // scope 0 at $DIR/structs.rs:+1:30: +1:70
++         StorageLive(_9);                 // scope 0 at $DIR/structs.rs:+1:30: +1:70
++         StorageLive(_10);                // scope 0 at $DIR/structs.rs:+1:30: +1:70
++         StorageLive(_11);                // scope 0 at $DIR/structs.rs:+1:30: +1:70
++         nop;                             // scope 0 at $DIR/structs.rs:+1:30: +1:70
+          StorageLive(_6);                 // scope 0 at $DIR/structs.rs:+1:45: +1:47
+          _6 = ();                         // scope 0 at $DIR/structs.rs:+1:45: +1:47
+          StorageLive(_7);                 // scope 0 at $DIR/structs.rs:+1:60: +1:68
+          _7 = Option::<isize>::Some(const -4_isize); // scope 0 at $DIR/structs.rs:+1:60: +1:68
+-         _5 = Foo { a: const 5_u8, b: move _6, c: const "a", d: move _7 }; // scope 0 at $DIR/structs.rs:+1:30: +1:70
++         _8 = const 5_u8;                 // scope 0 at $DIR/structs.rs:+1:30: +1:70
++         _9 = move _6;                    // scope 0 at $DIR/structs.rs:+1:30: +1:70
++         _10 = const "a";                 // scope 0 at $DIR/structs.rs:+1:30: +1:70
+                                           // mir::Constant
+                                           // + span: $DIR/structs.rs:53:52: 53:55
+                                           // + literal: Const { ty: &str, val: Value(Slice(..)) }
++         _11 = move _7;                   // scope 0 at $DIR/structs.rs:+1:30: +1:70
++         nop;                             // scope 0 at $DIR/structs.rs:+1:30: +1:70
+          StorageDead(_7);                 // scope 0 at $DIR/structs.rs:+1:69: +1:70
+          StorageDead(_6);                 // scope 0 at $DIR/structs.rs:+1:69: +1:70
+          StorageLive(_1);                 // scope 0 at $DIR/structs.rs:+1:15: +1:16
+-         _1 = (_5.0: u8);                 // scope 0 at $DIR/structs.rs:+1:15: +1:16
++         _1 = _8;                         // scope 0 at $DIR/structs.rs:+1:15: +1:16
+          StorageLive(_2);                 // scope 0 at $DIR/structs.rs:+1:18: +1:19
+-         _2 = (_5.1: ());                 // scope 0 at $DIR/structs.rs:+1:18: +1:19
++         _2 = _9;                         // scope 0 at $DIR/structs.rs:+1:18: +1:19
+          StorageLive(_3);                 // scope 0 at $DIR/structs.rs:+1:21: +1:22
+-         _3 = (_5.2: &str);               // scope 0 at $DIR/structs.rs:+1:21: +1:22
++         _3 = _10;                        // scope 0 at $DIR/structs.rs:+1:21: +1:22
+          StorageLive(_4);                 // scope 0 at $DIR/structs.rs:+1:24: +1:25
+-         _4 = (_5.3: std::option::Option<isize>); // scope 0 at $DIR/structs.rs:+1:24: +1:25
+-         StorageDead(_5);                 // scope 0 at $DIR/structs.rs:+1:70: +1:71
++         _4 = _11;                        // scope 0 at $DIR/structs.rs:+1:24: +1:25
++         StorageDead(_8);                 // scope 0 at $DIR/structs.rs:+1:70: +1:71
++         StorageDead(_9);                 // scope 0 at $DIR/structs.rs:+1:70: +1:71
++         StorageDead(_10);                // scope 0 at $DIR/structs.rs:+1:70: +1:71
++         StorageDead(_11);                // scope 0 at $DIR/structs.rs:+1:70: +1:71
++         nop;                             // scope 0 at $DIR/structs.rs:+1:70: +1:71
+          _0 = const ();                   // scope 0 at $DIR/structs.rs:+0:15: +6:2
+          StorageDead(_4);                 // scope 0 at $DIR/structs.rs:+6:1: +6:2
+          StorageDead(_3);                 // scope 0 at $DIR/structs.rs:+6:1: +6:2
+          StorageDead(_2);                 // scope 0 at $DIR/structs.rs:+6:1: +6:2
+          StorageDead(_1);                 // scope 0 at $DIR/structs.rs:+6:1: +6:2
+          return;                          // scope 0 at $DIR/structs.rs:+6:2: +6:2
+      }
+  }
+  
diff --git a/tests/mir-opt/sroa/structs.ref_copies.ScalarReplacementOfAggregates.diff b/tests/mir-opt/sroa/structs.ref_copies.ScalarReplacementOfAggregates.diff
new file mode 100644
index 00000000000..7b09ac18263
--- /dev/null
+++ b/tests/mir-opt/sroa/structs.ref_copies.ScalarReplacementOfAggregates.diff
@@ -0,0 +1,56 @@
+- // MIR for `ref_copies` before ScalarReplacementOfAggregates
++ // MIR for `ref_copies` after ScalarReplacementOfAggregates
+  
+  fn ref_copies(_1: &Foo) -> () {
+      debug x => _1;                       // in scope 0 at $DIR/structs.rs:+0:15: +0:16
+      let mut _0: ();                      // return place in scope 0 at $DIR/structs.rs:+0:24: +0:24
+      let _2: Foo;                         // in scope 0 at $DIR/structs.rs:+1:9: +1:10
++     let _5: u8;                          // in scope 0 at $DIR/structs.rs:+1:9: +1:10
++     let _6: ();                          // in scope 0 at $DIR/structs.rs:+1:9: +1:10
++     let _7: &str;                        // in scope 0 at $DIR/structs.rs:+1:9: +1:10
++     let _8: std::option::Option<isize>;  // in scope 0 at $DIR/structs.rs:+1:9: +1:10
+      scope 1 {
+-         debug y => _2;                   // in scope 1 at $DIR/structs.rs:+1:9: +1:10
++         debug y => Foo{ .0 => _5, .1 => _6, .2 => _7, .3 => _8, }; // in scope 1 at $DIR/structs.rs:+1:9: +1:10
+          let _3: u8;                      // in scope 1 at $DIR/structs.rs:+2:9: +2:10
+          scope 2 {
+              debug t => _3;               // in scope 2 at $DIR/structs.rs:+2:9: +2:10
+              let _4: &str;                // in scope 2 at $DIR/structs.rs:+3:9: +3:10
+              scope 3 {
+                  debug u => _4;           // in scope 3 at $DIR/structs.rs:+3:9: +3:10
+              }
+          }
+      }
+  
+      bb0: {
+-         StorageLive(_2);                 // scope 0 at $DIR/structs.rs:+1:9: +1:10
+-         _2 = (*_1);                      // scope 0 at $DIR/structs.rs:+1:13: +1:15
++         StorageLive(_5);                 // scope 0 at $DIR/structs.rs:+1:9: +1:10
++         StorageLive(_6);                 // scope 0 at $DIR/structs.rs:+1:9: +1:10
++         StorageLive(_7);                 // scope 0 at $DIR/structs.rs:+1:9: +1:10
++         StorageLive(_8);                 // scope 0 at $DIR/structs.rs:+1:9: +1:10
++         nop;                             // scope 0 at $DIR/structs.rs:+1:9: +1:10
++         _5 = ((*_1).0: u8);              // scope 0 at $DIR/structs.rs:+1:13: +1:15
++         _6 = ((*_1).1: ());              // scope 0 at $DIR/structs.rs:+1:13: +1:15
++         _7 = ((*_1).2: &str);            // scope 0 at $DIR/structs.rs:+1:13: +1:15
++         _8 = ((*_1).3: std::option::Option<isize>); // scope 0 at $DIR/structs.rs:+1:13: +1:15
++         nop;                             // scope 0 at $DIR/structs.rs:+1:13: +1:15
+          StorageLive(_3);                 // scope 1 at $DIR/structs.rs:+2:9: +2:10
+-         _3 = (_2.0: u8);                 // scope 1 at $DIR/structs.rs:+2:13: +2:16
++         _3 = _5;                         // scope 1 at $DIR/structs.rs:+2:13: +2:16
+          StorageLive(_4);                 // scope 2 at $DIR/structs.rs:+3:9: +3:10
+-         _4 = (_2.2: &str);               // scope 2 at $DIR/structs.rs:+3:13: +3:16
++         _4 = _7;                         // scope 2 at $DIR/structs.rs:+3:13: +3:16
+          _0 = const ();                   // scope 0 at $DIR/structs.rs:+0:24: +4:2
+          StorageDead(_4);                 // scope 2 at $DIR/structs.rs:+4:1: +4:2
+          StorageDead(_3);                 // scope 1 at $DIR/structs.rs:+4:1: +4:2
+-         StorageDead(_2);                 // scope 0 at $DIR/structs.rs:+4:1: +4:2
++         StorageDead(_5);                 // scope 0 at $DIR/structs.rs:+4:1: +4:2
++         StorageDead(_6);                 // scope 0 at $DIR/structs.rs:+4:1: +4:2
++         StorageDead(_7);                 // scope 0 at $DIR/structs.rs:+4:1: +4:2
++         StorageDead(_8);                 // scope 0 at $DIR/structs.rs:+4:1: +4:2
++         nop;                             // scope 0 at $DIR/structs.rs:+4:1: +4:2
+          return;                          // scope 0 at $DIR/structs.rs:+4:2: +4:2
+      }
+  }
+  
diff --git a/tests/mir-opt/sroa.rs b/tests/mir-opt/sroa/structs.rs
index fff92cf8d9f..7946eeaeae4 100644
--- a/tests/mir-opt/sroa.rs
+++ b/tests/mir-opt/sroa/structs.rs
@@ -111,12 +111,12 @@ fn main() {
     constant();
 }
 
-// EMIT_MIR sroa.dropping.ScalarReplacementOfAggregates.diff
-// EMIT_MIR sroa.enums.ScalarReplacementOfAggregates.diff
-// EMIT_MIR sroa.structs.ScalarReplacementOfAggregates.diff
-// EMIT_MIR sroa.unions.ScalarReplacementOfAggregates.diff
-// EMIT_MIR sroa.flat.ScalarReplacementOfAggregates.diff
-// EMIT_MIR sroa.escaping.ScalarReplacementOfAggregates.diff
-// EMIT_MIR sroa.copies.ScalarReplacementOfAggregates.diff
-// EMIT_MIR sroa.ref_copies.ScalarReplacementOfAggregates.diff
-// EMIT_MIR sroa.constant.ScalarReplacementOfAggregates.diff
+// EMIT_MIR structs.dropping.ScalarReplacementOfAggregates.diff
+// EMIT_MIR structs.enums.ScalarReplacementOfAggregates.diff
+// EMIT_MIR structs.structs.ScalarReplacementOfAggregates.diff
+// EMIT_MIR structs.unions.ScalarReplacementOfAggregates.diff
+// EMIT_MIR structs.flat.ScalarReplacementOfAggregates.diff
+// EMIT_MIR structs.escaping.ScalarReplacementOfAggregates.diff
+// EMIT_MIR structs.copies.ScalarReplacementOfAggregates.diff
+// EMIT_MIR structs.ref_copies.ScalarReplacementOfAggregates.diff
+// EMIT_MIR structs.constant.ScalarReplacementOfAggregates.diff
diff --git a/tests/mir-opt/sroa/structs.structs.ScalarReplacementOfAggregates.diff b/tests/mir-opt/sroa/structs.structs.ScalarReplacementOfAggregates.diff
new file mode 100644
index 00000000000..c94e4b137bc
--- /dev/null
+++ b/tests/mir-opt/sroa/structs.structs.ScalarReplacementOfAggregates.diff
@@ -0,0 +1,33 @@
+- // MIR for `structs` before ScalarReplacementOfAggregates
++ // MIR for `structs` after ScalarReplacementOfAggregates
+  
+  fn structs(_1: f32) -> f32 {
+      debug a => _1;                       // in scope 0 at $DIR/structs.rs:+0:16: +0:17
+      let mut _0: f32;                     // return place in scope 0 at $DIR/structs.rs:+0:27: +0:30
+      let mut _2: structs::U;              // in scope 0 at $DIR/structs.rs:+6:5: +6:21
+      let mut _3: f32;                     // in scope 0 at $DIR/structs.rs:+6:18: +6:19
++     let mut _4: usize;                   // in scope 0 at $DIR/structs.rs:+6:5: +6:21
++     let mut _5: f32;                     // in scope 0 at $DIR/structs.rs:+6:5: +6:21
+  
+      bb0: {
+-         StorageLive(_2);                 // scope 0 at $DIR/structs.rs:+6:5: +6:21
++         StorageLive(_4);                 // scope 0 at $DIR/structs.rs:+6:5: +6:21
++         StorageLive(_5);                 // scope 0 at $DIR/structs.rs:+6:5: +6:21
++         nop;                             // scope 0 at $DIR/structs.rs:+6:5: +6:21
+          StorageLive(_3);                 // scope 0 at $DIR/structs.rs:+6:18: +6:19
+          _3 = _1;                         // scope 0 at $DIR/structs.rs:+6:18: +6:19
+-         _2 = U { _foo: const 0_usize, a: move _3 }; // scope 0 at $DIR/structs.rs:+6:5: +6:21
++         _4 = const 0_usize;              // scope 0 at $DIR/structs.rs:+6:5: +6:21
++         _5 = move _3;                    // scope 0 at $DIR/structs.rs:+6:5: +6:21
++         nop;                             // scope 0 at $DIR/structs.rs:+6:5: +6:21
+          StorageDead(_3);                 // scope 0 at $DIR/structs.rs:+6:20: +6:21
+-         _0 = (_2.1: f32);                // scope 0 at $DIR/structs.rs:+6:5: +6:23
+-         StorageDead(_2);                 // scope 0 at $DIR/structs.rs:+7:1: +7:2
++         _0 = _5;                         // scope 0 at $DIR/structs.rs:+6:5: +6:23
++         StorageDead(_4);                 // scope 0 at $DIR/structs.rs:+7:1: +7:2
++         StorageDead(_5);                 // scope 0 at $DIR/structs.rs:+7:1: +7:2
++         nop;                             // scope 0 at $DIR/structs.rs:+7:1: +7:2
+          return;                          // scope 0 at $DIR/structs.rs:+7:2: +7:2
+      }
+  }
+  
diff --git a/tests/mir-opt/sroa/structs.unions.ScalarReplacementOfAggregates.diff b/tests/mir-opt/sroa/structs.unions.ScalarReplacementOfAggregates.diff
new file mode 100644
index 00000000000..5aa054589e4
--- /dev/null
+++ b/tests/mir-opt/sroa/structs.unions.ScalarReplacementOfAggregates.diff
@@ -0,0 +1,23 @@
+- // MIR for `unions` before ScalarReplacementOfAggregates
++ // MIR for `unions` after ScalarReplacementOfAggregates
+  
+  fn unions(_1: f32) -> u32 {
+      debug a => _1;                       // in scope 0 at $DIR/structs.rs:+0:15: +0:16
+      let mut _0: u32;                     // return place in scope 0 at $DIR/structs.rs:+0:26: +0:29
+      let mut _2: unions::Repr;            // in scope 0 at $DIR/structs.rs:+5:14: +5:27
+      let mut _3: f32;                     // in scope 0 at $DIR/structs.rs:+5:24: +5:25
+      scope 1 {
+      }
+  
+      bb0: {
+          StorageLive(_2);                 // scope 1 at $DIR/structs.rs:+5:14: +5:27
+          StorageLive(_3);                 // scope 1 at $DIR/structs.rs:+5:24: +5:25
+          _3 = _1;                         // scope 1 at $DIR/structs.rs:+5:24: +5:25
+          _2 = Repr { f: move _3 };        // scope 1 at $DIR/structs.rs:+5:14: +5:27
+          StorageDead(_3);                 // scope 1 at $DIR/structs.rs:+5:26: +5:27
+          _0 = (_2.1: u32);                // scope 1 at $DIR/structs.rs:+5:14: +5:29
+          StorageDead(_2);                 // scope 0 at $DIR/structs.rs:+6:1: +6:2
+          return;                          // scope 0 at $DIR/structs.rs:+6:2: +6:2
+      }
+  }
+