rustc_mir_transform/
simplify_branches.rs
1use rustc_middle::mir::*;
2use rustc_middle::ty::TyCtxt;
3use tracing::trace;
4
5pub(super) enum SimplifyConstCondition {
6 AfterConstProp,
7 Final,
8}
9
10impl<'tcx> crate::MirPass<'tcx> for SimplifyConstCondition {
12 fn name(&self) -> &'static str {
13 match self {
14 SimplifyConstCondition::AfterConstProp => "SimplifyConstCondition-after-const-prop",
15 SimplifyConstCondition::Final => "SimplifyConstCondition-final",
16 }
17 }
18
19 fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
20 trace!("Running SimplifyConstCondition on {:?}", body.source);
21 let typing_env = body.typing_env(tcx);
22 'blocks: for block in body.basic_blocks_mut() {
23 for stmt in block.statements.iter_mut() {
24 if let StatementKind::Intrinsic(box ref intrinsic) = stmt.kind
26 && let NonDivergingIntrinsic::Assume(discr) = intrinsic
27 && let Operand::Constant(ref c) = discr
28 && let Some(constant) = c.const_.try_eval_bool(tcx, typing_env)
29 {
30 if constant {
31 stmt.make_nop();
32 } else {
33 block.statements.clear();
34 block.terminator_mut().kind = TerminatorKind::Unreachable;
35 continue 'blocks;
36 }
37 }
38 }
39
40 let terminator = block.terminator_mut();
41 terminator.kind = match terminator.kind {
42 TerminatorKind::SwitchInt {
43 discr: Operand::Constant(ref c), ref targets, ..
44 } => {
45 let constant = c.const_.try_eval_bits(tcx, typing_env);
46 if let Some(constant) = constant {
47 let target = targets.target_for_value(constant);
48 TerminatorKind::Goto { target }
49 } else {
50 continue;
51 }
52 }
53 TerminatorKind::Assert {
54 target, cond: Operand::Constant(ref c), expected, ..
55 } => match c.const_.try_eval_bool(tcx, typing_env) {
56 Some(v) if v == expected => TerminatorKind::Goto { target },
57 _ => continue,
58 },
59 _ => continue,
60 };
61 }
62 }
63
64 fn is_required(&self) -> bool {
65 false
66 }
67}