about summary refs log tree commit diff
path: root/compiler/rustc_mir_transform/src
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/rustc_mir_transform/src')
-rw-r--r--compiler/rustc_mir_transform/src/coroutine.rs4
-rw-r--r--compiler/rustc_mir_transform/src/coroutine/drop.rs21
-rw-r--r--compiler/rustc_mir_transform/src/cross_crate_inline.rs7
-rw-r--r--compiler/rustc_mir_transform/src/elaborate_drop.rs14
-rw-r--r--compiler/rustc_mir_transform/src/gvn.rs11
-rw-r--r--compiler/rustc_mir_transform/src/lower_intrinsics.rs4
-rw-r--r--compiler/rustc_mir_transform/src/simplify.rs19
7 files changed, 58 insertions, 22 deletions
diff --git a/compiler/rustc_mir_transform/src/coroutine.rs b/compiler/rustc_mir_transform/src/coroutine.rs
index d5d0d56f528..06c6b46a9c2 100644
--- a/compiler/rustc_mir_transform/src/coroutine.rs
+++ b/compiler/rustc_mir_transform/src/coroutine.rs
@@ -1417,9 +1417,9 @@ fn check_field_tys_sized<'tcx>(
     coroutine_layout: &CoroutineLayout<'tcx>,
     def_id: LocalDefId,
 ) {
-    // No need to check if unsized_locals/unsized_fn_params is disabled,
+    // No need to check if unsized_fn_params is disabled,
     // since we will error during typeck.
-    if !tcx.features().unsized_locals() && !tcx.features().unsized_fn_params() {
+    if !tcx.features().unsized_fn_params() {
         return;
     }
 
diff --git a/compiler/rustc_mir_transform/src/coroutine/drop.rs b/compiler/rustc_mir_transform/src/coroutine/drop.rs
index 6021e795d21..dc68629ec0d 100644
--- a/compiler/rustc_mir_transform/src/coroutine/drop.rs
+++ b/compiler/rustc_mir_transform/src/coroutine/drop.rs
@@ -132,6 +132,7 @@ fn build_poll_switch<'tcx>(
     body: &mut Body<'tcx>,
     poll_enum: Ty<'tcx>,
     poll_unit_place: &Place<'tcx>,
+    fut_pin_place: &Place<'tcx>,
     ready_block: BasicBlock,
     yield_block: BasicBlock,
 ) -> BasicBlock {
@@ -162,9 +163,11 @@ fn build_poll_switch<'tcx>(
             Rvalue::Discriminant(*poll_unit_place),
         ))),
     };
+    let storage_dead =
+        Statement { source_info, kind: StatementKind::StorageDead(fut_pin_place.local) };
     let unreachable_block = insert_term_block(body, TerminatorKind::Unreachable);
     body.basic_blocks_mut().push(BasicBlockData {
-        statements: [discr_assign].to_vec(),
+        statements: [storage_dead, discr_assign].to_vec(),
         terminator: Some(Terminator {
             source_info,
             kind: TerminatorKind::SwitchInt {
@@ -332,10 +335,17 @@ pub(super) fn expand_async_drops<'tcx>(
             kind: StatementKind::Assign(Box::new((context_ref_place, arg))),
         });
         let yield_block = insert_term_block(body, TerminatorKind::Unreachable); // `kind` replaced later to yield
-        let switch_block =
-            build_poll_switch(tcx, body, poll_enum, &poll_unit_place, target, yield_block);
         let (pin_bb, fut_pin_place) =
             build_pin_fut(tcx, body, fut_place.clone(), UnwindAction::Continue);
+        let switch_block = build_poll_switch(
+            tcx,
+            body,
+            poll_enum,
+            &poll_unit_place,
+            &fut_pin_place,
+            target,
+            yield_block,
+        );
         let call_bb = build_poll_call(
             tcx,
             body,
@@ -357,16 +367,17 @@ pub(super) fn expand_async_drops<'tcx>(
                 body.local_decls.push(LocalDecl::new(context_mut_ref, source_info.span)),
             );
             let drop_yield_block = insert_term_block(body, TerminatorKind::Unreachable); // `kind` replaced later to yield
+            let (pin_bb2, fut_pin_place2) =
+                build_pin_fut(tcx, body, fut_place, UnwindAction::Continue);
             let drop_switch_block = build_poll_switch(
                 tcx,
                 body,
                 poll_enum,
                 &poll_unit_place,
+                &fut_pin_place2,
                 drop.unwrap(),
                 drop_yield_block,
             );
-            let (pin_bb2, fut_pin_place2) =
-                build_pin_fut(tcx, body, fut_place, UnwindAction::Continue);
             let drop_call_bb = build_poll_call(
                 tcx,
                 body,
diff --git a/compiler/rustc_mir_transform/src/cross_crate_inline.rs b/compiler/rustc_mir_transform/src/cross_crate_inline.rs
index 727d4a126d2..6d7b7e10ef6 100644
--- a/compiler/rustc_mir_transform/src/cross_crate_inline.rs
+++ b/compiler/rustc_mir_transform/src/cross_crate_inline.rs
@@ -50,6 +50,13 @@ fn cross_crate_inlinable(tcx: TyCtxt<'_>, def_id: LocalDefId) -> bool {
         _ => {}
     }
 
+    // If the crate is likely to be mostly unused, use cross-crate inlining to defer codegen until
+    // the function is referenced, in order to skip codegen for unused functions. This is
+    // intentionally after the check for `inline(never)`, so that `inline(never)` wins.
+    if tcx.sess.opts.unstable_opts.hint_mostly_unused {
+        return true;
+    }
+
     let sig = tcx.fn_sig(def_id).instantiate_identity();
     for ty in sig.inputs().skip_binder().iter().chain(std::iter::once(&sig.output().skip_binder()))
     {
diff --git a/compiler/rustc_mir_transform/src/elaborate_drop.rs b/compiler/rustc_mir_transform/src/elaborate_drop.rs
index 3a5e2620b14..c9bc52c6c7e 100644
--- a/compiler/rustc_mir_transform/src/elaborate_drop.rs
+++ b/compiler/rustc_mir_transform/src/elaborate_drop.rs
@@ -390,6 +390,20 @@ where
             Location { block: self.succ, statement_index: 0 },
             StatementKind::StorageDead(fut.local),
         );
+        // StorageDead(fut) in unwind block (at the begin)
+        if let Unwind::To(block) = unwind {
+            self.elaborator.patch().add_statement(
+                Location { block, statement_index: 0 },
+                StatementKind::StorageDead(fut.local),
+            );
+        }
+        // StorageDead(fut) in dropline block (at the begin)
+        if let Some(block) = dropline {
+            self.elaborator.patch().add_statement(
+                Location { block, statement_index: 0 },
+                StatementKind::StorageDead(fut.local),
+            );
+        }
 
         // #1:pin_obj_bb >>> call Pin<ObjTy>::new_unchecked(&mut obj)
         self.elaborator.patch().patch_terminator(
diff --git a/compiler/rustc_mir_transform/src/gvn.rs b/compiler/rustc_mir_transform/src/gvn.rs
index 92c30d239b5..bda71ceaa55 100644
--- a/compiler/rustc_mir_transform/src/gvn.rs
+++ b/compiler/rustc_mir_transform/src/gvn.rs
@@ -240,8 +240,6 @@ struct VnState<'body, 'tcx> {
     next_opaque: usize,
     /// Cache the deref values.
     derefs: Vec<VnIndex>,
-    /// Cache the value of the `unsized_locals` features, to avoid fetching it repeatedly in a loop.
-    feature_unsized_locals: bool,
     ssa: &'body SsaLocals,
     dominators: Dominators<BasicBlock>,
     reused_locals: DenseBitSet<Local>,
@@ -273,7 +271,6 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
             evaluated: IndexVec::with_capacity(num_values),
             next_opaque: 1,
             derefs: Vec::new(),
-            feature_unsized_locals: tcx.features().unsized_locals(),
             ssa,
             dominators,
             reused_locals: DenseBitSet::new_empty(local_decls.len()),
@@ -329,13 +326,7 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
     fn assign(&mut self, local: Local, value: VnIndex) {
         debug_assert!(self.ssa.is_ssa(local));
         self.locals[local] = Some(value);
-
-        // Only register the value if its type is `Sized`, as we will emit copies of it.
-        let is_sized = !self.feature_unsized_locals
-            || self.local_decls[local].ty.is_sized(self.tcx, self.typing_env());
-        if is_sized {
-            self.rev_locals[value].push(local);
-        }
+        self.rev_locals[value].push(local);
     }
 
     fn insert_constant(&mut self, value: Const<'tcx>) -> VnIndex {
diff --git a/compiler/rustc_mir_transform/src/lower_intrinsics.rs b/compiler/rustc_mir_transform/src/lower_intrinsics.rs
index 52f4c39c09b..fa29ab985b7 100644
--- a/compiler/rustc_mir_transform/src/lower_intrinsics.rs
+++ b/compiler/rustc_mir_transform/src/lower_intrinsics.rs
@@ -150,12 +150,12 @@ impl<'tcx> crate::MirPass<'tcx> for LowerIntrinsics {
                         });
                         terminator.kind = TerminatorKind::Goto { target };
                     }
-                    sym::size_of | sym::min_align_of => {
+                    sym::size_of | sym::align_of => {
                         let target = target.unwrap();
                         let tp_ty = generic_args.type_at(0);
                         let null_op = match intrinsic.name {
                             sym::size_of => NullOp::SizeOf,
-                            sym::min_align_of => NullOp::AlignOf,
+                            sym::align_of => NullOp::AlignOf,
                             _ => bug!("unexpected intrinsic"),
                         };
                         block.statements.push(Statement {
diff --git a/compiler/rustc_mir_transform/src/simplify.rs b/compiler/rustc_mir_transform/src/simplify.rs
index 8f88228d9bb..a54e548ad70 100644
--- a/compiler/rustc_mir_transform/src/simplify.rs
+++ b/compiler/rustc_mir_transform/src/simplify.rs
@@ -74,7 +74,11 @@ impl SimplifyCfg {
 }
 
 pub(super) fn simplify_cfg<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
-    CfgSimplifier::new(tcx, body).simplify();
+    if CfgSimplifier::new(tcx, body).simplify() {
+        // `simplify` returns that it changed something. We must invalidate the CFG caches as they
+        // are not consistent with the modified CFG any more.
+        body.basic_blocks.invalidate_cfg_cache();
+    }
     remove_dead_blocks(body);
 
     // FIXME: Should probably be moved into some kind of pass manager
@@ -121,12 +125,16 @@ impl<'a, 'tcx> CfgSimplifier<'a, 'tcx> {
         // Preserve `SwitchInt` reads on built and analysis MIR, or if `-Zmir-preserve-ub`.
         let preserve_switch_reads = matches!(body.phase, MirPhase::Built | MirPhase::Analysis(_))
             || tcx.sess.opts.unstable_opts.mir_preserve_ub;
-        let basic_blocks = body.basic_blocks_mut();
+        // Do not clear caches yet. The caller to `simplify` will do it if anything changed.
+        let basic_blocks = body.basic_blocks.as_mut_preserves_cfg();
 
         CfgSimplifier { preserve_switch_reads, basic_blocks, pred_count }
     }
 
-    fn simplify(mut self) {
+    /// Returns whether we actually simplified anything. In that case, the caller *must* invalidate
+    /// the CFG caches of the MIR body.
+    #[must_use]
+    fn simplify(mut self) -> bool {
         self.strip_nops();
 
         // Vec of the blocks that should be merged. We store the indices here, instead of the
@@ -134,6 +142,7 @@ impl<'a, 'tcx> CfgSimplifier<'a, 'tcx> {
         // We do not push the statements directly into the target block (`bb`) as that is slower
         // due to additional reallocations
         let mut merged_blocks = Vec::new();
+        let mut outer_changed = false;
         loop {
             let mut changed = false;
 
@@ -177,7 +186,11 @@ impl<'a, 'tcx> CfgSimplifier<'a, 'tcx> {
             if !changed {
                 break;
             }
+
+            outer_changed = true;
         }
+
+        outer_changed
     }
 
     /// This function will return `None` if