rustc_mir_transform/
multiple_return_terminators.rs

1//! This pass removes jumps to basic blocks containing only a return, and replaces them with a
2//! return instead.
3
4use rustc_index::bit_set::DenseBitSet;
5use rustc_middle::mir::*;
6use rustc_middle::ty::TyCtxt;
7
8use crate::simplify;
9
10pub(super) struct MultipleReturnTerminators;
11
12impl<'tcx> crate::MirPass<'tcx> for MultipleReturnTerminators {
13    fn is_enabled(&self, sess: &rustc_session::Session) -> bool {
14        sess.mir_opt_level() >= 4
15    }
16
17    fn run_pass(&self, _: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
18        // find basic blocks with no statement and a return terminator
19        let mut bbs_simple_returns = DenseBitSet::new_empty(body.basic_blocks.len());
20        let bbs = body.basic_blocks_mut();
21        for idx in bbs.indices() {
22            if bbs[idx].statements.is_empty()
23                && bbs[idx].terminator().kind == TerminatorKind::Return
24            {
25                bbs_simple_returns.insert(idx);
26            }
27        }
28
29        for bb in bbs {
30            if let TerminatorKind::Goto { target } = bb.terminator().kind {
31                if bbs_simple_returns.contains(target) {
32                    bb.terminator_mut().kind = TerminatorKind::Return;
33                }
34            }
35        }
36
37        simplify::remove_dead_blocks(body)
38    }
39
40    fn is_required(&self) -> bool {
41        false
42    }
43}