Skip to content

Commit

Permalink
Rollup merge of rust-lang#51323 - nikic:switch-int-lowering, r=nagisa
Browse files Browse the repository at this point in the history
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 (rust-lang#4353).
  • Loading branch information
Mark-Simulacrum authored Jun 4, 2018
2 parents 79dd148 + 4f4f7df commit e7ae1b2
Showing 1 changed file with 14 additions and 5 deletions.
19 changes: 14 additions & 5 deletions src/librustc_codegen_llvm/mir/block.rs
Original file line number Diff line number Diff line change
Expand Up @@ -191,14 +191,23 @@ impl<'a, 'tcx> FunctionCx<'a, 'tcx> {

mir::TerminatorKind::SwitchInt { ref discr, switch_ty, ref values, ref targets } => {
let discr = self.codegen_operand(&bx, discr);
if switch_ty == bx.tcx().types.bool {
if targets.len() == 2 {
// If there are two targets, emit br instead of switch
let lltrue = llblock(self, targets[0]);
let llfalse = llblock(self, targets[1]);
if let [0] = values[..] {
bx.cond_br(discr.immediate(), llfalse, lltrue);
if switch_ty == bx.tcx().types.bool {
// Don't generate trivial icmps when switching on bool
if let [0] = values[..] {
bx.cond_br(discr.immediate(), llfalse, lltrue);
} else {
assert_eq!(&values[..], &[1]);
bx.cond_br(discr.immediate(), lltrue, llfalse);
}
} else {
assert_eq!(&values[..], &[1]);
bx.cond_br(discr.immediate(), lltrue, llfalse);
let switch_llty = bx.cx.layout_of(switch_ty).immediate_llvm_type(bx.cx);
let llval = C_uint_big(switch_llty, values[0]);
let cmp = bx.icmp(llvm::IntEQ, discr.immediate(), llval);
bx.cond_br(cmp, lltrue, llfalse);
}
} else {
let (otherwise, targets) = targets.split_last().unwrap();
Expand Down

0 comments on commit e7ae1b2

Please sign in to comment.