]> git.lizzy.rs Git - rust.git/blob - compiler/rustc_mir_transform/src/dead_store_elimination.rs
Auto merge of #105919 - uweigand:s390x-stack-overflow, r=Nilstrieb
[rust.git] / compiler / rustc_mir_transform / src / dead_store_elimination.rs
1 //! This module implements a dead store elimination (DSE) routine.
2 //!
3 //! This transformation was written specifically for the needs of dest prop. Although it is
4 //! perfectly sound to use it in any context that might need it, its behavior should not be changed
5 //! without analyzing the interaction this will have with dest prop. Specifically, in addition to
6 //! the soundness of this pass in general, dest prop needs it to satisfy two additional conditions:
7 //!
8 //!  1. It's idempotent, meaning that running this pass a second time immediately after running it a
9 //!     first time will not cause any further changes.
10 //!  2. This idempotence persists across dest prop's main transform, in other words inserting any
11 //!     number of iterations of dest prop between the first and second application of this transform
12 //!     will still not cause any further changes.
13 //!
14
15 use rustc_index::bit_set::BitSet;
16 use rustc_middle::mir::*;
17 use rustc_middle::ty::TyCtxt;
18 use rustc_mir_dataflow::impls::{borrowed_locals, MaybeTransitiveLiveLocals};
19 use rustc_mir_dataflow::Analysis;
20
21 /// Performs the optimization on the body
22 ///
23 /// The `borrowed` set must be a `BitSet` of all the locals that are ever borrowed in this body. It
24 /// can be generated via the [`borrowed_locals`] function.
25 pub fn eliminate<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>, borrowed: &BitSet<Local>) {
26     let mut live = MaybeTransitiveLiveLocals::new(borrowed)
27         .into_engine(tcx, body)
28         .iterate_to_fixpoint()
29         .into_results_cursor(body);
30
31     let mut patch = Vec::new();
32     for (bb, bb_data) in traversal::preorder(body) {
33         for (statement_index, statement) in bb_data.statements.iter().enumerate().rev() {
34             let loc = Location { block: bb, statement_index };
35             if let StatementKind::Assign(assign) = &statement.kind {
36                 if !assign.1.is_safe_to_remove() {
37                     continue;
38                 }
39             }
40             match &statement.kind {
41                 StatementKind::Assign(box (place, _))
42                 | StatementKind::SetDiscriminant { place: box place, .. }
43                 | StatementKind::Deinit(box place) => {
44                     if !place.is_indirect() && !borrowed.contains(place.local) {
45                         live.seek_before_primary_effect(loc);
46                         if !live.get().contains(place.local) {
47                             patch.push(loc);
48                         }
49                     }
50                 }
51                 StatementKind::Retag(_, _)
52                 | StatementKind::StorageLive(_)
53                 | StatementKind::StorageDead(_)
54                 | StatementKind::Coverage(_)
55                 | StatementKind::Intrinsic(_)
56                 | StatementKind::Nop => (),
57
58                 StatementKind::FakeRead(_) | StatementKind::AscribeUserType(_, _) => {
59                     bug!("{:?} not found in this MIR phase!", &statement.kind)
60                 }
61             }
62         }
63     }
64
65     if patch.is_empty() {
66         return;
67     }
68
69     let bbs = body.basic_blocks.as_mut_preserves_cfg();
70     for Location { block, statement_index } in patch {
71         bbs[block].statements[statement_index].make_nop();
72     }
73
74     crate::simplify::simplify_locals(body, tcx)
75 }
76
77 pub struct DeadStoreElimination;
78
79 impl<'tcx> MirPass<'tcx> for DeadStoreElimination {
80     fn is_enabled(&self, sess: &rustc_session::Session) -> bool {
81         sess.mir_opt_level() >= 2
82     }
83
84     fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
85         let borrowed = borrowed_locals(body);
86         eliminate(tcx, body, &borrowed);
87     }
88 }