Skip to content

Commit e7ae1b2

Browse files
Rollup merge of #51323 - nikic:switch-int-lowering, r=nagisa
Generate br for all two target SwitchInts Instead of only for booleans. This means that `if let` also becomes a br. Apart from making the IR slightly simpler, this is supported by FastISel (#4353).
2 parents 79dd148 + 4f4f7df commit e7ae1b2

File tree

1 file changed

+14
-5
lines changed

1 file changed

+14
-5
lines changed

src/librustc_codegen_llvm/mir/block.rs

+14-5
Original file line numberDiff line numberDiff line change
@@ -191,14 +191,23 @@ impl<'a, 'tcx> FunctionCx<'a, 'tcx> {
191191

192192
mir::TerminatorKind::SwitchInt { ref discr, switch_ty, ref values, ref targets } => {
193193
let discr = self.codegen_operand(&bx, discr);
194-
if switch_ty == bx.tcx().types.bool {
194+
if targets.len() == 2 {
195+
// If there are two targets, emit br instead of switch
195196
let lltrue = llblock(self, targets[0]);
196197
let llfalse = llblock(self, targets[1]);
197-
if let [0] = values[..] {
198-
bx.cond_br(discr.immediate(), llfalse, lltrue);
198+
if switch_ty == bx.tcx().types.bool {
199+
// Don't generate trivial icmps when switching on bool
200+
if let [0] = values[..] {
201+
bx.cond_br(discr.immediate(), llfalse, lltrue);
202+
} else {
203+
assert_eq!(&values[..], &[1]);
204+
bx.cond_br(discr.immediate(), lltrue, llfalse);
205+
}
199206
} else {
200-
assert_eq!(&values[..], &[1]);
201-
bx.cond_br(discr.immediate(), lltrue, llfalse);
207+
let switch_llty = bx.cx.layout_of(switch_ty).immediate_llvm_type(bx.cx);
208+
let llval = C_uint_big(switch_llty, values[0]);
209+
let cmp = bx.icmp(llvm::IntEQ, discr.immediate(), llval);
210+
bx.cond_br(cmp, lltrue, llfalse);
202211
}
203212
} else {
204213
let (otherwise, targets) = targets.split_last().unwrap();

0 commit comments

Comments
 (0)