]> git.lizzy.rs Git - rust.git/blob - src/librustc_mir/transform/simplify_branches.rs
Auto merge of #68343 - matthiaskrgr:submodule_upd, r=oli-obk
[rust.git] / src / librustc_mir / transform / simplify_branches.rs
1 //! A pass that simplifies branches when their condition is known.
2
3 use crate::transform::{MirPass, MirSource};
4 use rustc::mir::*;
5 use rustc::ty::TyCtxt;
6
7 use std::borrow::Cow;
8
9 pub struct SimplifyBranches {
10     label: String,
11 }
12
13 impl SimplifyBranches {
14     pub fn new(label: &str) -> Self {
15         SimplifyBranches { label: format!("SimplifyBranches-{}", label) }
16     }
17 }
18
19 impl<'tcx> MirPass<'tcx> for SimplifyBranches {
20     fn name(&self) -> Cow<'_, str> {
21         Cow::Borrowed(&self.label)
22     }
23
24     fn run_pass(&self, tcx: TyCtxt<'tcx>, src: MirSource<'tcx>, body: &mut BodyAndCache<'tcx>) {
25         let param_env = tcx.param_env(src.def_id());
26         for block in body.basic_blocks_mut() {
27             let terminator = block.terminator_mut();
28             terminator.kind = match terminator.kind {
29                 TerminatorKind::SwitchInt {
30                     discr: Operand::Constant(ref c),
31                     switch_ty,
32                     ref values,
33                     ref targets,
34                     ..
35                 } => {
36                     let constant = c.literal.try_eval_bits(tcx, param_env, switch_ty);
37                     if let Some(constant) = constant {
38                         let (otherwise, targets) = targets.split_last().unwrap();
39                         let mut ret = TerminatorKind::Goto { target: *otherwise };
40                         for (&v, t) in values.iter().zip(targets.iter()) {
41                             if v == constant {
42                                 ret = TerminatorKind::Goto { target: *t };
43                                 break;
44                             }
45                         }
46                         ret
47                     } else {
48                         continue;
49                     }
50                 }
51                 TerminatorKind::Assert {
52                     target, cond: Operand::Constant(ref c), expected, ..
53                 } if (c.literal.try_eval_bool(tcx, param_env) == Some(true)) == expected => {
54                     TerminatorKind::Goto { target }
55                 }
56                 TerminatorKind::FalseEdges { real_target, .. } => {
57                     TerminatorKind::Goto { target: real_target }
58                 }
59                 TerminatorKind::FalseUnwind { real_target, .. } => {
60                     TerminatorKind::Goto { target: real_target }
61                 }
62                 _ => continue,
63             };
64         }
65     }
66 }