1 use crate::MirPass; 2 use rustc_middle::mir::*; 3 use rustc_middle::ty::TyCtxt; 4 5 pub enum SimplifyConstCondition { 6 AfterConstProp, 7 Final, 8 } 9 /// A pass that replaces a branch with a goto when its condition is known. 10 impl<'tcx> MirPass<'tcx> for SimplifyConstCondition { name(&self) -> &'static str11 fn name(&self) -> &'static str { 12 match self { 13 SimplifyConstCondition::AfterConstProp => "SimplifyConstCondition-after-const-prop", 14 SimplifyConstCondition::Final => "SimplifyConstCondition-final", 15 } 16 } 17 run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>)18 fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { 19 let param_env = tcx.param_env_reveal_all_normalized(body.source.def_id()); 20 for block in body.basic_blocks_mut() { 21 let terminator = block.terminator_mut(); 22 terminator.kind = match terminator.kind { 23 TerminatorKind::SwitchInt { 24 discr: Operand::Constant(ref c), ref targets, .. 25 } => { 26 let constant = c.literal.try_eval_bits(tcx, param_env, c.ty()); 27 if let Some(constant) = constant { 28 let target = targets.target_for_value(constant); 29 TerminatorKind::Goto { target } 30 } else { 31 continue; 32 } 33 } 34 TerminatorKind::Assert { 35 target, cond: Operand::Constant(ref c), expected, .. 36 } => match c.literal.try_eval_bool(tcx, param_env) { 37 Some(v) if v == expected => TerminatorKind::Goto { target }, 38 _ => continue, 39 }, 40 _ => continue, 41 }; 42 } 43 } 44 } 45