Skip to content

Commit 2a628bd

Browse files
committed
Remove duplicate switch targets
1 parent 41eda69 commit 2a628bd

File tree

3 files changed

+63
-1
lines changed

3 files changed

+63
-1
lines changed

compiler/rustc_mir_transform/src/instcombine.rs

+15-1
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ use crate::MirPass;
44
use rustc_hir::Mutability;
55
use rustc_middle::mir::{
66
BinOp, Body, Constant, ConstantKind, LocalDecls, Operand, Place, ProjectionElem, Rvalue,
7-
SourceInfo, Statement, StatementKind, Terminator, TerminatorKind, UnOp,
7+
SourceInfo, Statement, StatementKind, SwitchTargets, Terminator, TerminatorKind, UnOp,
88
};
99
use rustc_middle::ty::layout::ValidityRequirement;
1010
use rustc_middle::ty::{self, ParamEnv, SubstsRef, Ty, TyCtxt};
@@ -44,6 +44,7 @@ impl<'tcx> MirPass<'tcx> for InstCombine {
4444
&mut block.terminator.as_mut().unwrap(),
4545
&mut block.statements,
4646
);
47+
ctx.combine_duplicate_switch_targets(&mut block.terminator.as_mut().unwrap());
4748
}
4849
}
4950
}
@@ -217,6 +218,19 @@ impl<'tcx> InstCombineContext<'tcx, '_> {
217218
terminator.kind = TerminatorKind::Goto { target: destination_block };
218219
}
219220

221+
fn combine_duplicate_switch_targets(&self, terminator: &mut Terminator<'tcx>) {
222+
let TerminatorKind::SwitchInt { targets, .. } = &mut terminator.kind
223+
else { return };
224+
225+
let otherwise = targets.otherwise();
226+
if targets.iter().any(|t| t.1 == otherwise) {
227+
*targets = SwitchTargets::new(
228+
targets.iter().filter(|t| t.1 != otherwise),
229+
targets.otherwise(),
230+
);
231+
}
232+
}
233+
220234
fn combine_intrinsic_assert(
221235
&self,
222236
terminator: &mut Terminator<'tcx>,
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
- // MIR for `assert_zero` before InstCombine
2+
+ // MIR for `assert_zero` after InstCombine
3+
4+
fn assert_zero(_1: u8) -> u8 {
5+
let mut _0: u8; // return place in scope 0 at $DIR/instcombine_duplicate_switch_targets.rs:+0:37: +0:39
6+
7+
bb0: {
8+
- switchInt(_1) -> [0: bb2, 1: bb1, otherwise: bb1]; // scope 0 at $DIR/instcombine_duplicate_switch_targets.rs:+3:13: +7:14
9+
+ switchInt(_1) -> [0: bb2, otherwise: bb1]; // scope 0 at $DIR/instcombine_duplicate_switch_targets.rs:+3:13: +7:14
10+
}
11+
12+
bb1: {
13+
unreachable; // scope 0 at $DIR/instcombine_duplicate_switch_targets.rs:+10:13: +10:26
14+
}
15+
16+
bb2: {
17+
_0 = _1; // scope 0 at $DIR/instcombine_duplicate_switch_targets.rs:+13:13: +13:20
18+
return; // scope 0 at $DIR/instcombine_duplicate_switch_targets.rs:+14:13: +14:21
19+
}
20+
}
21+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
#![feature(custom_mir, core_intrinsics)]
2+
#![crate_type = "lib"]
3+
4+
use std::intrinsics::mir::*;
5+
6+
// unit-test: InstCombine
7+
8+
// EMIT_MIR instcombine_duplicate_switch_targets.assert_zero.InstCombine.diff
9+
#[custom_mir(dialect = "runtime", phase = "post-cleanup")]
10+
pub unsafe fn assert_zero(x: u8) -> u8 {
11+
mir!(
12+
{
13+
match x {
14+
0 => retblock,
15+
1 => unreachable,
16+
_ => unreachable,
17+
}
18+
}
19+
unreachable = {
20+
Unreachable()
21+
}
22+
retblock = {
23+
RET = x;
24+
Return()
25+
}
26+
)
27+
}

0 commit comments

Comments
 (0)