]> git.proxmox.com Git - rustc.git/blob - src/librustc_mir/transform/simplify_branches.rs
New upstream version 1.17.0+dfsg1
[rustc.git] / src / librustc_mir / transform / simplify_branches.rs
1 // Copyright 2016 The Rust Project Developers. See the COPYRIGHT
2 // file at the top-level directory of this distribution and at
3 // http://rust-lang.org/COPYRIGHT.
4 //
5 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8 // option. This file may not be copied, modified, or distributed
9 // except according to those terms.
10
11 //! A pass that simplifies branches when their condition is known.
12
13 use rustc::ty::TyCtxt;
14 use rustc::middle::const_val::ConstVal;
15 use rustc::mir::transform::{MirPass, MirSource, Pass};
16 use rustc::mir::*;
17
18 use std::fmt;
19
20 pub struct SimplifyBranches<'a> { label: &'a str }
21
22 impl<'a> SimplifyBranches<'a> {
23 pub fn new(label: &'a str) -> Self {
24 SimplifyBranches { label: label }
25 }
26 }
27
28 impl<'l, 'tcx> MirPass<'tcx> for SimplifyBranches<'l> {
29 fn run_pass<'a>(&mut self, _tcx: TyCtxt<'a, 'tcx, 'tcx>, _src: MirSource, mir: &mut Mir<'tcx>) {
30 for block in mir.basic_blocks_mut() {
31 let terminator = block.terminator_mut();
32 terminator.kind = match terminator.kind {
33 TerminatorKind::SwitchInt { discr: Operand::Constant(Constant {
34 literal: Literal::Value { ref value }, ..
35 }), ref values, ref targets, .. } => {
36 if let Some(ref constint) = value.to_const_int() {
37 let (otherwise, targets) = targets.split_last().unwrap();
38 let mut ret = TerminatorKind::Goto { target: *otherwise };
39 for (v, t) in values.iter().zip(targets.iter()) {
40 if v == constint {
41 ret = TerminatorKind::Goto { target: *t };
42 break;
43 }
44 }
45 ret
46 } else {
47 continue
48 }
49 },
50 TerminatorKind::Assert { target, cond: Operand::Constant(Constant {
51 literal: Literal::Value {
52 value: ConstVal::Bool(cond)
53 }, ..
54 }), expected, .. } if cond == expected => {
55 TerminatorKind::Goto { target: target }
56 },
57 _ => continue
58 };
59 }
60 }
61 }
62
63 impl<'l> Pass for SimplifyBranches<'l> {
64 fn disambiguator<'a>(&'a self) -> Option<Box<fmt::Display+'a>> {
65 Some(Box::new(self.label))
66 }
67
68 // avoid calling `type_name` - it contains `<'static>`
69 fn name(&self) -> ::std::borrow::Cow<'static, str> { "SimplifyBranches".into() }
70 }