diff options
Diffstat (limited to 'compiler/rustc_mir_transform/src/simplify_branches.rs')
| -rw-r--r-- | compiler/rustc_mir_transform/src/simplify_branches.rs | 66 | 
1 files changed, 66 insertions, 0 deletions
| diff --git a/compiler/rustc_mir_transform/src/simplify_branches.rs b/compiler/rustc_mir_transform/src/simplify_branches.rs new file mode 100644 index 00000000000..df90cfa318d --- /dev/null +++ b/compiler/rustc_mir_transform/src/simplify_branches.rs @@ -0,0 +1,66 @@ +//! A pass that simplifies branches when their condition is known. + +use crate::MirPass; +use rustc_middle::mir::*; +use rustc_middle::ty::TyCtxt; + +use std::borrow::Cow; + +pub struct SimplifyBranches { + label: String, +} + +impl SimplifyBranches { + pub fn new(label: &str) -> Self { + SimplifyBranches { label: format!("SimplifyBranches-{}", label) } + } +} + +impl<'tcx> MirPass<'tcx> for SimplifyBranches { + fn name(&self) -> Cow<'_, str> { + Cow::Borrowed(&self.label) + } + + fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { + let param_env = tcx.param_env(body.source.def_id()); + for block in body.basic_blocks_mut() { + let terminator = block.terminator_mut(); + terminator.kind = match terminator.kind { + TerminatorKind::SwitchInt { + discr: Operand::Constant(ref c), + switch_ty, + ref targets, + .. + } => { + let constant = c.literal.try_eval_bits(tcx, param_env, switch_ty); + if let Some(constant) = constant { + let otherwise = targets.otherwise(); + let mut ret = TerminatorKind::Goto { target: otherwise }; + for (v, t) in targets.iter() { + if v == constant { + ret = TerminatorKind::Goto { target: t }; + break; + } + } + ret + } else { + continue; + } + } + TerminatorKind::Assert { + target, cond: Operand::Constant(ref c), expected, .. + } => match c.literal.try_eval_bool(tcx, param_env) { + Some(v) if v == expected => TerminatorKind::Goto { target }, + _ => continue, + }, + TerminatorKind::FalseEdge { real_target, .. } => { + TerminatorKind::Goto { target: real_target } + } + TerminatorKind::FalseUnwind { real_target, .. } => { + TerminatorKind::Goto { target: real_target } + } + _ => continue, + }; + } + } +} | 
