//! A number of passes which remove various redundancies in the CFG.
//!
//! The `SimplifyCfg` pass gets rid of unnecessary blocks in the CFG, whereas the `SimplifyLocals`
//! gets rid of all the unnecessary local variable declarations.
//!
//! The `SimplifyLocals` pass is kinda expensive and therefore not very suitable to be run often.
//! Most of the passes should not care or be impacted in meaningful ways due to extra locals
//! either, so running the pass once, right before codegen, should suffice.
//!
//! On the other side of the spectrum, the `SimplifyCfg` pass is considerably cheap to run, thus
//! one should run it after every pass which may modify CFG in significant ways. This pass must
//! also be run before any analysis passes because it removes dead blocks, and some of these can be
//! ill-typed.
//!
//! The cause of this typing issue is typeck allowing most blocks whose end is not reachable have
//! an arbitrary return type, rather than having the usual () return type (as a note, typeck's
//! notion of reachability is in fact slightly weaker than MIR CFG reachability - see #31617). A
//! standard example of the situation is:
//!
//! ```rust
//!   fn example() {
//!       let _a: char = { return; };
//!   }
//! ```
//!
//! Here the block (`{ return; }`) has the return type `char`, rather than `()`, but the MIR we
//! naively generate still contains the `_a = ()` write in the unreachable block "after" the
//! return.
//!
//! **WARNING**: This is one of the few optimizations that runs on built and analysis MIR, and
//! so its effects may affect the type-checking, borrow-checking, and other analysis of MIR.
//! We must be extremely careful to only apply optimizations that preserve UB and all
//! non-determinism, since changes here can affect which programs compile in an insta-stable way.
//! The normal logic that a program with UB can be changed to do anything does not apply to
//! pre-"runtime" MIR!

use itertools::Itertools as _;
use rustc_index::bit_set::DenseBitSet;
use rustc_index::{Idx, IndexSlice, IndexVec};
use rustc_middle::mir::visit::{MutVisitor, MutatingUseContext, PlaceContext, Visitor};
use rustc_middle::mir::*;
use rustc_middle::ty::TyCtxt;
use rustc_mir_dataflow::debuginfo::debuginfo_locals;
use rustc_span::DUMMY_SP;
use smallvec::SmallVec;
use tracing::{debug, trace};

pub(super) enum SimplifyCfg {
    Initial,
    PromoteConsts,
    RemoveFalseEdges,
    /// Runs at the beginning of "analysis to runtime" lowering, *before* drop elaboration.
    PostAnalysis,
    /// Runs at the end of "analysis to runtime" lowering, *after* drop elaboration.
    /// This is before the main optimization passes on runtime MIR kick in.
    PreOptimizations,
    Final,
    MakeShim,
    AfterUnreachableEnumBranching,
}

impl SimplifyCfg {
    fn name(&self) -> &'static str {
        match self {
            SimplifyCfg::Initial => "SimplifyCfg-initial",
            SimplifyCfg::PromoteConsts => "SimplifyCfg-promote-consts",
            SimplifyCfg::RemoveFalseEdges => "SimplifyCfg-remove-false-edges",
            SimplifyCfg::PostAnalysis => "SimplifyCfg-post-analysis",
            SimplifyCfg::PreOptimizations => "SimplifyCfg-pre-optimizations",
            SimplifyCfg::Final => "SimplifyCfg-final",
            SimplifyCfg::MakeShim => "SimplifyCfg-make_shim",
            SimplifyCfg::AfterUnreachableEnumBranching => {
                "SimplifyCfg-after-unreachable-enum-branching"
            }
        }
    }
}

pub(super) fn simplify_cfg<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
    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
    body.basic_blocks.as_mut_preserves_cfg().shrink_to_fit();
}

impl<'tcx> crate::MirPass<'tcx> for SimplifyCfg {
    fn name(&self) -> &'static str {
        self.name()
    }

    fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
        debug!("SimplifyCfg({:?}) - simplifying {:?}", self.name(), body.source);
        simplify_cfg(tcx, body);
    }

    fn is_required(&self) -> bool {
        false
    }
}

struct CfgSimplifier<'a, 'tcx> {
    preserve_switch_reads: bool,
    basic_blocks: &'a mut IndexSlice<BasicBlock, BasicBlockData<'tcx>>,
    pred_count: IndexVec<BasicBlock, u32>,
}

impl<'a, 'tcx> CfgSimplifier<'a, 'tcx> {
    fn new(tcx: TyCtxt<'tcx>, body: &'a mut Body<'tcx>) -> Self {
        let mut pred_count = IndexVec::from_elem(0u32, &body.basic_blocks);

        // we can't use mir.predecessors() here because that counts
        // dead blocks, which we don't want to.
        pred_count[START_BLOCK] = 1;

        for (_, data) in traversal::preorder(body) {
            if let Some(ref term) = data.terminator {
                for tgt in term.successors() {
                    pred_count[tgt] += 1;
                }
            }
        }

        // 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;
        // 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 }
    }

    /// 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
        // statements itself to avoid moving the (relatively) large statements twice.
        // 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<BasicBlock> = Vec::new();
        let mut outer_changed = false;
        loop {
            let mut changed = false;

            for bb in self.basic_blocks.indices() {
                if self.pred_count[bb] == 0 {
                    continue;
                }

                debug!("simplifying {:?}", bb);

                let mut terminator =
                    self.basic_blocks[bb].terminator.take().expect("invalid terminator state");

                terminator.successors_mut(|successor| {
                    self.collapse_goto_chain(successor, &mut changed);
                });

                let mut inner_changed = true;
                merged_blocks.clear();
                while inner_changed {
                    inner_changed = false;
                    inner_changed |= self.simplify_branch(&mut terminator);
                    inner_changed |= self.merge_successor(&mut merged_blocks, &mut terminator);
                    changed |= inner_changed;
                }

                let statements_to_merge =
                    merged_blocks.iter().map(|&i| self.basic_blocks[i].statements.len()).sum();

                if statements_to_merge > 0 {
                    let mut statements = std::mem::take(&mut self.basic_blocks[bb].statements);
                    statements.reserve(statements_to_merge);
                    let mut parent_bb_last_debuginfos =
                        std::mem::take(&mut self.basic_blocks[bb].after_last_stmt_debuginfos);
                    for &from in &merged_blocks {
                        if let Some(stmt) = self.basic_blocks[from].statements.first_mut() {
                            stmt.debuginfos.prepend(&mut parent_bb_last_debuginfos);
                        }
                        statements.append(&mut self.basic_blocks[from].statements);
                        parent_bb_last_debuginfos =
                            std::mem::take(&mut self.basic_blocks[from].after_last_stmt_debuginfos);
                    }
                    self.basic_blocks[bb].statements = statements;
                    self.basic_blocks[bb].after_last_stmt_debuginfos = parent_bb_last_debuginfos;
                }

                self.basic_blocks[bb].terminator = Some(terminator);
            }

            if !changed {
                break;
            }

            outer_changed = true;
        }

        outer_changed
    }

    /// This function will return `None` if
    /// * the block has statements
    /// * the block has a terminator other than `goto`
    /// * the block has no terminator (meaning some other part of the current optimization stole it)
    fn take_terminator_if_simple_goto(&mut self, bb: BasicBlock) -> Option<Terminator<'tcx>> {
        match self.basic_blocks[bb] {
            BasicBlockData {
                ref statements,
                terminator:
                    ref mut terminator @ Some(Terminator { kind: TerminatorKind::Goto { .. }, .. }),
                ..
            } if statements.is_empty() => terminator.take(),
            // if `terminator` is None, this means we are in a loop. In that
            // case, let all the loop collapse to its entry.
            _ => None,
        }
    }

    /// Collapse a goto chain starting from `start`
    fn collapse_goto_chain(&mut self, start: &mut BasicBlock, changed: &mut bool) {
        // Using `SmallVec` here, because in some logs on libcore oli-obk saw many single-element
        // goto chains. We should probably benchmark different sizes.
        let mut terminators: SmallVec<[_; 1]> = Default::default();
        let mut current = *start;
        // If each successor has only one predecessor, it's a trivial goto chain.
        // We can move all debuginfos to the last basic block.
        let mut trivial_goto_chain = true;
        while let Some(terminator) = self.take_terminator_if_simple_goto(current) {
            let Terminator { kind: TerminatorKind::Goto { target }, .. } = terminator else {
                unreachable!();
            };
            trivial_goto_chain &= self.pred_count[target] == 1;
            terminators.push((current, terminator));
            current = target;
        }
        let last = current;
        *changed |= *start != last;
        *start = last;
        while let Some((current, mut terminator)) = terminators.pop() {
            let Terminator { kind: TerminatorKind::Goto { ref mut target }, .. } = terminator
            else {
                unreachable!();
            };
            if trivial_goto_chain {
                let mut pred_debuginfos =
                    std::mem::take(&mut self.basic_blocks[current].after_last_stmt_debuginfos);
                let debuginfos = if let Some(stmt) = self.basic_blocks[last].statements.first_mut()
                {
                    &mut stmt.debuginfos
                } else {
                    &mut self.basic_blocks[last].after_last_stmt_debuginfos
                };
                debuginfos.prepend(&mut pred_debuginfos);
            }
            *changed |= *target != last;
            *target = last;
            debug!("collapsing goto chain from {:?} to {:?}", current, target);

            if self.pred_count[current] == 1 {
                // This is the last reference to current, so the pred-count to
                // to target is moved into the current block.
                self.pred_count[current] = 0;
            } else {
                self.pred_count[*target] += 1;
                self.pred_count[current] -= 1;
            }
            self.basic_blocks[current].terminator = Some(terminator);
        }
    }

    // merge a block with 1 `goto` predecessor to its parent
    fn merge_successor(
        &mut self,
        merged_blocks: &mut Vec<BasicBlock>,
        terminator: &mut Terminator<'tcx>,
    ) -> bool {
        let target = match terminator.kind {
            TerminatorKind::Goto { target } if self.pred_count[target] == 1 => target,
            _ => return false,
        };

        debug!("merging block {:?} into {:?}", target, terminator);
        *terminator = match self.basic_blocks[target].terminator.take() {
            Some(terminator) => terminator,
            None => {
                // unreachable loop - this should not be possible, as we
                // don't strand blocks, but handle it correctly.
                return false;
            }
        };

        merged_blocks.push(target);
        self.pred_count[target] = 0;

        true
    }

    // turn a branch with all successors identical to a goto
    fn simplify_branch(&mut self, terminator: &mut Terminator<'tcx>) -> bool {
        // Removing a `SwitchInt` terminator may remove reads that result in UB,
        // so we must not apply this optimization before borrowck or when
        // `-Zmir-preserve-ub` is set.
        if self.preserve_switch_reads {
            return false;
        }

        let TerminatorKind::SwitchInt { .. } = terminator.kind else {
            return false;
        };

        let Ok(first_succ) = terminator.successors().all_equal_value() else {
            return false;
        };

        let count = terminator.successors().count();
        self.pred_count[first_succ] -= (count - 1) as u32;

        debug!("simplifying branch {:?}", terminator);
        terminator.kind = TerminatorKind::Goto { target: first_succ };
        true
    }

    fn strip_nops(&mut self) {
        for blk in self.basic_blocks.iter_mut() {
            blk.strip_nops();
        }
    }
}

pub(super) fn simplify_duplicate_switch_targets(terminator: &mut Terminator<'_>) {
    if let TerminatorKind::SwitchInt { targets, .. } = &mut terminator.kind {
        let otherwise = targets.otherwise();
        if targets.iter().any(|t| t.1 == otherwise) {
            *targets = SwitchTargets::new(
                targets.iter().filter(|t| t.1 != otherwise),
                targets.otherwise(),
            );
        }
    }
}

pub(super) fn remove_dead_blocks(body: &mut Body<'_>) {
    let should_deduplicate_unreachable = |bbdata: &BasicBlockData<'_>| {
        // CfgSimplifier::simplify leaves behind some unreachable basic blocks without a
        // terminator. Those blocks will be deleted by remove_dead_blocks, but we run just
        // before then so we need to handle missing terminators.
        // We also need to prevent confusing cleanup and non-cleanup blocks. In practice we
        // don't emit empty unreachable cleanup blocks, so this simple check suffices.
        bbdata.terminator.is_some() && bbdata.is_empty_unreachable() && !bbdata.is_cleanup
    };

    let reachable = traversal::reachable_as_bitset(body);
    let empty_unreachable_blocks = body
        .basic_blocks
        .iter_enumerated()
        .filter(|(bb, bbdata)| should_deduplicate_unreachable(bbdata) && reachable.contains(*bb))
        .count();

    let num_blocks = body.basic_blocks.len();
    if num_blocks == reachable.count() && empty_unreachable_blocks <= 1 {
        return;
    }

    let basic_blocks = body.basic_blocks.as_mut();

    let mut replacements: Vec<_> = (0..num_blocks).map(BasicBlock::new).collect();
    let mut orig_index = 0;
    let mut used_index = 0;
    let mut kept_unreachable = None;
    let mut deduplicated_unreachable = false;
    basic_blocks.raw.retain(|bbdata| {
        let orig_bb = BasicBlock::new(orig_index);
        if !reachable.contains(orig_bb) {
            orig_index += 1;
            return false;
        }

        let used_bb = BasicBlock::new(used_index);
        if should_deduplicate_unreachable(bbdata) {
            let kept_unreachable = *kept_unreachable.get_or_insert(used_bb);
            if kept_unreachable != used_bb {
                replacements[orig_index] = kept_unreachable;
                deduplicated_unreachable = true;
                orig_index += 1;
                return false;
            }
        }

        replacements[orig_index] = used_bb;
        used_index += 1;
        orig_index += 1;
        true
    });

    // If we deduplicated unreachable blocks we erase their source_info as we
    // can no longer attribute their code to a particular location in the
    // source.
    if deduplicated_unreachable {
        basic_blocks[kept_unreachable.unwrap()].terminator_mut().source_info =
            SourceInfo { span: DUMMY_SP, scope: OUTERMOST_SOURCE_SCOPE };
    }

    for block in basic_blocks {
        block.terminator_mut().successors_mut(|target| *target = replacements[target.index()]);
    }
}

pub(super) enum SimplifyLocals {
    BeforeConstProp,
    AfterGVN,
    Final,
}

impl<'tcx> crate::MirPass<'tcx> for SimplifyLocals {
    fn name(&self) -> &'static str {
        match &self {
            SimplifyLocals::BeforeConstProp => "SimplifyLocals-before-const-prop",
            SimplifyLocals::AfterGVN => "SimplifyLocals-after-value-numbering",
            SimplifyLocals::Final => "SimplifyLocals-final",
        }
    }

    fn is_enabled(&self, sess: &rustc_session::Session) -> bool {
        sess.mir_opt_level() > 0
    }

    fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
        trace!("running SimplifyLocals on {:?}", body.source);

        // First, we're going to get a count of *actual* uses for every `Local`.
        let mut used_locals = UsedLocals::new(body);

        // Next, we're going to remove any `Local` with zero actual uses. When we remove those
        // `Locals`, we're also going to subtract any uses of other `Locals` from the `used_locals`
        // count. For example, if we removed `_2 = discriminant(_1)`, then we'll subtract one from
        // `use_counts[_1]`. That in turn might make `_1` unused, so we loop until we hit a
        // fixedpoint where there are no more unused locals.
        remove_unused_definitions_helper(&mut used_locals, body);

        // Finally, we'll actually do the work of shrinking `body.local_decls` and remapping the
        // `Local`s.
        let map = make_local_map(&mut body.local_decls, &used_locals);

        // Only bother running the `LocalUpdater` if we actually found locals to remove.
        if map.iter().any(Option::is_none) {
            // Update references to all vars and tmps now
            let mut updater = LocalUpdater { map, tcx };
            updater.visit_body_preserves_cfg(body);

            body.local_decls.shrink_to_fit();
        }
    }

    fn is_required(&self) -> bool {
        false
    }
}

pub(super) fn remove_unused_definitions<'tcx>(body: &mut Body<'tcx>) {
    // First, we're going to get a count of *actual* uses for every `Local`.
    let mut used_locals = UsedLocals::new(body);

    // Next, we're going to remove any `Local` with zero actual uses. When we remove those
    // `Locals`, we're also going to subtract any uses of other `Locals` from the `used_locals`
    // count. For example, if we removed `_2 = discriminant(_1)`, then we'll subtract one from
    // `use_counts[_1]`. That in turn might make `_1` unused, so we loop until we hit a
    // fixedpoint where there are no more unused locals.
    remove_unused_definitions_helper(&mut used_locals, body);
}

/// Construct the mapping while swapping out unused stuff out from the `vec`.
fn make_local_map<V>(
    local_decls: &mut IndexVec<Local, V>,
    used_locals: &UsedLocals,
) -> IndexVec<Local, Option<Local>> {
    let mut map: IndexVec<Local, Option<Local>> = IndexVec::from_elem(None, local_decls);
    let mut used = Local::ZERO;

    for alive_index in local_decls.indices() {
        // `is_used` treats the `RETURN_PLACE` and arguments as used.
        if !used_locals.is_used(alive_index) {
            continue;
        }

        map[alive_index] = Some(used);
        if alive_index != used {
            local_decls.swap(alive_index, used);
        }
        used.increment_by(1);
    }
    local_decls.truncate(used.index());
    map
}

/// Keeps track of used & unused locals.
struct UsedLocals {
    increment: bool,
    use_count: IndexVec<Local, u32>,
    always_used: DenseBitSet<Local>,
}

impl UsedLocals {
    /// Determines which locals are used & unused in the given body.
    fn new(body: &Body<'_>) -> Self {
        let mut always_used = debuginfo_locals(body);
        always_used.insert(RETURN_PLACE);
        for arg in body.args_iter() {
            always_used.insert(arg);
        }
        let mut this = Self {
            increment: true,
            use_count: IndexVec::from_elem(0, &body.local_decls),
            always_used,
        };
        this.visit_body(body);
        this
    }

    /// Checks if local is used.
    ///
    /// Return place, arguments, var debuginfo are always considered used.
    fn is_used(&self, local: Local) -> bool {
        trace!(
            "is_used({:?}): use_count: {:?}, always_used: {}",
            local,
            self.use_count[local],
            self.always_used.contains(local)
        );
        // To keep things simple, we don't handle debugging information here, these are in DSE.
        self.always_used.contains(local) || self.use_count[local] != 0
    }

    /// Updates the use counts to reflect the removal of given statement.
    fn statement_removed(&mut self, statement: &Statement<'_>) {
        self.increment = false;

        // The location of the statement is irrelevant.
        let location = Location::START;
        self.visit_statement(statement, location);
    }

    /// Visits a left-hand side of an assignment.
    fn visit_lhs(&mut self, place: &Place<'_>, location: Location) {
        if place.is_indirect() {
            // A use, not a definition.
            self.visit_place(place, PlaceContext::MutatingUse(MutatingUseContext::Store), location);
        } else {
            // A definition. The base local itself is not visited, so this occurrence is not counted
            // toward its use count. There might be other locals still, used in an indexing
            // projection.
            self.super_projection(
                place.as_ref(),
                PlaceContext::MutatingUse(MutatingUseContext::Projection),
                location,
            );
        }
    }
}

impl<'tcx> Visitor<'tcx> for UsedLocals {
    fn visit_statement(&mut self, statement: &Statement<'tcx>, location: Location) {
        match statement.kind {
            StatementKind::Intrinsic(..)
            | StatementKind::Retag(..)
            | StatementKind::Coverage(..)
            | StatementKind::FakeRead(..)
            | StatementKind::PlaceMention(..)
            | StatementKind::AscribeUserType(..) => {
                self.super_statement(statement, location);
            }

            StatementKind::ConstEvalCounter
            | StatementKind::Nop
            | StatementKind::StorageLive(..)
            | StatementKind::StorageDead(..) => {}
            StatementKind::Assign(box (ref place, ref rvalue)) => {
                if rvalue.is_safe_to_remove() {
                    self.visit_lhs(place, location);
                    self.visit_rvalue(rvalue, location);
                } else {
                    self.super_statement(statement, location);
                }
            }

            StatementKind::SetDiscriminant { ref place, variant_index: _ }
            | StatementKind::BackwardIncompatibleDropHint { ref place, reason: _ } => {
                self.visit_lhs(place, location);
            }
        }
    }

    fn visit_local(&mut self, local: Local, ctx: PlaceContext, _location: Location) {
        if matches!(ctx, PlaceContext::NonUse(_)) {
            return;
        }
        if self.increment {
            self.use_count[local] += 1;
        } else {
            assert_ne!(self.use_count[local], 0);
            self.use_count[local] -= 1;
        }
    }
}

/// Removes unused definitions. Updates the used locals to reflect the changes made.
fn remove_unused_definitions_helper(used_locals: &mut UsedLocals, body: &mut Body<'_>) {
    // The use counts are updated as we remove the statements. A local might become unused
    // during the retain operation, leading to a temporary inconsistency (storage statements or
    // definitions referencing the local might remain). For correctness it is crucial that this
    // computation reaches a fixed point.

    let mut modified = true;
    while modified {
        modified = false;

        for data in body.basic_blocks.as_mut_preserves_cfg() {
            // Remove unnecessary StorageLive and StorageDead annotations.
            for statement in data.statements.iter_mut() {
                let keep_statement = match &statement.kind {
                    StatementKind::StorageLive(local) | StatementKind::StorageDead(local) => {
                        used_locals.is_used(*local)
                    }
                    StatementKind::Assign(box (place, _))
                    | StatementKind::SetDiscriminant { box place, .. }
                    | StatementKind::BackwardIncompatibleDropHint { box place, .. } => {
                        used_locals.is_used(place.local)
                    }
                    _ => continue,
                };
                if keep_statement {
                    continue;
                }
                trace!("removing statement {:?}", statement);
                modified = true;
                used_locals.statement_removed(statement);
                statement.make_nop(true);
            }
            data.strip_nops();
        }
    }
}

struct LocalUpdater<'tcx> {
    map: IndexVec<Local, Option<Local>>,
    tcx: TyCtxt<'tcx>,
}

impl<'tcx> MutVisitor<'tcx> for LocalUpdater<'tcx> {
    fn tcx(&self) -> TyCtxt<'tcx> {
        self.tcx
    }

    fn visit_statement_debuginfo(
        &mut self,
        stmt_debuginfo: &mut StmtDebugInfo<'tcx>,
        location: Location,
    ) {
        match stmt_debuginfo {
            StmtDebugInfo::AssignRef(local, place) => {
                if place.as_ref().accessed_locals().any(|local| self.map[local].is_none()) {
                    *stmt_debuginfo = StmtDebugInfo::InvalidAssign(*local);
                }
            }
            StmtDebugInfo::InvalidAssign(_) => {}
        }
        self.super_statement_debuginfo(stmt_debuginfo, location);
    }

    fn visit_local(&mut self, l: &mut Local, _: PlaceContext, _: Location) {
        *l = self.map[*l].unwrap();
    }
}

pub(crate) struct UsedInStmtLocals {
    pub(crate) locals: DenseBitSet<Local>,
}

impl UsedInStmtLocals {
    pub(crate) fn new(body: &Body<'_>) -> Self {
        let mut this = Self { locals: DenseBitSet::new_empty(body.local_decls.len()) };
        this.visit_body(body);
        this
    }

    pub(crate) fn remove_unused_storage_annotations<'tcx>(&self, body: &mut Body<'tcx>) {
        for data in body.basic_blocks.as_mut_preserves_cfg() {
            // Remove unnecessary StorageLive and StorageDead annotations.
            for statement in data.statements.iter_mut() {
                let keep_statement = match &statement.kind {
                    StatementKind::StorageLive(local) | StatementKind::StorageDead(local) => {
                        self.locals.contains(*local)
                    }
                    _ => continue,
                };
                if keep_statement {
                    continue;
                }
                statement.make_nop(true);
            }
        }
    }
}

impl<'tcx> Visitor<'tcx> for UsedInStmtLocals {
    fn visit_local(&mut self, local: Local, context: PlaceContext, _: Location) {
        if matches!(context, PlaceContext::NonUse(_)) {
            return;
        }
        self.locals.insert(local);
    }
}
