Skip to content

Commit

Permalink
Remove duplicate switch targets
Browse files Browse the repository at this point in the history
  • Loading branch information
saethlin committed Mar 18, 2023
1 parent 41eda69 commit 2a628bd
Show file tree
Hide file tree
Showing 3 changed files with 63 additions and 1 deletion.
16 changes: 15 additions & 1 deletion compiler/rustc_mir_transform/src/instcombine.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ use crate::MirPass;
use rustc_hir::Mutability;
use rustc_middle::mir::{
BinOp, Body, Constant, ConstantKind, LocalDecls, Operand, Place, ProjectionElem, Rvalue,
SourceInfo, Statement, StatementKind, Terminator, TerminatorKind, UnOp,
SourceInfo, Statement, StatementKind, SwitchTargets, Terminator, TerminatorKind, UnOp,
};
use rustc_middle::ty::layout::ValidityRequirement;
use rustc_middle::ty::{self, ParamEnv, SubstsRef, Ty, TyCtxt};
Expand Down Expand Up @@ -44,6 +44,7 @@ impl<'tcx> MirPass<'tcx> for InstCombine {
&mut block.terminator.as_mut().unwrap(),
&mut block.statements,
);
ctx.combine_duplicate_switch_targets(&mut block.terminator.as_mut().unwrap());
}
}
}
Expand Down Expand Up @@ -217,6 +218,19 @@ impl<'tcx> InstCombineContext<'tcx, '_> {
terminator.kind = TerminatorKind::Goto { target: destination_block };
}

fn combine_duplicate_switch_targets(&self, terminator: &mut Terminator<'tcx>) {
let TerminatorKind::SwitchInt { targets, .. } = &mut terminator.kind
else { return };

let otherwise = targets.otherwise();
if targets.iter().any(|t| t.1 == otherwise) {
*targets = SwitchTargets::new(
targets.iter().filter(|t| t.1 != otherwise),
targets.otherwise(),
);
}
}

fn combine_intrinsic_assert(
&self,
terminator: &mut Terminator<'tcx>,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
- // MIR for `assert_zero` before InstCombine
+ // MIR for `assert_zero` after InstCombine

fn assert_zero(_1: u8) -> u8 {
let mut _0: u8; // return place in scope 0 at $DIR/instcombine_duplicate_switch_targets.rs:+0:37: +0:39

bb0: {
- switchInt(_1) -> [0: bb2, 1: bb1, otherwise: bb1]; // scope 0 at $DIR/instcombine_duplicate_switch_targets.rs:+3:13: +7:14
+ switchInt(_1) -> [0: bb2, otherwise: bb1]; // scope 0 at $DIR/instcombine_duplicate_switch_targets.rs:+3:13: +7:14
}

bb1: {
unreachable; // scope 0 at $DIR/instcombine_duplicate_switch_targets.rs:+10:13: +10:26
}

bb2: {
_0 = _1; // scope 0 at $DIR/instcombine_duplicate_switch_targets.rs:+13:13: +13:20
return; // scope 0 at $DIR/instcombine_duplicate_switch_targets.rs:+14:13: +14:21
}
}

27 changes: 27 additions & 0 deletions tests/mir-opt/instcombine_duplicate_switch_targets.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
#![feature(custom_mir, core_intrinsics)]
#![crate_type = "lib"]

use std::intrinsics::mir::*;

// unit-test: InstCombine

// EMIT_MIR instcombine_duplicate_switch_targets.assert_zero.InstCombine.diff
#[custom_mir(dialect = "runtime", phase = "post-cleanup")]
pub unsafe fn assert_zero(x: u8) -> u8 {
mir!(
{
match x {
0 => retblock,
1 => unreachable,
_ => unreachable,
}
}
unreachable = {
Unreachable()
}
retblock = {
RET = x;
Return()
}
)
}

0 comments on commit 2a628bd

Please sign in to comment.