diff options
| author | Mark Simulacrum <mark.simulacrum@gmail.com> | 2018-06-03 18:18:05 -0600 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2018-06-03 18:18:05 -0600 |
| commit | e7ae1b26481664e1cc4b920dba9e59cedb8bd692 (patch) | |
| tree | dc5b4257a6a733735fa31c4a125d7b01bcfa3fa1 | |
| parent | 79dd148458ba2e4756fcd86c8e48afbb29ece15d (diff) | |
| parent | 4f4f7dfc00d69b8a94638ed1d9e666ada9911217 (diff) | |
| download | rust-e7ae1b26481664e1cc4b920dba9e59cedb8bd692.tar.gz rust-e7ae1b26481664e1cc4b920dba9e59cedb8bd692.zip | |
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).
| -rw-r--r-- | src/librustc_codegen_llvm/mir/block.rs | 19 |
1 files changed, 14 insertions, 5 deletions
diff --git a/src/librustc_codegen_llvm/mir/block.rs b/src/librustc_codegen_llvm/mir/block.rs index 1669059a760..14d20b6dbe2 100644 --- a/src/librustc_codegen_llvm/mir/block.rs +++ b/src/librustc_codegen_llvm/mir/block.rs @@ -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(); |
