summaryrefslogtreecommitdiffstats
path: root/compiler/rustc_mir_transform/src/simplify_branches.rs
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/rustc_mir_transform/src/simplify_branches.rs')
-rw-r--r--compiler/rustc_mir_transform/src/simplify_branches.rs52
1 files changed, 52 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 000000000..3bbae5b89
--- /dev/null
+++ b/compiler/rustc_mir_transform/src/simplify_branches.rs
@@ -0,0 +1,52 @@
+use crate::MirPass;
+use rustc_middle::mir::*;
+use rustc_middle::ty::TyCtxt;
+
+use std::borrow::Cow;
+
+/// A pass that replaces a branch with a goto when its condition is known.
+pub struct SimplifyConstCondition {
+ label: String,
+}
+
+impl SimplifyConstCondition {
+ pub fn new(label: &str) -> Self {
+ SimplifyConstCondition { label: format!("SimplifyConstCondition-{}", label) }
+ }
+}
+
+impl<'tcx> MirPass<'tcx> for SimplifyConstCondition {
+ 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 target = targets.target_for_value(constant);
+ TerminatorKind::Goto { target }
+ } 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,
+ },
+ _ => continue,
+ };
+ }
+ }
+}