]> git.proxmox.com Git - rustc.git/blob - compiler/rustc_mir/src/transform/simplify_branches.rs
New upstream version 1.48.0~beta.8+dfsg1
[rustc.git] / compiler / rustc_mir / src / 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_middle::mir::*;
5 use rustc_middle::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 Body<'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::FalseEdge { 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 }